From 9edea5d6139a4bfd6efce79b0eab7562a42b804d Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Sat, 16 Jan 2021 03:50:53 -0800 Subject: [PATCH 001/297] Capture the current state of the emscripten musl fork This snapshot was taken from emscripten 2.0.12 which was based on musl v1.1.15. --- arch/emscripten/atomic_arch.h | 113 +++++++ arch/emscripten/bits/alltypes.h | 421 ++++++++++++++++++++++++ arch/emscripten/bits/alltypes.h.in | 25 ++ arch/emscripten/bits/endian.h | 1 + arch/emscripten/bits/errno.h | 144 ++++++++ arch/emscripten/bits/fcntl.h | 40 +++ arch/emscripten/bits/fenv.h | 27 ++ arch/emscripten/bits/float.h | 17 + arch/emscripten/bits/io.h | 0 arch/emscripten/bits/ioctl.h | 197 +++++++++++ arch/emscripten/bits/ipc.h | 14 + arch/emscripten/bits/limits.h | 8 + arch/emscripten/bits/mman.h | 62 ++++ arch/emscripten/bits/msg.h | 16 + arch/emscripten/bits/poll.h | 0 arch/emscripten/bits/posix.h | 2 + arch/emscripten/bits/reg.h | 19 ++ arch/emscripten/bits/resource.h | 2 + arch/emscripten/bits/sem.h | 11 + arch/emscripten/bits/setjmp.h | 1 + arch/emscripten/bits/shm.h | 18 + arch/emscripten/bits/signal.h | 123 +++++++ arch/emscripten/bits/socket.h | 17 + arch/emscripten/bits/stat.h | 22 ++ arch/emscripten/bits/statfs.h | 7 + arch/emscripten/bits/stdarg.h | 4 + arch/emscripten/bits/stdint.h | 20 ++ arch/emscripten/bits/syscall.h | 226 +++++++++++++ arch/emscripten/bits/syscall.h.in | 115 +++++++ arch/emscripten/bits/termios.h | 160 +++++++++ arch/emscripten/bits/update_syscall.sh | 7 + arch/emscripten/bits/user.h | 48 +++ arch/emscripten/crt_arch.h | 0 arch/emscripten/pthread_arch.h | 5 + arch/emscripten/syscall_arch.h | 149 +++++++++ configure | 5 +- include/assert.h | 3 + include/fcntl.h | 10 + include/features.h | 3 + include/pthread.h | 7 + include/setjmp.h | 5 + include/stdio.h | 10 + include/sys/types.h | 1 - include/threads.h | 5 + include/unistd.h | 26 +- ldso/dlstart.c | 7 + ldso/dynlink.c | 7 + src/conf/sysconf.c | 90 ++--- src/dirent/opendir.c | 4 + src/env/__environ.c | 36 ++ src/errno/__errno_location.c | 13 + src/fcntl/fcntl.c | 8 + src/fcntl/open.c | 2 + src/internal/floatscan.c | 13 +- src/internal/libc.c | 7 + src/internal/libm.h | 8 + src/internal/pthread_impl.h | 30 +- src/internal/stdio_impl.h | 10 +- src/internal/syscall.h | 37 ++- src/legacy/getpagesize.c | 6 + src/linux/sbrk.c | 3 + src/locale/locale_map.c | 2 + src/locale/newlocale.c | 2 - src/math/ceil.c | 6 + src/math/ceilf.c | 6 + src/math/copysign.c | 6 + src/math/copysignf.c | 6 + src/math/fabs.c | 6 + src/math/fabsf.c | 6 + src/math/floor.c | 6 + src/math/floorf.c | 6 + src/math/fma.c | 4 + src/math/fmaf.c | 2 + src/math/fmal.c | 2 + src/math/fmax.c | 5 + src/math/fmaxf.c | 5 + src/math/fmin.c | 5 + src/math/fminf.c | 5 + src/math/ilogb.c | 2 + src/math/ilogbf.c | 2 + src/math/ilogbl.c | 4 + src/math/rint.c | 6 + src/math/rintf.c | 6 + src/math/sqrt.c | 6 + src/math/sqrtf.c | 6 + src/math/trunc.c | 6 + src/math/truncf.c | 6 + src/misc/realpath.c | 8 + src/network/if_indextoname.c | 4 + src/network/if_nametoindex.c | 4 + src/network/netlink.c | 4 + src/network/ns_parse.c | 60 ++-- src/network/res_msend.c | 4 + src/sched/sched_yield.c | 7 + src/stat/fchmod.c | 8 + src/stat/fchmodat.c | 4 + src/stat/fstat.c | 8 + src/stdio/__fdopen.c | 2 + src/stdio/__fopen_rb_ca.c | 2 + src/stdio/__lockfile.c | 4 + src/stdio/__stdio_close.c | 4 + src/stdio/__stdio_read.c | 8 + src/stdio/__stdio_seek.c | 5 + src/stdio/__stdio_write.c | 8 + src/stdio/fopen.c | 6 + src/stdio/fprintf.c | 22 ++ src/stdio/freopen.c | 2 + src/stdio/printf.c | 23 ++ src/stdio/sprintf.c | 23 ++ src/stdio/stdout.c | 21 ++ src/stdio/tmpfile.c | 4 + src/stdio/vfprintf.c | 101 +++++- src/stdio/vsnprintf.c | 55 ++++ src/stdio/vsprintf.c | 13 + src/stdio/vswprintf.c | 27 +- src/stdlib/strtod.c | 19 ++ src/string/memccpy.c | 9 +- src/string/memchr.c | 8 +- src/string/memmove.c | 10 +- src/string/stpcpy.c | 9 +- src/string/stpncpy.c | 10 +- src/string/strchrnul.c | 12 +- src/string/strlcpy.c | 6 +- src/string/strlen.c | 8 +- src/thread/__timedwait.c | 48 +++ src/thread/__wait.c | 30 ++ src/thread/pthread_atfork.c | 6 + src/thread/pthread_attr_get.c | 8 +- src/thread/pthread_barrier_wait.c | 11 +- src/thread/pthread_cond_timedwait.c | 21 ++ src/thread/pthread_getconcurrency.c | 2 + src/thread/pthread_getcpuclockid.c | 5 + src/thread/pthread_getschedparam.c | 5 + src/thread/pthread_key_create.c | 8 + src/thread/pthread_mutex_trylock.c | 2 + src/thread/pthread_rwlock_timedwrlock.c | 10 + src/thread/pthread_rwlock_trywrlock.c | 5 + src/thread/pthread_rwlock_unlock.c | 6 + src/thread/pthread_setconcurrency.c | 2 + src/thread/pthread_setschedparam.c | 5 + src/thread/pthread_setschedprio.c | 5 + src/thread/sem_timedwait.c | 3 + src/thread/thrd_create.c | 5 + src/thread/thrd_exit.c | 5 + src/thread/thrd_join.c | 5 + src/thread/thrd_sleep.c | 4 + src/thread/thrd_yield.c | 2 + src/time/__map_file.c | 4 + src/time/asctime.c | 4 +- src/time/clock_gettime.c | 14 + src/time/clock_settime.c | 9 + src/time/localtime_r.c | 3 +- src/time/nanosleep.c | 13 + src/time/strftime.c | 2 +- src/unistd/close.c | 6 + src/unistd/dup2.c | 7 + src/unistd/dup3.c | 2 + src/unistd/fchdir.c | 8 + src/unistd/fchown.c | 8 + src/unistd/fsync.c | 4 + src/unistd/isatty.c | 23 +- src/unistd/lseek.c | 5 + src/unistd/pipe2.c | 2 + src/unistd/pread.c | 12 + src/unistd/preadv.c | 8 + src/unistd/pwrite.c | 12 + src/unistd/pwritev.c | 8 + src/unistd/read.c | 12 + src/unistd/readv.c | 8 + src/unistd/setxid.c | 5 + src/unistd/usleep.c | 8 + src/unistd/write.c | 12 + src/unistd/writev.c | 9 + 173 files changed, 3323 insertions(+), 141 deletions(-) create mode 100644 arch/emscripten/atomic_arch.h create mode 100644 arch/emscripten/bits/alltypes.h create mode 100644 arch/emscripten/bits/alltypes.h.in create mode 100644 arch/emscripten/bits/endian.h create mode 100644 arch/emscripten/bits/errno.h create mode 100644 arch/emscripten/bits/fcntl.h create mode 100644 arch/emscripten/bits/fenv.h create mode 100644 arch/emscripten/bits/float.h create mode 100644 arch/emscripten/bits/io.h create mode 100644 arch/emscripten/bits/ioctl.h create mode 100644 arch/emscripten/bits/ipc.h create mode 100644 arch/emscripten/bits/limits.h create mode 100644 arch/emscripten/bits/mman.h create mode 100644 arch/emscripten/bits/msg.h create mode 100644 arch/emscripten/bits/poll.h create mode 100644 arch/emscripten/bits/posix.h create mode 100644 arch/emscripten/bits/reg.h create mode 100644 arch/emscripten/bits/resource.h create mode 100644 arch/emscripten/bits/sem.h create mode 100644 arch/emscripten/bits/setjmp.h create mode 100644 arch/emscripten/bits/shm.h create mode 100644 arch/emscripten/bits/signal.h create mode 100644 arch/emscripten/bits/socket.h create mode 100644 arch/emscripten/bits/stat.h create mode 100644 arch/emscripten/bits/statfs.h create mode 100644 arch/emscripten/bits/stdarg.h create mode 100644 arch/emscripten/bits/stdint.h create mode 100644 arch/emscripten/bits/syscall.h create mode 100644 arch/emscripten/bits/syscall.h.in create mode 100644 arch/emscripten/bits/termios.h create mode 100755 arch/emscripten/bits/update_syscall.sh create mode 100644 arch/emscripten/bits/user.h create mode 100644 arch/emscripten/crt_arch.h create mode 100644 arch/emscripten/pthread_arch.h create mode 100644 arch/emscripten/syscall_arch.h diff --git a/arch/emscripten/atomic_arch.h b/arch/emscripten/atomic_arch.h new file mode 100644 index 00000000..093edcd0 --- /dev/null +++ b/arch/emscripten/atomic_arch.h @@ -0,0 +1,113 @@ +#ifndef _INTERNAL_ATOMIC_H +#define _INTERNAL_ATOMIC_H + +#include +#include +#include + +#define a_clz_l __builtin_clz +#define a_ctz_l __builtin_ctz +#define a_clz_64 __builtin_clzll +#define a_ctz_64 __builtin_ctzll + +#define a_and_64 a_and_64 +static inline void a_and_64(volatile uint64_t *p, uint64_t v) +{ + *p &= v; +} + +#define a_or_64 a_or_64 +static inline void a_or_64(volatile uint64_t *p, uint64_t v) +{ + *p |= v; +} + +#define a_store_l a_store_l +static inline void a_store_l(volatile void *p, long x) +{ + __c11_atomic_store((_Atomic long*)p, x, __ATOMIC_SEQ_CST); +} + +#define a_or_l a_or_l +static inline void a_or_l(volatile void *p, long v) +{ + __c11_atomic_fetch_or((_Atomic long*)p, v, __ATOMIC_SEQ_CST); +} +#define a_cas_p a_cas_p +static inline void *a_cas_p(volatile void *p, void *t, void *s) +{ + void* expected = t; + __c11_atomic_compare_exchange_strong((_Atomic uintptr_t*)p, &expected, s, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return expected; +} + +#define a_cas_l a_cas_l +static inline long a_cas_l(volatile void *p, long t, long s) +{ + long expected = t; + __c11_atomic_compare_exchange_strong((_Atomic long*)p, &expected, s, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return expected; +} + +#define a_cas a_cas +static inline int a_cas(volatile int *p, int t, int s) +{ + int expected = t; + __c11_atomic_compare_exchange_strong((_Atomic int*)p, &expected, s, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return expected; +} + +#define a_or a_or +static inline void a_or(volatile void *p, int v) +{ + __c11_atomic_fetch_or((_Atomic int*)p, v, __ATOMIC_SEQ_CST); +} + +#define a_and a_and +static inline void a_and(volatile void *p, int v) +{ + __c11_atomic_fetch_and((_Atomic int*)p, v, __ATOMIC_SEQ_CST); +} + +#define a_swap a_swap +static inline int a_swap(volatile int *x, int v) +{ + return __c11_atomic_exchange((_Atomic int*)x, v, __ATOMIC_SEQ_CST); +} + +#define a_fetch_add a_fetch_add +static inline int a_fetch_add(volatile int *x, int v) +{ + return __c11_atomic_fetch_add((_Atomic int*)x, v, __ATOMIC_SEQ_CST); +} + +#define a_inc a_inc +static inline void a_inc(volatile int *x) +{ + __c11_atomic_fetch_add((_Atomic int*)x, 1, __ATOMIC_SEQ_CST); +} + +#define a_dec a_dec +static inline void a_dec(volatile int *x) +{ + __c11_atomic_fetch_sub((_Atomic int*)x, 1, __ATOMIC_SEQ_CST); +} + +#define a_store a_store +static inline void a_store(volatile int *p, int x) +{ + __c11_atomic_store((_Atomic int*)p, x, __ATOMIC_SEQ_CST); +} + +#define a_spin a_spin +static inline void a_spin() +{ +} + +#define a_crash a_crash +static inline void a_crash() +{ + EM_ASM( abort() ); +} + +#endif diff --git a/arch/emscripten/bits/alltypes.h b/arch/emscripten/bits/alltypes.h new file mode 100644 index 00000000..32c14dc5 --- /dev/null +++ b/arch/emscripten/bits/alltypes.h @@ -0,0 +1,421 @@ +#define _Addr __PTRDIFF_TYPE__ +#define _Int64 __INT64_TYPE__ +#define _Reg __PTRDIFF_TYPE__ + +#if __GNUC__ >= 3 +#if defined(__NEED_va_list) && !defined(__DEFINED_va_list) +typedef __builtin_va_list va_list; +#define __DEFINED_va_list +#endif + +#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list) +typedef __builtin_va_list __isoc_va_list; +#define __DEFINED___isoc_va_list +#endif + +#else +#if defined(__NEED_va_list) && !defined(__DEFINED_va_list) +typedef struct __va_list * va_list; +#define __DEFINED_va_list +#endif + +#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list) +typedef struct __va_list * __isoc_va_list; +#define __DEFINED___isoc_va_list +#endif + +#endif + +#ifndef __cplusplus +#ifdef __WCHAR_TYPE__ +#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t) +typedef __WCHAR_TYPE__ wchar_t; +#define __DEFINED_wchar_t +#endif + +#else +#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t) +typedef long wchar_t; +#define __DEFINED_wchar_t +#endif + +#endif +#endif +#if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t) +typedef unsigned wint_t; +#define __DEFINED_wint_t +#endif + + +#if defined(__FLT_EVAL_METHOD__) && __FLT_EVAL_METHOD__ == 0 +#if defined(__NEED_float_t) && !defined(__DEFINED_float_t) +typedef float float_t; +#define __DEFINED_float_t +#endif + +#if defined(__NEED_double_t) && !defined(__DEFINED_double_t) +typedef double double_t; +#define __DEFINED_double_t +#endif + +#else +#if defined(__NEED_float_t) && !defined(__DEFINED_float_t) +typedef long double float_t; +#define __DEFINED_float_t +#endif + +#if defined(__NEED_double_t) && !defined(__DEFINED_double_t) +typedef long double double_t; +#define __DEFINED_double_t +#endif + +#endif + +#if defined(__NEED_time_t) && !defined(__DEFINED_time_t) +typedef long time_t; +#define __DEFINED_time_t +#endif + +#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t) +typedef long suseconds_t; +#define __DEFINED_suseconds_t +#endif + + +#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t) +#ifdef __EMSCRIPTEN__ +// For canvas transfer implementation in Emscripten, use an extra 11th control field +// to pass a pointer to a string denoting the WebGL canvases to transfer. +typedef struct { union { int __i[11]; volatile int __vi[11]; unsigned __s[11]; } __u; } pthread_attr_t; +#else +typedef struct { union { int __i[10]; volatile int __vi[10]; unsigned __s[10]; } __u; } pthread_attr_t; +#endif +#define __DEFINED_pthread_attr_t +#endif + +#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t) +typedef struct { union { int __i[7]; volatile int __vi[7]; volatile void *__p[7]; } __u; } pthread_mutex_t; +typedef pthread_mutex_t mtx_t; +#define __DEFINED_pthread_mutex_t +#endif + +#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t) +typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t; +typedef pthread_cond_t cnd_t; +#define __DEFINED_pthread_cond_t +#endif + +#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t) +typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t; +#define __DEFINED_pthread_rwlock_t +#endif + +#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t) +typedef struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t; +#define __DEFINED_pthread_barrier_t +#endif + + +#if defined(__NEED_size_t) && !defined(__DEFINED_size_t) +typedef unsigned _Addr size_t; +#define __DEFINED_size_t +#endif + +#if defined(__NEED_uintptr_t) && !defined(__DEFINED_uintptr_t) +typedef unsigned _Addr uintptr_t; +#define __DEFINED_uintptr_t +#endif + +#if defined(__NEED_ptrdiff_t) && !defined(__DEFINED_ptrdiff_t) +typedef _Addr ptrdiff_t; +#define __DEFINED_ptrdiff_t +#endif + +#if defined(__NEED_ssize_t) && !defined(__DEFINED_ssize_t) +typedef _Addr ssize_t; +#define __DEFINED_ssize_t +#endif + +#if defined(__NEED_intptr_t) && !defined(__DEFINED_intptr_t) +typedef _Addr intptr_t; +#define __DEFINED_intptr_t +#endif + +#if defined(__NEED_regoff_t) && !defined(__DEFINED_regoff_t) +typedef _Addr regoff_t; +#define __DEFINED_regoff_t +#endif + +#if defined(__NEED_register_t) && !defined(__DEFINED_register_t) +typedef _Reg register_t; +#define __DEFINED_register_t +#endif + + +#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t) +typedef signed char int8_t; +#define __DEFINED_int8_t +#endif + +#if defined(__NEED_int16_t) && !defined(__DEFINED_int16_t) +typedef short int16_t; +#define __DEFINED_int16_t +#endif + +#if defined(__NEED_int32_t) && !defined(__DEFINED_int32_t) +typedef int int32_t; +#define __DEFINED_int32_t +#endif + +#if defined(__NEED_int64_t) && !defined(__DEFINED_int64_t) +typedef _Int64 int64_t; +#define __DEFINED_int64_t +#endif + +#if defined(__NEED_intmax_t) && !defined(__DEFINED_intmax_t) +typedef _Int64 intmax_t; +#define __DEFINED_intmax_t +#endif + +#if defined(__NEED_uint8_t) && !defined(__DEFINED_uint8_t) +typedef unsigned char uint8_t; +#define __DEFINED_uint8_t +#endif + +#if defined(__NEED_uint16_t) && !defined(__DEFINED_uint16_t) +typedef unsigned short uint16_t; +#define __DEFINED_uint16_t +#endif + +#if defined(__NEED_uint32_t) && !defined(__DEFINED_uint32_t) +typedef unsigned int uint32_t; +#define __DEFINED_uint32_t +#endif + +#if defined(__NEED_uint64_t) && !defined(__DEFINED_uint64_t) +typedef unsigned _Int64 uint64_t; +#define __DEFINED_uint64_t +#endif + +#if defined(__NEED_u_int64_t) && !defined(__DEFINED_u_int64_t) +typedef unsigned _Int64 u_int64_t; +#define __DEFINED_u_int64_t +#endif + +#if defined(__NEED_uintmax_t) && !defined(__DEFINED_uintmax_t) +typedef unsigned _Int64 uintmax_t; +#define __DEFINED_uintmax_t +#endif + + +#if defined(__NEED_mode_t) && !defined(__DEFINED_mode_t) +typedef unsigned mode_t; +#define __DEFINED_mode_t +#endif + +#if defined(__NEED_nlink_t) && !defined(__DEFINED_nlink_t) +typedef unsigned _Reg nlink_t; +#define __DEFINED_nlink_t +#endif + +#if defined(__NEED_off_t) && !defined(__DEFINED_off_t) +typedef _Int64 off_t; +#define __DEFINED_off_t +#endif + +#if defined(__NEED_ino_t) && !defined(__DEFINED_ino_t) +typedef unsigned _Int64 ino_t; +#define __DEFINED_ino_t +#endif + +#if defined(__NEED_dev_t) && !defined(__DEFINED_dev_t) +typedef unsigned int dev_t; +#define __DEFINED_dev_t +#endif + +#if defined(__NEED_blksize_t) && !defined(__DEFINED_blksize_t) +typedef long blksize_t; +#define __DEFINED_blksize_t +#endif + +#if defined(__NEED_blkcnt_t) && !defined(__DEFINED_blkcnt_t) +typedef int blkcnt_t; +#define __DEFINED_blkcnt_t +#endif + +#if defined(__NEED_fsblkcnt_t) && !defined(__DEFINED_fsblkcnt_t) +typedef unsigned int fsblkcnt_t; +#define __DEFINED_fsblkcnt_t +#endif + +#if defined(__NEED_fsfilcnt_t) && !defined(__DEFINED_fsfilcnt_t) +typedef unsigned int fsfilcnt_t; +#define __DEFINED_fsfilcnt_t +#endif + +#if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t) +typedef unsigned wint_t; +#define __DEFINED_wint_t +#endif + +#if defined(__NEED_wctype_t) && !defined(__DEFINED_wctype_t) +typedef unsigned long wctype_t; +#define __DEFINED_wctype_t +#endif + + +#if defined(__NEED_timer_t) && !defined(__DEFINED_timer_t) +typedef void * timer_t; +#define __DEFINED_timer_t +#endif + +#if defined(__NEED_clockid_t) && !defined(__DEFINED_clockid_t) +typedef int clockid_t; +#define __DEFINED_clockid_t +#endif + +#if defined(__NEED_clock_t) && !defined(__DEFINED_clock_t) +typedef long clock_t; +#define __DEFINED_clock_t +#endif + +#if defined(__NEED_max_align_t) && !defined(__DEFINED_max_align_t) +typedef struct { long long __ll; long double __ld; } max_align_t; +#define __DEFINED_max_align_t +#endif + +#if defined(__NEED_struct_timeval) && !defined(__DEFINED_struct_timeval) +struct timeval { time_t tv_sec; suseconds_t tv_usec; }; +#define __DEFINED_struct_timeval +#endif + +#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec) +struct timespec { time_t tv_sec; long tv_nsec; }; +#define __DEFINED_struct_timespec +#endif + + +#if defined(__NEED_pid_t) && !defined(__DEFINED_pid_t) +typedef int pid_t; +#define __DEFINED_pid_t +#endif + +#if defined(__NEED_id_t) && !defined(__DEFINED_id_t) +typedef unsigned id_t; +#define __DEFINED_id_t +#endif + +#if defined(__NEED_uid_t) && !defined(__DEFINED_uid_t) +typedef unsigned uid_t; +#define __DEFINED_uid_t +#endif + +#if defined(__NEED_gid_t) && !defined(__DEFINED_gid_t) +typedef unsigned gid_t; +#define __DEFINED_gid_t +#endif + +#if defined(__NEED_key_t) && !defined(__DEFINED_key_t) +typedef int key_t; +#define __DEFINED_key_t +#endif + +#if defined(__NEED_useconds_t) && !defined(__DEFINED_useconds_t) +typedef unsigned useconds_t; +#define __DEFINED_useconds_t +#endif + + +#ifdef __cplusplus +#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) +typedef unsigned long pthread_t; +#define __DEFINED_pthread_t +#endif + +#else +#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) +typedef struct __pthread * pthread_t; +#define __DEFINED_pthread_t +#endif + +#endif +#if defined(__NEED_pthread_once_t) && !defined(__DEFINED_pthread_once_t) +typedef int pthread_once_t; +#define __DEFINED_pthread_once_t +#endif + +#if defined(__NEED_pthread_key_t) && !defined(__DEFINED_pthread_key_t) +typedef unsigned pthread_key_t; +#define __DEFINED_pthread_key_t +#endif + +#if defined(__NEED_pthread_spinlock_t) && !defined(__DEFINED_pthread_spinlock_t) +typedef int pthread_spinlock_t; +#define __DEFINED_pthread_spinlock_t +#endif + +#if defined(__NEED_pthread_mutexattr_t) && !defined(__DEFINED_pthread_mutexattr_t) +typedef struct { unsigned __attr; } pthread_mutexattr_t; +#define __DEFINED_pthread_mutexattr_t +#endif + +#if defined(__NEED_pthread_condattr_t) && !defined(__DEFINED_pthread_condattr_t) +typedef struct { unsigned __attr; } pthread_condattr_t; +#define __DEFINED_pthread_condattr_t +#endif + +#if defined(__NEED_pthread_barrierattr_t) && !defined(__DEFINED_pthread_barrierattr_t) +typedef struct { unsigned __attr; } pthread_barrierattr_t; +#define __DEFINED_pthread_barrierattr_t +#endif + +#if defined(__NEED_pthread_rwlockattr_t) && !defined(__DEFINED_pthread_rwlockattr_t) +typedef struct { unsigned __attr[2]; } pthread_rwlockattr_t; +#define __DEFINED_pthread_rwlockattr_t +#endif + + +#if defined(__NEED_FILE) && !defined(__DEFINED_FILE) +typedef struct _IO_FILE FILE; +#define __DEFINED_FILE +#endif + + +#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t) +typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t; +#define __DEFINED_mbstate_t +#endif + + +#if defined(__NEED_locale_t) && !defined(__DEFINED_locale_t) +typedef struct __locale_struct * locale_t; +#define __DEFINED_locale_t +#endif + + +#if defined(__NEED_sigset_t) && !defined(__DEFINED_sigset_t) +typedef struct __sigset_t { unsigned long __bits[128/sizeof(long)]; } sigset_t; +#define __DEFINED_sigset_t +#endif + + +#if defined(__NEED_struct_iovec) && !defined(__DEFINED_struct_iovec) +struct iovec { void *iov_base; size_t iov_len; }; +#define __DEFINED_struct_iovec +#endif + + +#if defined(__NEED_socklen_t) && !defined(__DEFINED_socklen_t) +typedef unsigned socklen_t; +#define __DEFINED_socklen_t +#endif + +#if defined(__NEED_sa_family_t) && !defined(__DEFINED_sa_family_t) +typedef unsigned short sa_family_t; +#define __DEFINED_sa_family_t +#endif + + +#undef _Addr +#undef _Int64 +#undef _Reg diff --git a/arch/emscripten/bits/alltypes.h.in b/arch/emscripten/bits/alltypes.h.in new file mode 100644 index 00000000..fc922d01 --- /dev/null +++ b/arch/emscripten/bits/alltypes.h.in @@ -0,0 +1,25 @@ +#define _Addr __PTRDIFF_TYPE__ +#define _Int64 __INT64_TYPE__ +#define _Reg __PTRDIFF_TYPE__ + +TYPEDEF __builtin_va_list va_list; +TYPEDEF __builtin_va_list __isoc_va_list; + +#ifndef __cplusplus +TYPEDEF unsigned wchar_t; +#endif +TYPEDEF unsigned wint_t; + +TYPEDEF float float_t; +TYPEDEF double double_t; + +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; +TYPEDEF long time_t; +TYPEDEF long suseconds_t; + +TYPEDEF struct { union { int __i[10]; unsigned __s[10]; } __u; } pthread_attr_t; +TYPEDEF struct { union { int __i[7]; void *__p[7]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; +TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; + diff --git a/arch/emscripten/bits/endian.h b/arch/emscripten/bits/endian.h new file mode 100644 index 00000000..172c338f --- /dev/null +++ b/arch/emscripten/bits/endian.h @@ -0,0 +1 @@ +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/arch/emscripten/bits/errno.h b/arch/emscripten/bits/errno.h new file mode 100644 index 00000000..43a8a6ba --- /dev/null +++ b/arch/emscripten/bits/errno.h @@ -0,0 +1,144 @@ +#include + +#define EPERM __WASI_ERRNO_PERM +#define ENOENT __WASI_ERRNO_NOENT +#define ESRCH __WASI_ERRNO_SRCH +#define EINTR __WASI_ERRNO_INTR +#define EIO __WASI_ERRNO_IO +#define ENXIO __WASI_ERRNO_NXIO +#define E2BIG __WASI_ERRNO_2BIG +#define ENOEXEC __WASI_ERRNO_NOEXEC +#define EBADF __WASI_ERRNO_BADF +#define ECHILD __WASI_ERRNO_CHILD +#define EAGAIN __WASI_ERRNO_AGAIN +#define ENOMEM __WASI_ERRNO_NOMEM +#define EACCES __WASI_ERRNO_ACCES +#define EFAULT __WASI_ERRNO_FAULT +#define EBUSY __WASI_ERRNO_BUSY +#define EEXIST __WASI_ERRNO_EXIST +#define EXDEV __WASI_ERRNO_XDEV +#define ENODEV __WASI_ERRNO_NODEV +#define ENOTDIR __WASI_ERRNO_NOTDIR +#define EISDIR __WASI_ERRNO_ISDIR +#define EINVAL __WASI_ERRNO_INVAL +#define ENFILE __WASI_ERRNO_NFILE +#define EMFILE __WASI_ERRNO_MFILE +#define ENOTTY __WASI_ERRNO_NOTTY +#define ETXTBSY __WASI_ERRNO_TXTBSY +#define EFBIG __WASI_ERRNO_FBIG +#define ENOSPC __WASI_ERRNO_NOSPC +#define ESPIPE __WASI_ERRNO_SPIPE +#define EROFS __WASI_ERRNO_ROFS +#define EMLINK __WASI_ERRNO_MLINK +#define EPIPE __WASI_ERRNO_PIPE +#define EDOM __WASI_ERRNO_DOM +#define ERANGE __WASI_ERRNO_RANGE +#define EDEADLK __WASI_ERRNO_DEADLK +#define ENAMETOOLONG __WASI_ERRNO_NAMETOOLONG +#define ENOLCK __WASI_ERRNO_NOLCK +#define ENOSYS __WASI_ERRNO_NOSYS +#define ENOTEMPTY __WASI_ERRNO_NOTEMPTY +#define ELOOP __WASI_ERRNO_LOOP +#define ENOMSG __WASI_ERRNO_NOMSG +#define EIDRM __WASI_ERRNO_IDRM +#define ENOLINK __WASI_ERRNO_NOLINK +#define EPROTO __WASI_ERRNO_PROTO +#define EMULTIHOP __WASI_ERRNO_MULTIHOP +#define EBADMSG __WASI_ERRNO_BADMSG +#define EOVERFLOW __WASI_ERRNO_OVERFLOW +#define EILSEQ __WASI_ERRNO_ILSEQ +#define ENOTSOCK __WASI_ERRNO_NOTSOCK +#define EDESTADDRREQ __WASI_ERRNO_DESTADDRREQ +#define EMSGSIZE __WASI_ERRNO_MSGSIZE +#define EPROTOTYPE __WASI_ERRNO_PROTOTYPE +#define ENOPROTOOPT __WASI_ERRNO_NOPROTOOPT +#define EPROTONOSUPPORT __WASI_ERRNO_PROTONOSUPPORT +#define EAFNOSUPPORT __WASI_ERRNO_AFNOSUPPORT +#define EADDRINUSE __WASI_ERRNO_ADDRINUSE +#define EADDRNOTAVAIL __WASI_ERRNO_ADDRNOTAVAIL +#define ENETDOWN __WASI_ERRNO_NETDOWN +#define ENETUNREACH __WASI_ERRNO_NETUNREACH +#define ENETRESET __WASI_ERRNO_NETRESET +#define ECONNABORTED __WASI_ERRNO_CONNABORTED +#define ECONNRESET __WASI_ERRNO_CONNRESET +#define ENOBUFS __WASI_ERRNO_NOBUFS +#define EISCONN __WASI_ERRNO_ISCONN +#define ENOTCONN __WASI_ERRNO_NOTCONN +#define ETIMEDOUT __WASI_ERRNO_TIMEDOUT +#define ECONNREFUSED __WASI_ERRNO_CONNREFUSED +#define EHOSTUNREACH __WASI_ERRNO_HOSTUNREACH +#define EALREADY __WASI_ERRNO_ALREADY +#define EINPROGRESS __WASI_ERRNO_INPROGRESS +#define ESTALE __WASI_ERRNO_STALE +#define EDQUOT __WASI_ERRNO_DQUOT +#define ECANCELED __WASI_ERRNO_CANCELED +#define EOWNERDEAD __WASI_ERRNO_OWNERDEAD +#define ENOTRECOVERABLE __WASI_ERRNO_NOTRECOVERABLE + +// Codes without a wasi equivalent, make sure they start +// above the wasi ones, which are dense [1,76]. +// Also try to fit the codes in a single byte signed wasm SLEB. + +#define ENOSTR 100 +#define EBFONT 101 +#define EBADSLT 102 +#define EBADRQC 103 +#define ENOANO 104 +#define ENOTBLK 105 +#define ECHRNG 106 +#define EL3HLT 107 +#define EL3RST 108 +#define ELNRNG 109 +#define EUNATCH 110 +#define ENOCSI 111 +#define EL2HLT 112 +#define EBADE 113 +#define EBADR 114 +#define EXFULL 115 +#define ENODATA 116 +#define ETIME 117 +#define ENOSR 118 +#define ENONET 119 +#define ENOPKG 120 +#define EREMOTE 121 +#define EADV 122 +#define ESRMNT 123 +#define ECOMM 124 +#define EDOTDOT 125 +#define ENOTUNIQ 126 +#define EBADFD 127 +#define EREMCHG 128 +#define ELIBACC 129 +#define ELIBBAD 130 +#define ELIBSCN 131 +#define ELIBMAX 132 +#define ELIBEXEC 133 +#define ERESTART 134 +#define ESTRPIPE 135 +#define EUSERS 136 +#define ESOCKTNOSUPPORT 137 +#define EOPNOTSUPP 138 +#define EPFNOSUPPORT 139 +#define ESHUTDOWN 140 +#define ETOOMANYREFS 141 +#define EHOSTDOWN 142 +#define EUCLEAN 143 +#define ENOTNAM 144 +#define ENAVAIL 145 +#define EISNAM 146 +#define EREMOTEIO 147 +#define ENOMEDIUM 148 +#define EMEDIUMTYPE 149 +#define ENOKEY 150 +#define EKEYEXPIRED 151 +#define EKEYREVOKED 152 +#define EKEYREJECTED 153 +#define ERFKILL 154 +#define EHWPOISON 155 +#define EL2NSYNC 156 + +// codes which musl defines as aliases + +#define EWOULDBLOCK EAGAIN +#define EDEADLOCK EDEADLK +#define ENOTSUP EOPNOTSUPP diff --git a/arch/emscripten/bits/fcntl.h b/arch/emscripten/bits/fcntl.h new file mode 100644 index 00000000..900601b1 --- /dev/null +++ b/arch/emscripten/bits/fcntl.h @@ -0,0 +1,40 @@ +#define O_CREAT 0100 +#define O_EXCL 0200 +#define O_NOCTTY 0400 +#define O_TRUNC 01000 +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_DSYNC 010000 +#define O_SYNC 04010000 +#define O_RSYNC 04010000 +#define O_DIRECTORY 0200000 +#define O_NOFOLLOW 0400000 +#define O_CLOEXEC 02000000 + +#define O_ASYNC 020000 +#define O_DIRECT 040000 +#define O_LARGEFILE 0100000 +#define O_NOATIME 01000000 +#define O_PATH 010000000 +#define O_TMPFILE 020000000 +#define O_NDELAY O_NONBLOCK + +#define F_DUPFD 0 +#define F_GETFD 1 +#define F_SETFD 2 +#define F_GETFL 3 +#define F_SETFL 4 + +#define F_SETOWN 8 +#define F_GETOWN 9 +#define F_SETSIG 10 +#define F_GETSIG 11 + +#define F_GETLK 12 +#define F_SETLK 13 +#define F_SETLKW 14 + +#define F_SETOWN_EX 15 +#define F_GETOWN_EX 16 + +#define F_GETOWNER_UIDS 17 diff --git a/arch/emscripten/bits/fenv.h b/arch/emscripten/bits/fenv.h new file mode 100644 index 00000000..d3512cb6 --- /dev/null +++ b/arch/emscripten/bits/fenv.h @@ -0,0 +1,27 @@ +#define FE_ALL_EXCEPT 0 + +#define FE_TONEAREST 0 +#define FE_DOWNWARD 0x400 +#define FE_UPWARD 0x800 +#define FE_TOWARDZERO 0xc00 + +typedef unsigned short fexcept_t; + +typedef struct { + unsigned short __control_word; + unsigned short __unused1; + unsigned short __status_word; + unsigned short __unused2; + unsigned short __tags; + unsigned short __unused3; + unsigned int __eip; + unsigned short __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short __data_selector; + unsigned short __unused5; + unsigned int __mxcsr; +} fenv_t; + +#define FE_DFL_ENV ((const fenv_t *) -1) diff --git a/arch/emscripten/bits/float.h b/arch/emscripten/bits/float.h new file mode 100644 index 00000000..53ec2d10 --- /dev/null +++ b/arch/emscripten/bits/float.h @@ -0,0 +1,17 @@ +#define FLT_ROUNDS 1 +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ + +#define LDBL_TRUE_MIN __LDBL_DENORM_MIN__ +#define LDBL_MIN __LDBL_MIN__ +#define LDBL_MAX __LDBL_MAX__ +#define LDBL_EPSILON __LDBL_EPSILON__ + +#define LDBL_MANT_DIG __LDBL_MANT_DIG__ +#define LDBL_MIN_EXP __LDBL_MIN_EXP__ +#define LDBL_MAX_EXP __LDBL_MAX_EXP__ + +#define LDBL_DIG __LDBL_DIG__ +#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__ +#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ + +#define DECIMAL_DIG __DECIMAL_DIG__ diff --git a/arch/emscripten/bits/io.h b/arch/emscripten/bits/io.h new file mode 100644 index 00000000..e69de29b diff --git a/arch/emscripten/bits/ioctl.h b/arch/emscripten/bits/ioctl.h new file mode 100644 index 00000000..9d75118e --- /dev/null +++ b/arch/emscripten/bits/ioctl.h @@ -0,0 +1,197 @@ +#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) ) +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0) +#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c)) +#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c)) +#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c)) + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 +#define TIOCTTYGSTRUCT 0x5426 +#define TIOCSBRK 0x5427 +#define TIOCCBRK 0x5428 +#define TIOCGSID 0x5429 +#define TIOCGPTN 0x80045430 +#define TIOCSPTLCK 0x40045431 +#define TCGETX 0x5432 +#define TCSETX 0x5433 +#define TCSETXF 0x5434 +#define TCSETXW 0x5435 + +#define FIONCLEX 0x5450 +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 +#define TIOCSERGETLSR 0x5459 +#define TIOCSERGETMULTI 0x545A +#define TIOCSERSETMULTI 0x545B + +#define TIOCMIWAIT 0x545C +#define TIOCGICOUNT 0x545D +#define TIOCGHAYESESP 0x545E +#define TIOCSHAYESESP 0x545F +#define FIOQSIZE 0x5460 + +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64 + +#define TIOCSER_TEMT 0x01 + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 +#define TIOCM_MODEM_BITS TIOCM_OUT2 + +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 +#define N_6PACK 7 +#define N_MASC 8 +#define N_R3964 9 +#define N_PROFIBUS_FDL 10 +#define N_IRDA 11 +#define N_SMSBLOCK 12 +#define N_HDLC 13 +#define N_SYNC_PPP 14 +#define N_HCI 15 + +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 + +#define SIOCADDRT 0x890B +#define SIOCDELRT 0x890C +#define SIOCRTMSG 0x890D + +#define SIOCGIFNAME 0x8910 +#define SIOCSIFLINK 0x8911 +#define SIOCGIFCONF 0x8912 +#define SIOCGIFFLAGS 0x8913 +#define SIOCSIFFLAGS 0x8914 +#define SIOCGIFADDR 0x8915 +#define SIOCSIFADDR 0x8916 +#define SIOCGIFDSTADDR 0x8917 +#define SIOCSIFDSTADDR 0x8918 +#define SIOCGIFBRDADDR 0x8919 +#define SIOCSIFBRDADDR 0x891a +#define SIOCGIFNETMASK 0x891b +#define SIOCSIFNETMASK 0x891c +#define SIOCGIFMETRIC 0x891d +#define SIOCSIFMETRIC 0x891e +#define SIOCGIFMEM 0x891f +#define SIOCSIFMEM 0x8920 +#define SIOCGIFMTU 0x8921 +#define SIOCSIFMTU 0x8922 +#define SIOCSIFHWADDR 0x8924 +#define SIOCGIFENCAP 0x8925 +#define SIOCSIFENCAP 0x8926 +#define SIOCGIFHWADDR 0x8927 +#define SIOCGIFSLAVE 0x8929 +#define SIOCSIFSLAVE 0x8930 +#define SIOCADDMULTI 0x8931 +#define SIOCDELMULTI 0x8932 +#define SIOCGIFINDEX 0x8933 +#define SIOGIFINDEX SIOCGIFINDEX +#define SIOCSIFPFLAGS 0x8934 +#define SIOCGIFPFLAGS 0x8935 +#define SIOCDIFADDR 0x8936 +#define SIOCSIFHWBROADCAST 0x8937 +#define SIOCGIFCOUNT 0x8938 + +#define SIOCGIFBR 0x8940 +#define SIOCSIFBR 0x8941 + +#define SIOCGIFTXQLEN 0x8942 +#define SIOCSIFTXQLEN 0x8943 + +#define SIOCDARP 0x8953 +#define SIOCGARP 0x8954 +#define SIOCSARP 0x8955 + +#define SIOCDRARP 0x8960 +#define SIOCGRARP 0x8961 +#define SIOCSRARP 0x8962 + +#define SIOCGIFMAP 0x8970 +#define SIOCSIFMAP 0x8971 + +#define SIOCADDDLCI 0x8980 +#define SIOCDELDLCI 0x8981 + +#define SIOCDEVPRIVATE 0x89F0 +#define SIOCPROTOPRIVATE 0x89E0 diff --git a/arch/emscripten/bits/ipc.h b/arch/emscripten/bits/ipc.h new file mode 100644 index 00000000..b748d3b7 --- /dev/null +++ b/arch/emscripten/bits/ipc.h @@ -0,0 +1,14 @@ +struct ipc_perm +{ + key_t __ipc_perm_key; + uid_t uid; + gid_t gid; + uid_t cuid; + gid_t cgid; + mode_t mode; + int __ipc_perm_seq; + long __pad1; + long __pad2; +}; + +#define IPC_64 0x100 diff --git a/arch/emscripten/bits/limits.h b/arch/emscripten/bits/limits.h new file mode 100644 index 00000000..3fd93311 --- /dev/null +++ b/arch/emscripten/bits/limits.h @@ -0,0 +1,8 @@ +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define PAGE_SIZE 16384 +#define LONG_BIT 32 +#endif + +#define LONG_MAX 0x7fffffffL +#define LLONG_MAX 0x7fffffffffffffffLL diff --git a/arch/emscripten/bits/mman.h b/arch/emscripten/bits/mman.h new file mode 100644 index 00000000..add63855 --- /dev/null +++ b/arch/emscripten/bits/mman.h @@ -0,0 +1,62 @@ +#define MAP_FAILED ((void *) -1) + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 +#define PROT_GROWSDOWN 0x01000000 +#define PROT_GROWSUP 0x02000000 + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_FIXED 0x10 + +#define MAP_TYPE 0x0f +#define MAP_FILE 0x00 +#define MAP_ANON 0x20 +#define MAP_ANONYMOUS MAP_ANON +#define MAP_32BIT 0x40 +#define MAP_NORESERVE 0x4000 +#define MAP_GROWSDOWN 0x0100 +#define MAP_DENYWRITE 0x0800 +#define MAP_EXECUTABLE 0x1000 +#define MAP_LOCKED 0x2000 +#define MAP_POPULATE 0x8000 +#define MAP_NONBLOCK 0x10000 +#define MAP_STACK 0x20000 +#define MAP_HUGETLB 0x40000 + +#define POSIX_MADV_NORMAL 0 +#define POSIX_MADV_RANDOM 1 +#define POSIX_MADV_SEQUENTIAL 2 +#define POSIX_MADV_WILLNEED 3 +#define POSIX_MADV_DONTNEED 0 + +#define MS_ASYNC 1 +#define MS_INVALIDATE 2 +#define MS_SYNC 4 + +#define MCL_CURRENT 1 +#define MCL_FUTURE 2 + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define MADV_NORMAL 0 +#define MADV_RANDOM 1 +#define MADV_SEQUENTIAL 2 +#define MADV_WILLNEED 3 +#define MADV_DONTNEED 4 +#define MADV_REMOVE 9 +#define MADV_DONTFORK 10 +#define MADV_DOFORK 11 +#define MADV_MERGEABLE 12 +#define MADV_UNMERGEABLE 13 +#define MADV_HUGEPAGE 14 +#define MADV_NOHUGEPAGE 15 +#define MADV_DONTDUMP 16 +#define MADV_DODUMP 17 +#define MADV_HWPOISON 100 +#define MADV_SOFT_OFFLINE 101 + +#define MREMAP_MAYMOVE 1 +#define MREMAP_FIXED 2 +#endif diff --git a/arch/emscripten/bits/msg.h b/arch/emscripten/bits/msg.h new file mode 100644 index 00000000..3db8576b --- /dev/null +++ b/arch/emscripten/bits/msg.h @@ -0,0 +1,16 @@ +struct msqid_ds +{ + struct ipc_perm msg_perm; + time_t msg_stime; + int __unused1; + time_t msg_rtime; + int __unused2; + time_t msg_ctime; + int __unused3; + unsigned long msg_cbytes; + msgqnum_t msg_qnum; + msglen_t msg_qbytes; + pid_t msg_lspid; + pid_t msg_lrpid; + unsigned long __unused[2]; +}; diff --git a/arch/emscripten/bits/poll.h b/arch/emscripten/bits/poll.h new file mode 100644 index 00000000..e69de29b diff --git a/arch/emscripten/bits/posix.h b/arch/emscripten/bits/posix.h new file mode 100644 index 00000000..30a38714 --- /dev/null +++ b/arch/emscripten/bits/posix.h @@ -0,0 +1,2 @@ +#define _POSIX_V6_ILP32_OFFBIG 1 +#define _POSIX_V7_ILP32_OFFBIG 1 diff --git a/arch/emscripten/bits/reg.h b/arch/emscripten/bits/reg.h new file mode 100644 index 00000000..8bc2582d --- /dev/null +++ b/arch/emscripten/bits/reg.h @@ -0,0 +1,19 @@ +#undef __WORDSIZE +#define __WORDSIZE 32 +#define EBX 0 +#define ECX 1 +#define EDX 2 +#define ESI 3 +#define EDI 4 +#define EBP 5 +#define EAX 6 +#define DS 7 +#define ES 8 +#define FS 9 +#define GS 10 +#define ORIG_EAX 11 +#define EIP 12 +#define CS 13 +#define EFL 14 +#define UESP 15 +#define SS 16 diff --git a/arch/emscripten/bits/resource.h b/arch/emscripten/bits/resource.h new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/arch/emscripten/bits/resource.h @@ -0,0 +1,2 @@ + + diff --git a/arch/emscripten/bits/sem.h b/arch/emscripten/bits/sem.h new file mode 100644 index 00000000..f5ce202b --- /dev/null +++ b/arch/emscripten/bits/sem.h @@ -0,0 +1,11 @@ +struct semid_ds { + struct ipc_perm sem_perm; + time_t sem_otime; + time_t __unused1; + time_t sem_ctime; + time_t __unused2; + unsigned short sem_nsems; + char __sem_nsems_pad[sizeof(time_t)-sizeof(short)]; + time_t __unused3; + time_t __unused4; +}; diff --git a/arch/emscripten/bits/setjmp.h b/arch/emscripten/bits/setjmp.h new file mode 100644 index 00000000..decd26dc --- /dev/null +++ b/arch/emscripten/bits/setjmp.h @@ -0,0 +1 @@ +typedef unsigned long __jmp_buf[6]; diff --git a/arch/emscripten/bits/shm.h b/arch/emscripten/bits/shm.h new file mode 100644 index 00000000..8807c4fb --- /dev/null +++ b/arch/emscripten/bits/shm.h @@ -0,0 +1,18 @@ +#define SHMLBA 4096 + +struct shmid_ds +{ + struct ipc_perm shm_perm; + size_t shm_segsz; + time_t shm_atime; + int __unused1; + time_t shm_dtime; + int __unused2; + time_t shm_ctime; + int __unused3; + pid_t shm_cpid; + pid_t shm_lpid; + unsigned long shm_nattch; + unsigned long __pad1; + unsigned long __pad2; +}; diff --git a/arch/emscripten/bits/signal.h b/arch/emscripten/bits/signal.h new file mode 100644 index 00000000..58bc5e2c --- /dev/null +++ b/arch/emscripten/bits/signal.h @@ -0,0 +1,123 @@ +#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 + +#ifdef _GNU_SOURCE +#define REG_GS 0 +#define REG_FS 1 +#define REG_ES 2 +#define REG_DS 3 +#define REG_EDI 4 +#define REG_ESI 5 +#define REG_EBP 6 +#define REG_ESP 7 +#define REG_EBX 8 +#define REG_EDX 9 +#define REG_ECX 10 +#define REG_EAX 11 +#define REG_TRAPNO 12 +#define REG_ERR 13 +#define REG_EIP 14 +#define REG_CS 15 +#define REG_EFL 16 +#define REG_UESP 17 +#define REG_SS 18 +#endif + +struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +}; + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +typedef int greg_t, gregset_t[19]; +typedef struct _fpstate { + unsigned long cw, sw, tag, ipoff, cssel, dataoff, datasel; + struct { + unsigned short significand[4], exponent; + } _st[8]; + unsigned long status; +} *fpregset_t; +struct sigcontext { + unsigned short gs, __gsh, fs, __fsh, es, __esh, ds, __dsh; + unsigned long edi, esi, ebp, esp, ebx, edx, ecx, eax; + unsigned long trapno, err, eip; + unsigned short cs, __csh; + unsigned long eflags, esp_at_signal; + unsigned short ss, __ssh; + struct _fpstate *fpstate; + unsigned long oldmask, cr2; +}; +typedef struct { + gregset_t gregs; + fpregset_t fpregs; + unsigned long oldmask, cr2; +} mcontext_t; +#else +typedef struct { + unsigned __space[22]; +} mcontext_t; +#endif + +typedef struct __ucontext { + unsigned long uc_flags; + struct __ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + sigset_t uc_sigmask; + unsigned long __fpregs_mem[28]; +} 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/emscripten/bits/socket.h b/arch/emscripten/bits/socket.h new file mode 100644 index 00000000..36febbc2 --- /dev/null +++ b/arch/emscripten/bits/socket.h @@ -0,0 +1,17 @@ +struct msghdr +{ + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + int msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; + +struct cmsghdr +{ + socklen_t cmsg_len; + int cmsg_level; + int cmsg_type; +}; diff --git a/arch/emscripten/bits/stat.h b/arch/emscripten/bits/stat.h new file mode 100644 index 00000000..bb9314a5 --- /dev/null +++ b/arch/emscripten/bits/stat.h @@ -0,0 +1,22 @@ +/* copied from kernel definition, but with padding replaced + * by the corresponding correctly-sized userspace types. */ + +struct stat +{ + dev_t st_dev; + int __st_dev_padding; + long __st_ino_truncated; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + int __st_rdev_padding; + off_t st_size; + blksize_t st_blksize; + blkcnt_t st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + ino_t st_ino; +}; diff --git a/arch/emscripten/bits/statfs.h b/arch/emscripten/bits/statfs.h new file mode 100644 index 00000000..f103f4e4 --- /dev/null +++ b/arch/emscripten/bits/statfs.h @@ -0,0 +1,7 @@ +struct statfs { + unsigned long f_type, f_bsize; + fsblkcnt_t f_blocks, f_bfree, f_bavail; + fsfilcnt_t f_files, f_ffree; + fsid_t f_fsid; + unsigned long f_namelen, f_frsize, f_flags, f_spare[4]; +}; diff --git a/arch/emscripten/bits/stdarg.h b/arch/emscripten/bits/stdarg.h new file mode 100644 index 00000000..fde37814 --- /dev/null +++ b/arch/emscripten/bits/stdarg.h @@ -0,0 +1,4 @@ +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#define va_copy(d,s) __builtin_va_copy(d,s) diff --git a/arch/emscripten/bits/stdint.h b/arch/emscripten/bits/stdint.h new file mode 100644 index 00000000..d1b27121 --- /dev/null +++ b/arch/emscripten/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/emscripten/bits/syscall.h b/arch/emscripten/bits/syscall.h new file mode 100644 index 00000000..dddf57e4 --- /dev/null +++ b/arch/emscripten/bits/syscall.h @@ -0,0 +1,226 @@ +/* + * The .h version of this file is generated from the .h.in. + * See update_syscall.sh. + */ +#define __NR_exit 1 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_chdir 12 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_getpid 20 +#define __NR_pause 29 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_sync 36 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_acct 51 +#define __NR_ioctl 54 +#define __NR_setpgid 57 +#define __NR_umask 60 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_setrlimit 75 +#define __NR_getrusage 77 +#define __NR_symlink 83 +#define __NR_readlink 85 +#define __NR_munmap 91 +#define __NR_fchmod 94 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_socketcall 102 +#define __NR_setitimer 104 +#define __NR_wait4 114 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_mprotect 125 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR__newselect 142 +#define __NR_msync 144 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_mremap 163 +#define __NR_poll 168 +#define __NR_rt_sigqueueinfo 178 +#define __NR_pread64 180 +#define __NR_pwrite64 181 +#define __NR_getcwd 183 +#define __NR_ugetrlimit 191 +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#define __NR_lchown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_chown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_mincore 218 +#define __NR_madvise 219 +#define __NR_madvise1 219 +#define __NR_getdents64 220 +#define __NR_fcntl64 221 +#define __NR_exit_group 252 +#define __NR_statfs64 268 +#define __NR_fstatfs64 269 +#define __NR_fadvise64_64 272 +#define __NR_openat 295 +#define __NR_mkdirat 296 +#define __NR_mknodat 297 +#define __NR_fchownat 298 +#define __NR_fstatat64 300 +#define __NR_unlinkat 301 +#define __NR_renameat 302 +#define __NR_linkat 303 +#define __NR_symlinkat 304 +#define __NR_readlinkat 305 +#define __NR_fchmodat 306 +#define __NR_faccessat 307 +#define __NR_pselect6 308 +#define __NR_utimensat 320 +#define __NR_fallocate 324 +#define __NR_dup3 330 +#define __NR_pipe2 331 +#define __NR_preadv 333 +#define __NR_pwritev 334 +#define __NR_recvmmsg 337 +#define __NR_prlimit64 340 +#define __NR_sendmmsg 345 +#define SYS_exit 1 +#define SYS_read 3 +#define SYS_write 4 +#define SYS_open 5 +#define SYS_link 9 +#define SYS_unlink 10 +#define SYS_chdir 12 +#define SYS_mknod 14 +#define SYS_chmod 15 +#define SYS_getpid 20 +#define SYS_pause 29 +#define SYS_access 33 +#define SYS_nice 34 +#define SYS_sync 36 +#define SYS_rename 38 +#define SYS_mkdir 39 +#define SYS_rmdir 40 +#define SYS_dup 41 +#define SYS_pipe 42 +#define SYS_acct 51 +#define SYS_ioctl 54 +#define SYS_setpgid 57 +#define SYS_umask 60 +#define SYS_dup2 63 +#define SYS_getppid 64 +#define SYS_getpgrp 65 +#define SYS_setsid 66 +#define SYS_setrlimit 75 +#define SYS_getrusage 77 +#define SYS_symlink 83 +#define SYS_readlink 85 +#define SYS_munmap 91 +#define SYS_fchmod 94 +#define SYS_getpriority 96 +#define SYS_setpriority 97 +#define SYS_socketcall 102 +#define SYS_setitimer 104 +#define SYS_wait4 114 +#define SYS_setdomainname 121 +#define SYS_uname 122 +#define SYS_mprotect 125 +#define SYS_getpgid 132 +#define SYS_fchdir 133 +#define SYS__newselect 142 +#define SYS_msync 144 +#define SYS_getsid 147 +#define SYS_fdatasync 148 +#define SYS_mlock 150 +#define SYS_munlock 151 +#define SYS_mlockall 152 +#define SYS_munlockall 153 +#define SYS_mremap 163 +#define SYS_poll 168 +#define SYS_rt_sigqueueinfo 178 +#define SYS_pread64 180 +#define SYS_pwrite64 181 +#define SYS_getcwd 183 +#define SYS_ugetrlimit 191 +#define SYS_mmap2 192 +#define SYS_truncate64 193 +#define SYS_ftruncate64 194 +#define SYS_stat64 195 +#define SYS_lstat64 196 +#define SYS_fstat64 197 +#define SYS_lchown32 198 +#define SYS_getuid32 199 +#define SYS_getgid32 200 +#define SYS_geteuid32 201 +#define SYS_getegid32 202 +#define SYS_setreuid32 203 +#define SYS_setregid32 204 +#define SYS_getgroups32 205 +#define SYS_fchown32 207 +#define SYS_setresuid32 208 +#define SYS_getresuid32 209 +#define SYS_setresgid32 210 +#define SYS_getresgid32 211 +#define SYS_chown32 212 +#define SYS_setuid32 213 +#define SYS_setgid32 214 +#define SYS_mincore 218 +#define SYS_madvise 219 +#define SYS_madvise1 219 +#define SYS_getdents64 220 +#define SYS_fcntl64 221 +#define SYS_exit_group 252 +#define SYS_statfs64 268 +#define SYS_fstatfs64 269 +#define SYS_fadvise64_64 272 +#define SYS_openat 295 +#define SYS_mkdirat 296 +#define SYS_mknodat 297 +#define SYS_fchownat 298 +#define SYS_fstatat64 300 +#define SYS_unlinkat 301 +#define SYS_renameat 302 +#define SYS_linkat 303 +#define SYS_symlinkat 304 +#define SYS_readlinkat 305 +#define SYS_fchmodat 306 +#define SYS_faccessat 307 +#define SYS_pselect6 308 +#define SYS_utimensat 320 +#define SYS_fallocate 324 +#define SYS_dup3 330 +#define SYS_pipe2 331 +#define SYS_preadv 333 +#define SYS_pwritev 334 +#define SYS_recvmmsg 337 +#define SYS_prlimit64 340 +#define SYS_sendmmsg 345 diff --git a/arch/emscripten/bits/syscall.h.in b/arch/emscripten/bits/syscall.h.in new file mode 100644 index 00000000..c5d4a2ef --- /dev/null +++ b/arch/emscripten/bits/syscall.h.in @@ -0,0 +1,115 @@ +/* + * The .h version of this file is generated from the .h.in. + * See update_syscall.sh. + */ +#define __NR_exit 1 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_chdir 12 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_getpid 20 +#define __NR_pause 29 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_sync 36 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_acct 51 +#define __NR_ioctl 54 +#define __NR_setpgid 57 +#define __NR_umask 60 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_setrlimit 75 +#define __NR_getrusage 77 +#define __NR_symlink 83 +#define __NR_readlink 85 +#define __NR_munmap 91 +#define __NR_fchmod 94 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_socketcall 102 +#define __NR_setitimer 104 +#define __NR_wait4 114 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_mprotect 125 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR__newselect 142 +#define __NR_msync 144 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_mremap 163 +#define __NR_poll 168 +#define __NR_rt_sigqueueinfo 178 +#define __NR_pread64 180 +#define __NR_pwrite64 181 +#define __NR_getcwd 183 +#define __NR_ugetrlimit 191 +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#define __NR_lchown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_chown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_mincore 218 +#define __NR_madvise 219 +#define __NR_madvise1 219 +#define __NR_getdents64 220 +#define __NR_fcntl64 221 +#define __NR_exit_group 252 +#define __NR_statfs64 268 +#define __NR_fstatfs64 269 +#define __NR_fadvise64_64 272 +#define __NR_openat 295 +#define __NR_mkdirat 296 +#define __NR_mknodat 297 +#define __NR_fchownat 298 +#define __NR_fstatat64 300 +#define __NR_unlinkat 301 +#define __NR_renameat 302 +#define __NR_linkat 303 +#define __NR_symlinkat 304 +#define __NR_readlinkat 305 +#define __NR_fchmodat 306 +#define __NR_faccessat 307 +#define __NR_pselect6 308 +#define __NR_utimensat 320 +#define __NR_fallocate 324 +#define __NR_dup3 330 +#define __NR_pipe2 331 +#define __NR_preadv 333 +#define __NR_pwritev 334 +#define __NR_recvmmsg 337 +#define __NR_prlimit64 340 +#define __NR_sendmmsg 345 diff --git a/arch/emscripten/bits/termios.h b/arch/emscripten/bits/termios.h new file mode 100644 index 00000000..61c888f4 --- /dev/null +++ b/arch/emscripten/bits/termios.h @@ -0,0 +1,160 @@ +struct termios +{ + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_line; + cc_t c_cc[NCCS]; + speed_t __c_ispeed; + speed_t __c_ospeed; +}; + +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 + +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#define NLDLY 0000400 +#define NL0 0000000 +#define NL1 0000400 +#define CRDLY 0003000 +#define CR0 0000000 +#define CR1 0001000 +#define CR2 0002000 +#define CR3 0003000 +#define TABDLY 0014000 +#define TAB0 0000000 +#define TAB1 0004000 +#define TAB2 0010000 +#define TAB3 0014000 +#define BSDLY 0020000 +#define BS0 0000000 +#define BS1 0020000 +#define FFDLY 0100000 +#define FF0 0000000 +#define FF1 0100000 + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +/* ?? */ +#define XTABS 0014000 + +#define B0 0000000 +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 + +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 + +#define CBAUD 0010017 + +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 + +#define CRTSCTS 020000000000 + +#define ISIG 0000001 +#define ICANON 0000002 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define IEXTEN 0100000 + +/* Extensions? */ +#define CBAUDEX 0010000 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define EXTPROC 0200000 + +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 diff --git a/arch/emscripten/bits/update_syscall.sh b/arch/emscripten/bits/update_syscall.sh new file mode 100755 index 00000000..7e4489cb --- /dev/null +++ b/arch/emscripten/bits/update_syscall.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# This scripe updates syscall.h based on the contents of syscall.h.in +# essentially duplicate all the __NR_ marcros with __SYS_ macros. In upstream +# must this is don by the top level Makefile. + +cp syscall.h.in syscall.h +sed -n -e s/__NR_/SYS_/p < syscall.h.in >> syscall.h diff --git a/arch/emscripten/bits/user.h b/arch/emscripten/bits/user.h new file mode 100644 index 00000000..fa623621 --- /dev/null +++ b/arch/emscripten/bits/user.h @@ -0,0 +1,48 @@ +#undef __WORDSIZE +#define __WORDSIZE 32 + +typedef struct user_fpregs_struct +{ + long cwd, swd, twd, fip, fcs, foo, fos, st_space[20]; +} elf_fpregset_t; + +typedef struct user_fpxregs_struct +{ + unsigned short cwd, swd, twd, fop; + long fip, fcs, foo, fos, mxcsr, reserved; + long st_space[32], xmm_space[32], padding[56]; +} elf_fpxregset_t; + +struct user_regs_struct +{ + long ebx, ecx, edx, esi, edi, ebp, eax, xds, xes, xfs, xgs; + long orig_eax, eip, xcs, eflags, esp, xss; +}; + +#define ELF_NGREG 17 +typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG]; + +struct user +{ + struct user_regs_struct regs; + int u_fpvalid; + struct user_fpregs_struct i387; + unsigned long u_tsize; + unsigned long u_dsize; + unsigned long u_ssize; + unsigned long start_code; + unsigned long start_stack; + long signal; + int reserved; + struct user_regs_struct *u_ar0; + struct user_fpregs_struct *u_fpstate; + unsigned long magic; + char u_comm[32]; + int u_debugreg[8]; +}; + +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) diff --git a/arch/emscripten/crt_arch.h b/arch/emscripten/crt_arch.h new file mode 100644 index 00000000..e69de29b diff --git a/arch/emscripten/pthread_arch.h b/arch/emscripten/pthread_arch.h new file mode 100644 index 00000000..77ef9a2b --- /dev/null +++ b/arch/emscripten/pthread_arch.h @@ -0,0 +1,5 @@ +struct pthread *__pthread_self(void); + +#define TP_ADJ(p) (p) + +#define CANCEL_REG_IP 16 diff --git a/arch/emscripten/syscall_arch.h b/arch/emscripten/syscall_arch.h new file mode 100644 index 00000000..7ff67eca --- /dev/null +++ b/arch/emscripten/syscall_arch.h @@ -0,0 +1,149 @@ +#include +#include +#include + +#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) 0, __SYSCALL_LL_E((x)) + +#define __SC_socket 1 +#define __SC_bind 2 +#define __SC_connect 3 +#define __SC_listen 4 +#define __SC_accept 5 +#define __SC_getsockname 6 +#define __SC_getpeername 7 +#define __SC_socketpair 8 +#define __SC_send 9 +#define __SC_recv 10 +#define __SC_sendto 11 +#define __SC_recvfrom 12 +#define __SC_shutdown 13 +#define __SC_setsockopt 14 +#define __SC_getsockopt 15 +#define __SC_sendmsg 16 +#define __SC_recvmsg 17 +#define __SC_accept4 18 +#define __SC_recvmmsg 19 +#define __SC_sendmmsg 20 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Causes the final import in the wasm binary be named "env.sys_" */ +#define SYS_IMPORT(NAME) EM_IMPORT(__sys_##NAME) + +long SYS_IMPORT(exit) __syscall1(long exit_code); +long SYS_IMPORT(open) __syscall5(long path, long flags, ...); // mode is optional +long SYS_IMPORT(link) __syscall9(long oldpath, long newpath); +long SYS_IMPORT(unlink) __syscall10(long path); +long SYS_IMPORT(chdir) __syscall12(long path); +long SYS_IMPORT(mknod) __syscall14(long path, long mode, long dev); +long SYS_IMPORT(chmod) __syscall15(long path, long mode); +long SYS_IMPORT(getpid) __syscall20(void); +long SYS_IMPORT(pause) __syscall29(void); +long SYS_IMPORT(access) __syscall33(long path, long amode); +long SYS_IMPORT(nice) __syscall34(long inc); +long SYS_IMPORT(sync) __syscall36(void); +long SYS_IMPORT(rename) __syscall38(long old_path, long new_path); +long SYS_IMPORT(mkdir) __syscall39(long path, long mode); +long SYS_IMPORT(rmdir) __syscall40(long path); +long SYS_IMPORT(dup) __syscall41(long fd); +long SYS_IMPORT(pipe) __syscall42(long fd); +long SYS_IMPORT(acct) __syscall51(long filename); +long SYS_IMPORT(ioctl) __syscall54(long fd, long request, ...); +long SYS_IMPORT(setpgid) __syscall57(long pid, long gpid); +long SYS_IMPORT(umask) __syscall60(long mask); +long SYS_IMPORT(dup2) __syscall63(long oldfd, long newfd); +long SYS_IMPORT(getppid) __syscall64(void); +long SYS_IMPORT(getpgrp) __syscall65(void); +long SYS_IMPORT(setsid) __syscall66(void); +long SYS_IMPORT(setrlimit) __syscall75(long resource, long limit); +long SYS_IMPORT(getrusage) __syscall77(long who, long usage); +long SYS_IMPORT(symlink) __syscall83(long target, long linkpath); +long SYS_IMPORT(readlink) __syscall85(long path, long buf, long bufsize); +long SYS_IMPORT(munmap) __syscall91(long addr, long len); +long SYS_IMPORT(fchmod) __syscall94(long fd, long mode); +long SYS_IMPORT(getpriority) __syscall96(long which, long who); +long SYS_IMPORT(setpriority) __syscall97(long which, long who, long prio); +long SYS_IMPORT(socketcall) __syscall102(long call, long args); +long SYS_IMPORT(setitimer) __syscall104(long which, long new_value, long old_value); +long SYS_IMPORT(wait4) __syscall114(long pid, long wstatus, long options, long rusage); +long SYS_IMPORT(setdomainname) __syscall121(long name, long size); +long SYS_IMPORT(uname) __syscall122(long buf); +long SYS_IMPORT(mprotect) __syscall125(long addr, long len, long size); +long SYS_IMPORT(getpgid) __syscall132(long pid); +long SYS_IMPORT(fchdir) __syscall133(long fd); +long SYS_IMPORT(_newselect) + __syscall142(long nfds, long readfds, long writefds, long exceptfds, long timeout); +long SYS_IMPORT(msync) __syscall144(long addr, long len, long flags); +long SYS_IMPORT(getsid) __syscall147(long pid); +long SYS_IMPORT(fdatasync) __syscall148(long fd); +long SYS_IMPORT(mlock) __syscall150(long addr, long len); +long SYS_IMPORT(munlock) __syscall151(long addr, long len); +long SYS_IMPORT(mlockall) __syscall152(long flags); +long SYS_IMPORT(munlockall) __syscall153(void); +long SYS_IMPORT(mremap) + __syscall163(long old_addr, long old_size, long new_size, long flags, long new_addr); +long SYS_IMPORT(poll) __syscall168(long fds, long nfds, long timeout); +long SYS_IMPORT(rt_sigqueueinfo) __syscall178(long tgid, long sig, long uinfo); +long SYS_IMPORT(getcwd) __syscall183(long buf, long size); +long SYS_IMPORT(ugetrlimit) __syscall191(long resource, long rlim); +long SYS_IMPORT(mmap2) __syscall192(long addr, long len, long prot, long flags, long fd, long off); +long SYS_IMPORT(truncate64) __syscall193(long path, long zero, long low, long high); +long SYS_IMPORT(ftruncate64) __syscall194(long fd, long zero, long low, long high); +long SYS_IMPORT(stat64) __syscall195(long path, long buf); +long SYS_IMPORT(lstat64) __syscall196(long path, long buf); +long SYS_IMPORT(fstat64) __syscall197(long fd, long buf); +long SYS_IMPORT(lchown32) __syscall198(long path, long owner, long group); +long SYS_IMPORT(getuid32) __syscall199(void); +long SYS_IMPORT(getgid32) __syscall200(void); +long SYS_IMPORT(geteuid32) __syscall201(void); +long SYS_IMPORT(getegid32) __syscall202(void); +long SYS_IMPORT(setreuid32) __syscall203(long ruid, long euid); +long SYS_IMPORT(setregid32) __syscall204(long rgid, long egid); +long SYS_IMPORT(getgroups32) __syscall205(long size, long list); +long SYS_IMPORT(fchown32) __syscall207(long fd, long owner, long group); +long SYS_IMPORT(setresuid32) __syscall208(long ruid, long euid, long suid); +long SYS_IMPORT(getresuid32) __syscall209(long ruid, long euid, long suid); +long SYS_IMPORT(setresgid32) __syscall210(long rgid, long egid, long sgid); +long SYS_IMPORT(getresgid32) __syscall211(long rgid, long egid, long sgid); +long SYS_IMPORT(chown32) __syscall212(long path, long owner, long group); +long SYS_IMPORT(setuid32) __syscall213(long uid); +long SYS_IMPORT(setgid32) __syscall214(long uid); +long SYS_IMPORT(mincore) __syscall218(long addr, long length, long vec); +long SYS_IMPORT(madvise1) __syscall219(long addr, long length, long advice); +long SYS_IMPORT(getdents64) __syscall220(long fd, long dirp, long count); +long SYS_IMPORT(fcntl64) __syscall221(long fd, long cmd, ...); +long SYS_IMPORT(exit_group) __syscall252(long status); +long SYS_IMPORT(statfs64) __syscall268(long path, long size, long buf); +long SYS_IMPORT(fstatfs64) __syscall269(long fd, long size, long buf); +long SYS_IMPORT(fadvise64_64) + __syscall272(long fd, long zero, long low, long high, long low2, long high2, long advice); +long SYS_IMPORT(openat) __syscall295(long dirfd, long path, long flags, ...); +long SYS_IMPORT(mkdirat) __syscall296(long dirfd, long path, long mode); +long SYS_IMPORT(mknodat) __syscall297(long dirfd, long path, long mode, long dev); +long SYS_IMPORT(fchownat) __syscall298(long dirfd, long path, long owner, long group, long flags); +long SYS_IMPORT(fstatat64) __syscall300(long dirfd, long path, long buf, long flags); +long SYS_IMPORT(unlinkat) __syscall301(long dirfd, long path, long flags); +long SYS_IMPORT(renameat) __syscall302(long olddirfd, long oldpath, long newdirfd, long newpath); +long SYS_IMPORT(linkat) + __syscall303(long olddirfd, long oldpath, long newdirfd, long newpath, long flags); +long SYS_IMPORT(symlinkat) __syscall304(long target, long newdirfd, long linkpath); +long SYS_IMPORT(readlinkat) __syscall305(long dirfd, long path, long bug, long bufsize); +long SYS_IMPORT(fchmodat) __syscall306(long dirfd, long path, long mode, ...); +long SYS_IMPORT(faccessat) __syscall307(long dirfd, long path, long amode, long flags); +long SYS_IMPORT(pselect6) __syscall308(long nfds, long readfds, long writefds, long exceptfds, long timeout, long sigmaks); +long SYS_IMPORT(utimensat) __syscall320(long dirfd, long path, long times, long flags); +long SYS_IMPORT(fallocate) __syscall324(long fd, long mode, long off_low, long off_high, long len_low, long len_high); +long SYS_IMPORT(dup3) __syscall330(long fd, long suggestfd, long flags); +long SYS_IMPORT(pipe2) __syscall331(long fds, long flags); +long SYS_IMPORT(recvmmsg) __syscall337(long sockfd, long msgvec, long vlen, long flags, ...); +long SYS_IMPORT(prlimit64) __syscall340(long pid, long resource, long new_limit, long old_limit); +long SYS_IMPORT(sendmmsg) __syscall345(long sockfd, long msgvec, long vlen, long flags, ...); + +#ifdef __cplusplus +} +#endif diff --git a/configure b/configure index af8b45f0..928455e7 100755 --- a/configure +++ b/configure @@ -325,6 +325,7 @@ or1k*) ARCH=or1k ;; powerpc64*) ARCH=powerpc64 ;; powerpc*) ARCH=powerpc ;; sh[1-9bel-]*|sh|superh*) ARCH=sh ;; +asmjs-unknown-emscripten) ARCH=emscripten ;; unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;; *) fail "$0: unknown or unsupported target \"$target\"" ;; esac @@ -382,7 +383,7 @@ tryflag CFLAGS_NOSSP -fno-stack-protector # option is sufficient, and if not, add a macro to cripple these # functions with volatile... # -tryflag CFLAGS_MEMOPS -fno-tree-loop-distribute-patterns +# XXX EMSCRIPTEN tryflag CFLAGS_MEMOPS -fno-tree-loop-distribute-patterns # # Enable debugging if requessted. @@ -500,7 +501,7 @@ fi # tryflag CFLAGS_AUTO -Werror=implicit-function-declaration tryflag CFLAGS_AUTO -Werror=implicit-int -tryflag CFLAGS_AUTO -Werror=pointer-sign +# XXX EMSCRIPTEN tryflag CFLAGS_AUTO -Werror=pointer-sign tryflag CFLAGS_AUTO -Werror=pointer-arith if test "x$warnings" = xyes ; then diff --git a/include/assert.h b/include/assert.h index e679adbf..1ae0ea55 100644 --- a/include/assert.h +++ b/include/assert.h @@ -16,6 +16,9 @@ extern "C" { #endif +#ifdef __EMSCRIPTEN__ +_Noreturn +#endif void __assert_fail (const char *, const char *, int, const char *); #ifdef __cplusplus diff --git a/include/fcntl.h b/include/fcntl.h index e683e4dc..e8bc80b3 100644 --- a/include/fcntl.h +++ b/include/fcntl.h @@ -1,6 +1,10 @@ #ifndef _FCNTL_H #define _FCNTL_H +#ifdef __EMSCRIPTEN__ +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -72,9 +76,15 @@ int posix_fallocate(int, off_t, off_t); #undef SEEK_SET #undef SEEK_CUR #undef SEEK_END +#ifdef __EMSCRIPTEN__ +#define SEEK_SET __WASI_WHENCE_SET +#define SEEK_CUR __WASI_WHENCE_CUR +#define SEEK_END __WASI_WHENCE_END +#else #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 +#endif // EMSCRIPTEN #ifndef S_IRUSR #define S_ISUID 04000 diff --git a/include/features.h b/include/features.h index 3cc3e579..48c4aa6c 100644 --- a/include/features.h +++ b/include/features.h @@ -33,4 +33,7 @@ #define _Noreturn #endif +#define weak_alias(old, new) \ + extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) + #endif diff --git a/include/pthread.h b/include/pthread.h index 3d2e0c45..378ae292 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -203,11 +203,18 @@ struct __ptcb { struct __ptcb *__next; }; +#ifdef __EMSCRIPTEN__ +// For Emscripten, the cleanup stack is not implemented as a macro, since it's currently in the JS side. +typedef void (*cleanup_handler_routine)(void *arg); +void pthread_cleanup_push(cleanup_handler_routine routine, void *arg); +void pthread_cleanup_pop(int execute); +#else void _pthread_cleanup_push(struct __ptcb *, void (*)(void *), void *); void _pthread_cleanup_pop(struct __ptcb *, int); #define pthread_cleanup_push(f, x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x); #define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0) +#endif #ifdef _GNU_SOURCE struct cpu_set_t; diff --git a/include/setjmp.h b/include/setjmp.h index 2d43abf8..fac697fc 100644 --- a/include/setjmp.h +++ b/include/setjmp.h @@ -19,7 +19,12 @@ typedef struct __jmp_buf_tag { || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ || defined(_BSD_SOURCE) typedef jmp_buf sigjmp_buf; +/* XXX EMSCRIPTEN: No signals support, alias sigsetjmp and siglongjmp to their non-signals counterparts. */ +#if __EMSCRIPTEN__ +#define sigsetjmp(buf, x) setjmp((buf)) +#else int sigsetjmp (sigjmp_buf, int); +#endif _Noreturn void siglongjmp (sigjmp_buf, int); #endif diff --git a/include/stdio.h b/include/stdio.h index 884d2e6a..e24168ac 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -1,6 +1,10 @@ #ifndef _STDIO_H #define _STDIO_H +#ifdef __EMSCRIPTEN__ +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -33,9 +37,15 @@ extern "C" { #undef SEEK_SET #undef SEEK_CUR #undef SEEK_END +#ifdef __EMSCRIPTEN__ +#define SEEK_SET __WASI_WHENCE_SET +#define SEEK_CUR __WASI_WHENCE_CUR +#define SEEK_END __WASI_WHENCE_END +#else #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 +#endif // EMSCRIPTEN #define _IOFBF 0 #define _IOLBF 1 diff --git a/include/sys/types.h b/include/sys/types.h index 75e489c5..0c35541d 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -69,7 +69,6 @@ typedef long long quad_t; typedef unsigned long long u_quad_t; #include #include -#include #endif #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) diff --git a/include/threads.h b/include/threads.h index 01794826..a9024028 100644 --- a/include/threads.h +++ b/include/threads.h @@ -20,6 +20,11 @@ typedef void (*tss_dtor_t)(void *); #define __NEED_cnd_t #define __NEED_mtx_t +// XXX Emscripten: Fix musl libc issue, where the above defines are wrong, but instead should be the following: (https://github.com/emscripten-core/emscripten/issues/5343) +#define __NEED_pthread_cond_t +#define __NEED_pthread_mutex_t +// XXX + #include #define TSS_DTOR_ITERATIONS 4 diff --git a/include/unistd.h b/include/unistd.h index 760a1652..29a644fa 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -1,6 +1,10 @@ #ifndef _UNISTD_H #define _UNISTD_H +#ifdef __EMSCRIPTEN__ +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -11,9 +15,15 @@ extern "C" { #define STDOUT_FILENO 1 #define STDERR_FILENO 2 +#ifdef __EMSCRIPTEN__ +#define SEEK_SET __WASI_WHENCE_SET +#define SEEK_CUR __WASI_WHENCE_CUR +#define SEEK_END __WASI_WHENCE_END +#else #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 +#endif // EMSCRIPTEN #ifdef __cplusplus #define NULL 0L @@ -173,7 +183,7 @@ void setusershell(void); void endusershell(void); char *getusershell(void); int acct(const char *); -long syscall(long, ...); +/* XXX EMSCRIPTEN long syscall(long, ...); */ int execvpe(const char *, char *const [], char *const []); int issetugid(void); #endif @@ -221,11 +231,23 @@ int eaccess(const char *, int); #define _POSIX_FSYNC _POSIX_VERSION #define _POSIX_NO_TRUNC 1 #define _POSIX_RAW_SOCKETS _POSIX_VERSION + +#ifndef __EMSCRIPTEN__ #define _POSIX_REALTIME_SIGNALS _POSIX_VERSION +#else +#define _POSIX_REALTIME_SIGNALS -1 +#endif + #define _POSIX_REGEXP 1 #define _POSIX_SAVED_IDS 1 #define _POSIX_SHELL 1 + +#ifndef __EMSCRIPTEN__ #define _POSIX_SPAWN _POSIX_VERSION +#else +#define _POSIX_SPAWN -1 +#endif + #define _POSIX_VDISABLE 0 #define _POSIX_THREADS _POSIX_VERSION @@ -245,7 +267,9 @@ int eaccess(const char *, int); #define _POSIX_READER_WRITER_LOCKS _POSIX_VERSION #define _POSIX_ASYNCHRONOUS_IO _POSIX_VERSION #define _POSIX_SEMAPHORES _POSIX_VERSION +#ifndef __EMSCRIPTEN__ #define _POSIX_SHARED_MEMORY_OBJECTS _POSIX_VERSION +#endif #define _POSIX2_C_BIND _POSIX_VERSION diff --git a/ldso/dlstart.c b/ldso/dlstart.c index 4dbe1784..200ab8ff 100644 --- a/ldso/dlstart.c +++ b/ldso/dlstart.c @@ -1,3 +1,10 @@ +/* + * Copyright 2017 The Emscripten Authors. All rights reserved. + * Emscripten is available under two separate licenses, the MIT license and the + * University of Illinois/NCSA Open Source License. Both these licenses can be + * found in the LICENSE file. + */ + #include #include "dynlink.h" diff --git a/ldso/dynlink.c b/ldso/dynlink.c index e458f386..77ec2616 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1,3 +1,10 @@ +/* + * Copyright 2017 The Emscripten Authors. All rights reserved. + * Emscripten is available under two separate licenses, the MIT license and the + * University of Illinois/NCSA Open Source License. Both these licenses can be + * found in the LICENSE file. + */ + #define _GNU_SOURCE #include #include diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index b8b761d0..c17d1fce 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -23,22 +23,22 @@ long sysconf(int name) { - static const short values[] = { - [_SC_ARG_MAX] = JT_ARG_MAX, - [_SC_CHILD_MAX] = RLIM(NPROC), + static const int values[] = { // XXX EMSCRIPTEN int instead of short + [_SC_ARG_MAX] = 2097152, // XXX EMSCRIPTEN replace JT_ARG_MAX, + [_SC_CHILD_MAX] = 47839, // XXX EMSCRIPTEN replace RLIM(NPROC), [_SC_CLK_TCK] = 100, - [_SC_NGROUPS_MAX] = 32, - [_SC_OPEN_MAX] = RLIM(NOFILE), - [_SC_STREAM_MAX] = -1, + [_SC_NGROUPS_MAX] = 65536, // XXX EMSCRIPTEN replace 32, + [_SC_OPEN_MAX] = 1024, // XXX EMSCRIPTEN replace RLIM(NOFILE), + [_SC_STREAM_MAX] = 16, // XXX EMSCRIPTEN replace -1 [_SC_TZNAME_MAX] = TZNAME_MAX, [_SC_JOB_CONTROL] = 1, [_SC_SAVED_IDS] = 1, - [_SC_REALTIME_SIGNALS] = 1, - [_SC_PRIORITY_SCHEDULING] = -1, + [_SC_REALTIME_SIGNALS] = 200809, // XXX EMSCRIPTEN replace 1, + [_SC_PRIORITY_SCHEDULING] = 200809, // XXX EMSCRIPTEN replace -1, [_SC_TIMERS] = VER, [_SC_ASYNCHRONOUS_IO] = VER, - [_SC_PRIORITIZED_IO] = -1, - [_SC_SYNCHRONIZED_IO] = -1, + [_SC_PRIORITIZED_IO] = VER, // XXX EMSCRIPTEN replace -1 + [_SC_SYNCHRONIZED_IO] = 200809, // XXX EMSCRIPTEN replace -1, [_SC_FSYNC] = VER, [_SC_MAPPED_FILES] = VER, [_SC_MEMLOCK] = VER, @@ -49,46 +49,46 @@ long sysconf(int name) [_SC_SHARED_MEMORY_OBJECTS] = VER, [_SC_AIO_LISTIO_MAX] = -1, [_SC_AIO_MAX] = -1, - [_SC_AIO_PRIO_DELTA_MAX] = JT_ZERO, /* ?? */ - [_SC_DELAYTIMER_MAX] = _POSIX_DELAYTIMER_MAX, + [_SC_AIO_PRIO_DELTA_MAX] = 20, // XXX EMSCRIPTEN replace JT_ZERO, /* ?? */ + [_SC_DELAYTIMER_MAX] = 2147483647, // XXX EMSCRIPTEN replace _POSIX_DELAYTIMER_MAX, [_SC_MQ_OPEN_MAX] = -1, [_SC_MQ_PRIO_MAX] = JT_MQ_PRIO_MAX, [_SC_VERSION] = VER, [_SC_PAGE_SIZE] = JT_PAGE_SIZE, - [_SC_RTSIG_MAX] = _NSIG - 1 - 31 - 3, - [_SC_SEM_NSEMS_MAX] = SEM_NSEMS_MAX, + [_SC_RTSIG_MAX] = 32, // XXX EMSCRIPTEN replace _NSIG - 1 - 31 - 3, + [_SC_SEM_NSEMS_MAX] = -1, // XXX EMSCRIPTEN replace SEM_NSEMS_MAX, [_SC_SEM_VALUE_MAX] = JT_SEM_VALUE_MAX, - [_SC_SIGQUEUE_MAX] = -1, + [_SC_SIGQUEUE_MAX] = 47839, // XXX EMSCRIPTEN replace -1, [_SC_TIMER_MAX] = -1, [_SC_BC_BASE_MAX] = _POSIX2_BC_BASE_MAX, [_SC_BC_DIM_MAX] = _POSIX2_BC_DIM_MAX, [_SC_BC_SCALE_MAX] = _POSIX2_BC_SCALE_MAX, [_SC_BC_STRING_MAX] = _POSIX2_BC_STRING_MAX, - [_SC_COLL_WEIGHTS_MAX] = COLL_WEIGHTS_MAX, - [_SC_EXPR_NEST_MAX] = -1, - [_SC_LINE_MAX] = -1, - [_SC_RE_DUP_MAX] = RE_DUP_MAX, + [_SC_COLL_WEIGHTS_MAX] = 255, // XXX EMSCRIPTEN replace COLL_WEIGHTS_MAX, + [_SC_EXPR_NEST_MAX] = 32, // XXX EMSCRIPTEN replace -1, + [_SC_LINE_MAX] = 2048, // XXX EMSCRIPTEN replace -1, + [_SC_RE_DUP_MAX] = 32767, // XXX EMSCRIPTEN replace RE_DUP_MAX, [_SC_2_VERSION] = VER, [_SC_2_C_BIND] = VER, - [_SC_2_C_DEV] = -1, + [_SC_2_C_DEV] = 200809, // XXX EMSCRIPTEN replace -1, [_SC_2_FORT_DEV] = -1, [_SC_2_FORT_RUN] = -1, - [_SC_2_SW_DEV] = -1, - [_SC_2_LOCALEDEF] = -1, + [_SC_2_SW_DEV] = 200809, // XXX EMSCRIPTEN replace -1, + [_SC_2_LOCALEDEF] = 200809, // XXX EMSCRIPTEN replace -1, [_SC_IOV_MAX] = IOV_MAX, [_SC_THREADS] = VER, [_SC_THREAD_SAFE_FUNCTIONS] = VER, - [_SC_GETGR_R_SIZE_MAX] = -1, - [_SC_GETPW_R_SIZE_MAX] = -1, + [_SC_GETGR_R_SIZE_MAX] = 1024, // XXX EMSCRIPTEN replace -1, + [_SC_GETPW_R_SIZE_MAX] = 1024, // XXX EMSCRIPTEN replace -1, [_SC_LOGIN_NAME_MAX] = 256, [_SC_TTY_NAME_MAX] = TTY_NAME_MAX, [_SC_THREAD_DESTRUCTOR_ITERATIONS] = PTHREAD_DESTRUCTOR_ITERATIONS, - [_SC_THREAD_KEYS_MAX] = PTHREAD_KEYS_MAX, - [_SC_THREAD_STACK_MIN] = PTHREAD_STACK_MIN, + [_SC_THREAD_KEYS_MAX] = 1024, // XXX EMSCRIPTEN replace PTHREAD_KEYS_MAX, + [_SC_THREAD_STACK_MIN] = 16384, // XXX EMSCRIPTEN replace PTHREAD_STACK_MIN, [_SC_THREAD_THREADS_MAX] = -1, [_SC_THREAD_ATTR_STACKADDR] = VER, [_SC_THREAD_ATTR_STACKSIZE] = VER, - [_SC_THREAD_PRIORITY_SCHEDULING] = VER, + [_SC_THREAD_PRIORITY_SCHEDULING] = -1, // XXX EMSCRIPTEN replace VER, [_SC_THREAD_PRIO_INHERIT] = -1, [_SC_THREAD_PRIO_PROTECT] = -1, [_SC_THREAD_PROCESS_SHARED] = VER, @@ -96,27 +96,27 @@ long sysconf(int name) [_SC_NPROCESSORS_ONLN] = JT_NPROCESSORS_ONLN, [_SC_PHYS_PAGES] = JT_PHYS_PAGES, [_SC_AVPHYS_PAGES] = JT_AVPHYS_PAGES, - [_SC_ATEXIT_MAX] = -1, + [_SC_ATEXIT_MAX] = 2147483647, // XXX EMSCRIPTEN replace -1, [_SC_PASS_MAX] = -1, [_SC_XOPEN_VERSION] = _XOPEN_VERSION, [_SC_XOPEN_XCU_VERSION] = _XOPEN_VERSION, [_SC_XOPEN_UNIX] = 1, - [_SC_XOPEN_CRYPT] = -1, + [_SC_XOPEN_CRYPT] = 1, // XXX EMSCRIPTEN replace -1, [_SC_XOPEN_ENH_I18N] = 1, [_SC_XOPEN_SHM] = 1, - [_SC_2_CHAR_TERM] = -1, + [_SC_2_CHAR_TERM] = 200809, // XXX EMSCRIPTEN replace -1, [_SC_2_UPE] = -1, [_SC_XOPEN_XPG2] = -1, [_SC_XOPEN_XPG3] = -1, [_SC_XOPEN_XPG4] = -1, [_SC_NZERO] = NZERO, - [_SC_XBS5_ILP32_OFF32] = -1, + [_SC_XBS5_ILP32_OFF32] = 1, // XXX EMSCRIPTEN replace -1, [_SC_XBS5_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : JT_ZERO, - [_SC_XBS5_LP64_OFF64] = sizeof(long)==8 ? 1 : JT_ZERO, + [_SC_XBS5_LP64_OFF64] = -1, // XXX EMSCRIPTEN replace sizeof(long)==8 ? 1 : JT_ZERO, [_SC_XBS5_LPBIG_OFFBIG] = -1, - [_SC_XOPEN_LEGACY] = -1, - [_SC_XOPEN_REALTIME] = -1, - [_SC_XOPEN_REALTIME_THREADS] = -1, + [_SC_XOPEN_LEGACY] = 1, // XXX EMSCRIPTEN replace -1, + [_SC_XOPEN_REALTIME] = 1, // XXX EMSCRIPTEN replace -1, + [_SC_XOPEN_REALTIME_THREADS] = 1, // XXX EMSCRIPTEN replace -1, [_SC_ADVISORY_INFO] = VER, [_SC_BARRIERS] = VER, [_SC_CLOCK_SELECTION] = VER, @@ -137,14 +137,14 @@ long sysconf(int name) [_SC_2_PBS_LOCATE] = -1, [_SC_2_PBS_MESSAGE] = -1, [_SC_2_PBS_TRACK] = -1, - [_SC_SYMLOOP_MAX] = SYMLOOP_MAX, + [_SC_SYMLOOP_MAX] = -1, // XXX EMSCRIPTEN replace SYMLOOP_MAX, [_SC_STREAMS] = JT_ZERO, [_SC_2_PBS_CHECKPOINT] = -1, - [_SC_V6_ILP32_OFF32] = -1, + [_SC_V6_ILP32_OFF32] = 1, // XXX EMSCRIPTEN replace -1, [_SC_V6_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : JT_ZERO, - [_SC_V6_LP64_OFF64] = sizeof(long)==8 ? 1 : JT_ZERO, + [_SC_V6_LP64_OFF64] = -1, // XXX EMSCRIPTEN replace sizeof(long)==8 ? 1 : JT_ZERO, [_SC_V6_LPBIG_OFFBIG] = -1, - [_SC_HOST_NAME_MAX] = HOST_NAME_MAX, + [_SC_HOST_NAME_MAX] = 64, // XXX EMSCRIPTEN replace HOST_NAME_MAX, [_SC_TRACE] = -1, [_SC_TRACE_EVENT_FILTER] = -1, [_SC_TRACE_INHERIT] = -1, @@ -161,7 +161,7 @@ long sysconf(int name) [_SC_TRACE_NAME_MAX] = -1, [_SC_TRACE_SYS_MAX] = -1, [_SC_TRACE_USER_EVENT_MAX] = -1, - [_SC_XOPEN_STREAMS] = JT_ZERO, + [_SC_XOPEN_STREAMS] = -1, // XXX EMSCRIPTEN replace JT_ZERO, [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1, [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1, }; @@ -190,14 +190,23 @@ long sysconf(int name) return SEM_VALUE_MAX; case JT_NPROCESSORS_CONF & 255: case JT_NPROCESSORS_ONLN & 255: ; +#ifdef __EMSCRIPTEN__ + errno = ENOSYS; + return -1; +#else unsigned char set[128] = {1}; int i, cnt; __syscall(SYS_sched_getaffinity, 0, sizeof set, set); for (i=cnt=0; i LONG_MAX) ? LONG_MAX : mem; +#endif case JT_ZERO & 255: return 0; } diff --git a/src/dirent/opendir.c b/src/dirent/opendir.c index 5cb84e30..40068bec 100644 --- a/src/dirent/opendir.c +++ b/src/dirent/opendir.c @@ -13,7 +13,11 @@ DIR *opendir(const char *name) if ((fd = open(name, O_RDONLY|O_DIRECTORY|O_CLOEXEC)) < 0) return 0; if (!(dir = calloc(1, sizeof *dir))) { +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd); +#else __syscall(SYS_close, fd); +#endif return 0; } dir->fd = fd; diff --git a/src/env/__environ.c b/src/env/__environ.c index e6c6faa5..9b708fad 100644 --- a/src/env/__environ.c +++ b/src/env/__environ.c @@ -1,6 +1,42 @@ #include "libc.h" +#ifdef __EMSCRIPTEN__ +#include +#include +#endif + char **__environ = 0; weak_alias(__environ, ___environ); weak_alias(__environ, _environ); weak_alias(__environ, environ); + +#ifdef __EMSCRIPTEN__ +__attribute__((constructor(100))) // construct this before user code +void __emscripten_environ_constructor(void) { + size_t environ_count; + size_t environ_buf_size; + __wasi_errno_t err = __wasi_environ_sizes_get(&environ_count, + &environ_buf_size); + if (err != __WASI_ERRNO_SUCCESS) { + return; + } + + __environ = malloc(sizeof(char *) * (environ_count + 1)); + if (__environ == 0) { + return; + } + char *environ_buf = malloc(sizeof(char) * environ_buf_size); + if (environ_buf == 0) { + __environ = 0; + return; + } + + // Ensure null termination. + __environ[environ_count] = 0; + + err = __wasi_environ_get((uint8_t**)__environ, environ_buf); + if (err != __WASI_ERRNO_SUCCESS) { + __environ = 0; + } +} +#endif diff --git a/src/errno/__errno_location.c b/src/errno/__errno_location.c index 7172a1be..5a674420 100644 --- a/src/errno/__errno_location.c +++ b/src/errno/__errno_location.c @@ -1,6 +1,19 @@ #include "pthread_impl.h" +#if __EMSCRIPTEN_PTHREADS__ +// for pthreads, use the proper location on the thread info, so each +// thread has its own errno int *__errno_location(void) { return &__pthread_self()->errno_val; } +#else +// for single-threaded mode, avoid linking in pthreads support code +// just for this +static int __errno_storage = 0; + +int *__errno_location(void) +{ + return &__errno_storage; +} +#endif diff --git a/src/fcntl/fcntl.c b/src/fcntl/fcntl.c index ce615d0e..2b7c3df2 100644 --- a/src/fcntl/fcntl.c +++ b/src/fcntl/fcntl.c @@ -24,17 +24,25 @@ int fcntl(int fd, int cmd, ...) if (cmd == F_DUPFD_CLOEXEC) { int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg); if (ret != -EINVAL) { +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); +#endif return __syscall_ret(ret); } ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0); if (ret != -EINVAL) { +#ifdef __EMSCRIPTEN__ + if (ret >= 0) __wasi_fd_close(ret); +#else if (ret >= 0) __syscall(SYS_close, ret); +#endif return __syscall_ret(-EINVAL); } ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg); +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); +#endif return __syscall_ret(ret); } switch (cmd) { diff --git a/src/fcntl/open.c b/src/fcntl/open.c index 3928a6e6..fd425856 100644 --- a/src/fcntl/open.c +++ b/src/fcntl/open.c @@ -15,8 +15,10 @@ int open(const char *filename, int flags, ...) } int fd = __sys_open_cp(filename, flags, mode); +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process if (fd>=0 && (flags & O_CLOEXEC)) __syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC); +#endif return __syscall_ret(fd); } diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c index eef70df9..8c0828fc 100644 --- a/src/internal/floatscan.c +++ b/src/internal/floatscan.c @@ -33,9 +33,6 @@ #define MASK (KMAX-1) -#define CONCAT2(x,y) x ## y -#define CONCAT(x,y) CONCAT2(x,y) - static long long scanexp(FILE *f, int pok) { int c; @@ -110,7 +107,10 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po gotdig=1; } else { dc++; - if (c!='0') x[KMAX-4] |= 1; + if (c!='0') { + lnz = (KMAX-4)*9; + x[KMAX-4] |= 1; + } } } if (!gotrad) lrp=dc; @@ -172,6 +172,9 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po return sign * (long double)x[0] * p10s[rp-10]; } + /* Drop trailing zeros */ + for (; !x[z-1]; z--); + /* Align radix point to B1B digit boundary */ if (rp % 9) { int rpm9 = rp>=0 ? rp%9 : rp%9+9; @@ -295,7 +298,7 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po y -= bias; if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { - if (fabs(y) >= CONCAT(0x1p, LDBL_MANT_DIG)) { + if (fabsl(y) >= 2/LDBL_EPSILON) { if (denormal && bits==LDBL_MANT_DIG+e2-emin) denormal = 0; y *= 0.5; diff --git a/src/internal/libc.c b/src/internal/libc.c index 2e10942d..6e4f0468 100644 --- a/src/internal/libc.c +++ b/src/internal/libc.c @@ -8,3 +8,10 @@ char *__progname=0, *__progname_full=0; weak_alias(__progname, program_invocation_short_name); weak_alias(__progname_full, program_invocation_name); + +#ifdef __EMSCRIPTEN_PTHREADS__ +#include +struct __libc* EMSCRIPTEN_KEEPALIVE emscripten_get_global_libc() { + return &libc; +} +#endif diff --git a/src/internal/libm.h b/src/internal/libm.h index df864111..6a3aaed5 100644 --- a/src/internal/libm.h +++ b/src/internal/libm.h @@ -60,6 +60,13 @@ union ldshape { #error Unsupported long double representation #endif +#ifdef __EMSCRIPTEN__ +/* + * asm.js doesn't have user-accessible floating point exceptions, so there's + * no point in trying to force expression evaluations to produce them. + */ +#define FORCE_EVAL(x) +#else #define FORCE_EVAL(x) do { \ if (sizeof(x) == sizeof(float)) { \ volatile float __x; \ @@ -72,6 +79,7 @@ union ldshape { __x = (x); \ } \ } while(0) +#endif /* Get two 32 bit ints from a double. */ #define EXTRACT_WORDS(hi,lo,d) \ diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 3890bb56..bcdda727 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -8,16 +8,28 @@ #include "libc.h" #include "syscall.h" #include "atomic.h" +#ifdef __EMSCRIPTEN__ +#include +#endif #include "futex.h" #define pthread __pthread struct pthread { +// XXX Emscripten: Need some custom thread control structures. +#ifdef __EMSCRIPTEN__ + // Note: The specific order of these fields is important, since these are accessed + // by direct pointer arithmetic in worker.js. + int threadStatus; // 0: thread not exited, 1: exited. + int threadExitCode; // Thread exit code. + void *profilerBlock; // If --threadprofiling is enabled, this pointer is allocated to contain internal information about the thread state for profiling purposes. +#endif + struct pthread *self; void **dtv, *unused1, *unused2; uintptr_t sysinfo; uintptr_t canary, canary2; - pid_t tid, pid; + pid_t tid; int tsd_used, errno_val; volatile int cancel, canceldisable, cancelasync; int detached; @@ -81,6 +93,12 @@ struct __timer { #define _rw_lock __u.__vi[0] #define _rw_waiters __u.__vi[1] #define _rw_shared __u.__i[2] +#ifdef __EMSCRIPTEN__ +// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, so use an extra field +// _rw_wr_owner to record which thread owns the write lock in order to avoid hangs. +// Points to the pthread that currently has the write lock. +#define _rw_wr_owner __u.__vi[3] +#endif #define _b_lock __u.__vi[0] #define _b_waiters __u.__vi[1] #define _b_limit __u.__i[2] @@ -130,8 +148,12 @@ static inline void __wake(volatile void *addr, int cnt, int priv) { if (priv) priv = 128; if (cnt<0) cnt = INT_MAX; +#ifdef __EMSCRIPTEN__ + emscripten_futex_wake(addr, (cnt)<0?INT_MAX:(cnt)); +#else __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS || __syscall(SYS_futex, addr, FUTEX_WAKE, cnt); +#endif } void __acquire_ptc(void); @@ -147,4 +169,10 @@ void __restore_sigs(void *); #define __ATTRP_C11_THREAD ((void*)(uintptr_t)-1) +#ifdef __EMSCRIPTEN__ +void __emscripten_init_pthread(pthread_t thread); +#if !__EMSCRIPTEN_PTHREADS__ +pthread_t __emscripten_pthread_stub(void); +#endif +#endif #endif diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h index 7cdf729d..7abd62e2 100644 --- a/src/internal/stdio_impl.h +++ b/src/internal/stdio_impl.h @@ -61,7 +61,7 @@ size_t __string_read(FILE *, unsigned char *, size_t); int __toread(FILE *); int __towrite(FILE *); -#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303) +#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303) && !defined(__EMSCRIPTEN__) __attribute__((visibility("protected"))) #endif int __overflow(FILE *, int), __uflow(FILE *); @@ -94,4 +94,12 @@ void __ofl_unlock(void); FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t); int __fclose_ca(FILE *); +// XXX EMSCRIPTEN +extern int vfiprintf(FILE *restrict f, const char *restrict fmt, va_list ap); +extern int vsiprintf(char *restrict s, const char *restrict fmt, va_list ap); +extern int vsniprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap); +extern int __small_vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap); +extern int __small_vsprintf(char *restrict s, const char *restrict fmt, va_list ap); +extern int __small_vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap); + #endif diff --git a/src/internal/syscall.h b/src/internal/syscall.h index ff3cf53a..b60fce0a 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -17,11 +17,18 @@ typedef long syscall_arg_t; #endif +#ifdef __cplusplus +extern "C" { +#endif __attribute__((visibility("hidden"))) long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), __syscall_cp(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t); +#ifdef __cplusplus +} +#endif +#ifndef __EMSCRIPTEN__ #ifdef SYSCALL_NO_INLINE #define __syscall0(n) (__syscall)(n) #define __syscall1(n,a) (__syscall)(n,__scc(a)) @@ -39,6 +46,17 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #define __syscall6(n,a,b,c,d,e,f) __syscall6(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) #endif #define __syscall7(n,a,b,c,d,e,f,g) (__syscall)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) +#else // __EMSCRIPTEN__ +#define __syscall_emscripten(n, ...) __syscall##n(__VA_ARGS__) +#define __syscall_emscripten0(n) __syscall_emscripten(n) +#define __syscall_emscripten1(n,a) __syscall_emscripten(n,__scc(a)) +#define __syscall_emscripten2(n,a,b) __syscall_emscripten(n,__scc(a),__scc(b)) +#define __syscall_emscripten3(n,a,b,c) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c)) +#define __syscall_emscripten4(n,a,b,c,d) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c),__scc(d)) +#define __syscall_emscripten5(n,a,b,c,d,e) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) +#define __syscall_emscripten6(n,a,b,c,d,e,f) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) +#define __syscall_emscripten7(n,a,b,c,d,e,f,g) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) +#endif // __EMSCRIPTEN__ #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,) @@ -46,12 +64,18 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X(a,b) #define __SYSCALL_DISP(b,...) __SYSCALL_CONCAT(b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) +#ifndef __EMSCRIPTEN__ #define __syscall(...) __SYSCALL_DISP(__syscall,__VA_ARGS__) +#else +#define __syscall(...) __SYSCALL_DISP(__syscall_emscripten,__VA_ARGS__) +#endif + #define syscall(...) __syscall_ret(__syscall(__VA_ARGS__)) #define socketcall __socketcall #define socketcall_cp __socketcall_cp +#ifndef __EMSCRIPTEN__ #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) @@ -61,6 +85,11 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #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_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) +#else // __EMSCRIPTEN__ +#define __syscall_cp(...) __syscall(__VA_ARGS__) +#define SYSCALL_USE_SOCKETCALL +#endif // __EMSCRIPTEN__ + #define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) #ifndef SYSCALL_USE_SOCKETCALL @@ -222,6 +251,7 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #define __SC_recvmmsg 19 #define __SC_sendmmsg 20 +#ifndef __EMSCRIPTEN__ #ifdef SYS_open #define __sys_open2(x,pn,fl) __syscall2(SYS_open, pn, (fl)|O_LARGEFILE) #define __sys_open3(x,pn,fl,mo) __syscall3(SYS_open, pn, (fl)|O_LARGEFILE, mo) @@ -233,7 +263,12 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #define __sys_open_cp2(x,pn,fl) __syscall_cp3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) #define __sys_open_cp3(x,pn,fl,mo) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) #endif - +#else // __EMSCRIPTEN__ +#define __sys_open2(x,pn,fl) __SYSCALL_CONCAT(__syscall, SYS_open)(__scc(pn), __scc((fl)|O_LARGEFILE)) +#define __sys_open3(x,pn,fl,mo) __SYSCALL_CONCAT(__syscall, SYS_open)(__scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) +#define __sys_open_cp2(x,pn,fl) __SYSCALL_CONCAT(__syscall, SYS_open)(__scc(pn), __scc((fl)|O_LARGEFILE)) +#define __sys_open_cp3(x,pn,fl,mo) __SYSCALL_CONCAT(__syscall, SYS_open)(__scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) +#endif #define __sys_open(...) __SYSCALL_DISP(__sys_open,,__VA_ARGS__) #define sys_open(...) __syscall_ret(__sys_open(__VA_ARGS__)) diff --git a/src/legacy/getpagesize.c b/src/legacy/getpagesize.c index 0fc29ffc..3d3240bc 100644 --- a/src/legacy/getpagesize.c +++ b/src/legacy/getpagesize.c @@ -4,5 +4,11 @@ int getpagesize(void) { +#if __EMSCRIPTEN__ + // A value used historically in emscripten, and which so far we don't have a + // strong reason to change. + return 16384; +#else return PAGE_SIZE; +#endif } diff --git a/src/linux/sbrk.c b/src/linux/sbrk.c index 1e82d643..909d825b 100644 --- a/src/linux/sbrk.c +++ b/src/linux/sbrk.c @@ -1,3 +1,4 @@ +#if !__EMSCRIPTEN__ /* Emscripten controls sbrk itself */ #include #include #include "syscall.h" @@ -7,3 +8,5 @@ void *sbrk(intptr_t inc) if (inc) return (void *)__syscall_ret(-ENOMEM); return (void *)__syscall(SYS_brk, 0); } +#endif + diff --git a/src/locale/locale_map.c b/src/locale/locale_map.c index c3e59174..ad0c7e82 100644 --- a/src/locale/locale_map.c +++ b/src/locale/locale_map.c @@ -65,6 +65,7 @@ const struct __locale_map *__get_locale(int cat, const char *val) return p; } +#ifndef __EMSCRIPTEN__ // don't support MUSL_LOCPATH which uses mmap if (!libc.secure) path = getenv("MUSL_LOCPATH"); /* FIXME: add a default path? */ @@ -93,6 +94,7 @@ const struct __locale_map *__get_locale(int cat, const char *val) break; } } +#endif /* If no locale definition was found, make a locale map * object anyway to store the name, which is kept for the diff --git a/src/locale/newlocale.c b/src/locale/newlocale.c index f50bbe91..bbc31208 100644 --- a/src/locale/newlocale.c +++ b/src/locale/newlocale.c @@ -41,8 +41,6 @@ locale_t __newlocale(int mask, const char *name, locale_t loc) if (j==1 && tmp.cat[LC_CTYPE]==&__c_dot_utf8) return UTF8_LOCALE; - if ((loc = malloc(sizeof *loc))) *loc = tmp; - return loc; } diff --git a/src/math/ceil.c b/src/math/ceil.c index b13e6f2d..cba7293b 100644 --- a/src/math/ceil.c +++ b/src/math/ceil.c @@ -9,6 +9,11 @@ static const double_t toint = 1/EPS; double ceil(double x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_ceil(x); +#else union {double f; uint64_t i;} u = {x}; int e = u.i >> 52 & 0x7ff; double_t y; @@ -28,4 +33,5 @@ double ceil(double x) if (y < 0) return x + y + 1; return x + y; +#endif } diff --git a/src/math/ceilf.c b/src/math/ceilf.c index 869835f3..9a071337 100644 --- a/src/math/ceilf.c +++ b/src/math/ceilf.c @@ -2,6 +2,11 @@ float ceilf(float x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_ceilf(x); +#else union {float f; uint32_t i;} u = {x}; int e = (int)(u.i >> 23 & 0xff) - 0x7f; uint32_t m; @@ -24,4 +29,5 @@ float ceilf(float x) u.f = 1.0; } return u.f; +#endif } diff --git a/src/math/copysign.c b/src/math/copysign.c index b09331b6..1fc78c9f 100644 --- a/src/math/copysign.c +++ b/src/math/copysign.c @@ -1,8 +1,14 @@ #include "libm.h" double copysign(double x, double y) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_copysign(x, y); +#else union {double f; uint64_t i;} ux={x}, uy={y}; ux.i &= -1ULL/2; ux.i |= uy.i & 1ULL<<63; return ux.f; +#endif } diff --git a/src/math/copysignf.c b/src/math/copysignf.c index 0af6ae9b..76d2d255 100644 --- a/src/math/copysignf.c +++ b/src/math/copysignf.c @@ -3,8 +3,14 @@ float copysignf(float x, float y) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_copysignf(x, y); +#else union {float f; uint32_t i;} ux={x}, uy={y}; ux.i &= 0x7fffffff; ux.i |= uy.i & 0x80000000; return ux.f; +#endif } diff --git a/src/math/fabs.c b/src/math/fabs.c index e8258cfd..566a461f 100644 --- a/src/math/fabs.c +++ b/src/math/fabs.c @@ -3,7 +3,13 @@ double fabs(double x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_fabs(x); +#else union {double f; uint64_t i;} u = {x}; u.i &= -1ULL/2; return u.f; +#endif } diff --git a/src/math/fabsf.c b/src/math/fabsf.c index 4efc8d68..1ff074a7 100644 --- a/src/math/fabsf.c +++ b/src/math/fabsf.c @@ -3,7 +3,13 @@ float fabsf(float x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_fabsf(x); +#else union {float f; uint32_t i;} u = {x}; u.i &= 0x7fffffff; return u.f; +#endif } diff --git a/src/math/floor.c b/src/math/floor.c index 14a31cd8..0459dfba 100644 --- a/src/math/floor.c +++ b/src/math/floor.c @@ -9,6 +9,11 @@ static const double_t toint = 1/EPS; double floor(double x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_floor(x); +#else union {double f; uint64_t i;} u = {x}; int e = u.i >> 52 & 0x7ff; double_t y; @@ -28,4 +33,5 @@ double floor(double x) if (y > 0) return x + y - 1; return x + y; +#endif } diff --git a/src/math/floorf.c b/src/math/floorf.c index dceec739..4552d38b 100644 --- a/src/math/floorf.c +++ b/src/math/floorf.c @@ -2,6 +2,11 @@ float floorf(float x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_floorf(x); +#else union {float f; uint32_t i;} u = {x}; int e = (int)(u.i >> 23 & 0xff) - 0x7f; uint32_t m; @@ -24,4 +29,5 @@ float floorf(float x) u.f = -1.0; } return u.f; +#endif } diff --git a/src/math/fma.c b/src/math/fma.c index 741ccd75..38e0866f 100644 --- a/src/math/fma.c +++ b/src/math/fma.c @@ -79,7 +79,9 @@ static int getexp(long double x) double fma(double x, double y, double z) { +#ifndef __EMSCRIPTEN__ #pragma STDC FENV_ACCESS ON +#endif long double hi, lo1, lo2, xy; int round, ez, exy; @@ -331,7 +333,9 @@ static inline struct dd dd_mul(double a, double b) */ double fma(double x, double y, double z) { +#ifndef __EMSCRIPTEN__ #pragma STDC FENV_ACCESS ON +#endif double xs, ys, zs, adj; struct dd xy, r; int oround; diff --git a/src/math/fmaf.c b/src/math/fmaf.c index aa57feb6..f3d232b1 100644 --- a/src/math/fmaf.c +++ b/src/math/fmaf.c @@ -38,7 +38,9 @@ */ float fmaf(float x, float y, float z) { +#ifndef __EMSCRIPTEN__ #pragma STDC FENV_ACCESS ON +#endif double xy, result; union {double f; uint64_t i;} u; int e; diff --git a/src/math/fmal.c b/src/math/fmal.c index 4506aac6..ac8ecbbb 100644 --- a/src/math/fmal.c +++ b/src/math/fmal.c @@ -164,7 +164,9 @@ static inline struct dd dd_mul(long double a, long double b) */ long double fmal(long double x, long double y, long double z) { +#ifndef __EMSCRIPTEN__ #pragma STDC FENV_ACCESS ON +#endif long double xs, ys, zs, adj; struct dd xy, r; int oround; diff --git a/src/math/fmax.c b/src/math/fmax.c index 94f0caa1..2018a78c 100644 --- a/src/math/fmax.c +++ b/src/math/fmax.c @@ -6,8 +6,13 @@ double fmax(double x, double y) return y; if (isnan(y)) return x; +// XXX EMSCRIPTEN: use wasm builtins for code size +#ifdef __wasm__ + return __builtin_wasm_max_f64(x, y); +#else /* handle signed zeros, see C99 Annex F.9.9.2 */ if (signbit(x) != signbit(y)) return signbit(x) ? y : x; return x < y ? y : x; +#endif } diff --git a/src/math/fmaxf.c b/src/math/fmaxf.c index 695d8179..8524cee4 100644 --- a/src/math/fmaxf.c +++ b/src/math/fmaxf.c @@ -6,8 +6,13 @@ float fmaxf(float x, float y) return y; if (isnan(y)) return x; +// XXX EMSCRIPTEN: use wasm builtins for code size +#ifdef __wasm__ + return __builtin_wasm_max_f32(x, y); +#else /* handle signed zeroes, see C99 Annex F.9.9.2 */ if (signbit(x) != signbit(y)) return signbit(x) ? y : x; return x < y ? y : x; +#endif } diff --git a/src/math/fmin.c b/src/math/fmin.c index 08a8fd17..2334d7b8 100644 --- a/src/math/fmin.c +++ b/src/math/fmin.c @@ -6,8 +6,13 @@ double fmin(double x, double y) return y; if (isnan(y)) return x; +// XXX EMSCRIPTEN: use wasm builtins for code size +#ifdef __wasm__ + return __builtin_wasm_min_f64(x, y); +#else /* handle signed zeros, see C99 Annex F.9.9.2 */ if (signbit(x) != signbit(y)) return signbit(x) ? x : y; return x < y ? x : y; +#endif } diff --git a/src/math/fminf.c b/src/math/fminf.c index 3573c7de..bfbaafce 100644 --- a/src/math/fminf.c +++ b/src/math/fminf.c @@ -6,8 +6,13 @@ float fminf(float x, float y) return y; if (isnan(y)) return x; +// XXX EMSCRIPTEN: use wasm builtins for code size +#ifdef __wasm__ + return __builtin_wasm_min_f32(x, y); +#else /* handle signed zeros, see C99 Annex F.9.9.2 */ if (signbit(x) != signbit(y)) return signbit(x) ? x : y; return x < y ? x : y; +#endif } diff --git a/src/math/ilogb.c b/src/math/ilogb.c index 64d40154..a52d78ef 100644 --- a/src/math/ilogb.c +++ b/src/math/ilogb.c @@ -3,7 +3,9 @@ int ilogb(double x) { +#ifndef __EMSCRIPTEN__ #pragma STDC FENV_ACCESS ON +#endif union {double f; uint64_t i;} u = {x}; uint64_t i = u.i; int e = i>>52 & 0x7ff; diff --git a/src/math/ilogbf.c b/src/math/ilogbf.c index e23ba209..18aef0ae 100644 --- a/src/math/ilogbf.c +++ b/src/math/ilogbf.c @@ -3,7 +3,9 @@ int ilogbf(float x) { +#ifndef __EMSCRIPTEN__ #pragma STDC FENV_ACCESS ON +#endif union {float f; uint32_t i;} u = {x}; uint32_t i = u.i; int e = i>>23 & 0xff; diff --git a/src/math/ilogbl.c b/src/math/ilogbl.c index 7b1a9cf8..9931cac5 100644 --- a/src/math/ilogbl.c +++ b/src/math/ilogbl.c @@ -9,7 +9,9 @@ int ilogbl(long double x) #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 int ilogbl(long double x) { +#ifndef __EMSCRIPTEN__ #pragma STDC FENV_ACCESS ON +#endif union ldshape u = {x}; uint64_t m = u.i.m; int e = u.i.se & 0x7fff; @@ -32,7 +34,9 @@ int ilogbl(long double x) #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 int ilogbl(long double x) { +#ifndef __EMSCRIPTEN__ #pragma STDC FENV_ACCESS ON +#endif union ldshape u = {x}; int e = u.i.se & 0x7fff; diff --git a/src/math/rint.c b/src/math/rint.c index fbba390e..690f3e02 100644 --- a/src/math/rint.c +++ b/src/math/rint.c @@ -11,6 +11,11 @@ static const double_t toint = 1/EPS; double rint(double x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_rint(x); +#else union {double f; uint64_t i;} u = {x}; int e = u.i>>52 & 0x7ff; int s = u.i>>63; @@ -25,4 +30,5 @@ double rint(double x) if (y == 0) return s ? -0.0 : 0; return y; +#endif } diff --git a/src/math/rintf.c b/src/math/rintf.c index 9047688d..e393c88a 100644 --- a/src/math/rintf.c +++ b/src/math/rintf.c @@ -13,6 +13,11 @@ static const float_t toint = 1/EPS; float rintf(float x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_rintf(x); +#else union {float f; uint32_t i;} u = {x}; int e = u.i>>23 & 0xff; int s = u.i>>31; @@ -27,4 +32,5 @@ float rintf(float x) if (y == 0) return s ? -0.0f : 0.0f; return y; +#endif } diff --git a/src/math/sqrt.c b/src/math/sqrt.c index b2775673..e612a1c6 100644 --- a/src/math/sqrt.c +++ b/src/math/sqrt.c @@ -82,6 +82,11 @@ static const double tiny = 1.0e-300; double sqrt(double x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_sqrt(x); +#else double z; int32_t sign = (int)0x80000000; int32_t ix0,s0,q,m,t,i; @@ -182,4 +187,5 @@ double sqrt(double x) ix0 += m << 20; INSERT_WORDS(z, ix0, ix1); return z; +#endif } diff --git a/src/math/sqrtf.c b/src/math/sqrtf.c index 28cb4ad3..fc58451e 100644 --- a/src/math/sqrtf.c +++ b/src/math/sqrtf.c @@ -19,6 +19,11 @@ static const float tiny = 1.0e-30; float sqrtf(float x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_sqrtf(x); +#else float z; int32_t sign = (int)0x80000000; int32_t ix,s,q,m,t,i; @@ -81,4 +86,5 @@ float sqrtf(float x) ix += m << 23; SET_FLOAT_WORD(z, ix); return z; +#endif } diff --git a/src/math/trunc.c b/src/math/trunc.c index d13711b5..c6d25ec1 100644 --- a/src/math/trunc.c +++ b/src/math/trunc.c @@ -2,6 +2,11 @@ double trunc(double x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_trunc(x); +#else union {double f; uint64_t i;} u = {x}; int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12; uint64_t m; @@ -16,4 +21,5 @@ double trunc(double x) FORCE_EVAL(x + 0x1p120f); u.i &= ~m; return u.f; +#endif } diff --git a/src/math/truncf.c b/src/math/truncf.c index 1a7d03c3..3c9f7f46 100644 --- a/src/math/truncf.c +++ b/src/math/truncf.c @@ -2,6 +2,11 @@ float truncf(float x) { +// XXX EMSCRIPTEN: use the wasm instruction via clang builtin +// See https://github.com/emscripten-core/emscripten/issues/9236 +#ifdef __wasm__ + return __builtin_truncf(x); +#else union {float f; uint32_t i;} u = {x}; int e = (int)(u.i >> 23 & 0xff) - 0x7f + 9; uint32_t m; @@ -16,4 +21,5 @@ float truncf(float x) FORCE_EVAL(x + 0x1p120f); u.i &= ~m; return u.f; +#endif } diff --git a/src/misc/realpath.c b/src/misc/realpath.c index 88c849cd..975c0fa2 100644 --- a/src/misc/realpath.c +++ b/src/misc/realpath.c @@ -37,9 +37,17 @@ char *realpath(const char *restrict filename, char *restrict resolved) goto err; } +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd); +#else __syscall(SYS_close, fd); +#endif return resolved ? strcpy(resolved, tmp) : strdup(tmp); err: +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd); +#else __syscall(SYS_close, fd); +#endif return 0; } diff --git a/src/network/if_indextoname.c b/src/network/if_indextoname.c index 6ee7f13c..42fe33de 100644 --- a/src/network/if_indextoname.c +++ b/src/network/if_indextoname.c @@ -13,6 +13,10 @@ char *if_indextoname(unsigned index, char *name) if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) return 0; ifr.ifr_ifindex = index; r = ioctl(fd, SIOCGIFNAME, &ifr); +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd); +#else __syscall(SYS_close, fd); +#endif return r < 0 ? 0 : strncpy(name, ifr.ifr_name, IF_NAMESIZE); } diff --git a/src/network/if_nametoindex.c b/src/network/if_nametoindex.c index 331413c6..5d61e579 100644 --- a/src/network/if_nametoindex.c +++ b/src/network/if_nametoindex.c @@ -13,6 +13,10 @@ unsigned if_nametoindex(const char *name) if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) return 0; strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); r = ioctl(fd, SIOCGIFINDEX, &ifr); +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd); +#else __syscall(SYS_close, fd); +#endif return r < 0 ? 0 : ifr.ifr_ifindex; } diff --git a/src/network/netlink.c b/src/network/netlink.c index 94dba7f5..676b65cd 100644 --- a/src/network/netlink.c +++ b/src/network/netlink.c @@ -47,6 +47,10 @@ int __rtnetlink_enumerate(int link_af, int addr_af, int (*cb)(void *ctx, struct if (fd < 0) return -1; r = __netlink_enumerate(fd, 1, RTM_GETLINK, link_af, cb, ctx); if (!r) r = __netlink_enumerate(fd, 2, RTM_GETADDR, addr_af, cb, ctx); +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd); +#else __syscall(SYS_close,fd); +#endif return r; } diff --git a/src/network/ns_parse.c b/src/network/ns_parse.c index d01da47a..71bd309c 100644 --- a/src/network/ns_parse.c +++ b/src/network/ns_parse.c @@ -47,6 +47,30 @@ void ns_put32(unsigned long l, unsigned char *cp) *cp++ = l; } +int ns_skiprr(const unsigned char *ptr, const unsigned char *eom, ns_sect section, int count) +{ + const unsigned char *p = ptr; + int r; + + while (count--) { + r = dn_skipname(p, eom); + if (r < 0) goto bad; + if (r + 2 * NS_INT16SZ > eom - p) goto bad; + p += r + 2 * NS_INT16SZ; + if (section != ns_s_qd) { + if (NS_INT32SZ + NS_INT16SZ > eom - p) goto bad; + p += NS_INT32SZ; + NS_GET16(r, p); + if (r > eom - p) goto bad; + p += r; + } + } + return p - ptr; +bad: + errno = EMSGSIZE; + return -1; +} + int ns_initparse(const unsigned char *msg, int msglen, ns_msg *handle) { int i, r; @@ -77,35 +101,20 @@ int ns_initparse(const unsigned char *msg, int msglen, ns_msg *handle) return -1; } -int ns_skiprr(const unsigned char *ptr, const unsigned char *eom, ns_sect section, int count) +int ns_name_uncompress(const unsigned char *msg, const unsigned char *eom, + const unsigned char *src, char *dst, size_t dstsiz) { - const unsigned char *p = ptr; int r; - - while (count--) { - r = dn_skipname(p, eom); - if (r < 0) goto bad; - if (r + 2 * NS_INT16SZ > eom - p) goto bad; - p += r + 2 * NS_INT16SZ; - if (section != ns_s_qd) { - if (NS_INT32SZ + NS_INT16SZ > eom - p) goto bad; - p += NS_INT32SZ; - NS_GET16(r, p); - if (r > eom - p) goto bad; - p += r; - } - } - return p - ptr; -bad: - errno = EMSGSIZE; - return -1; + r = dn_expand(msg, eom, src, dst, dstsiz); + if (r < 0) errno = EMSGSIZE; + return r; } int ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { int r; - if (section < 0 || section >= ns_s_max) goto bad; + if (section >= ns_s_max) goto bad; if (section != handle->_sect) { handle->_sect = section; handle->_rrnum = 0; @@ -160,12 +169,3 @@ int ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) return -1; } -int ns_name_uncompress(const unsigned char *msg, const unsigned char *eom, - const unsigned char *src, char *dst, size_t dstsiz) -{ - int r; - r = dn_expand(msg, eom, src, dst, dstsiz); - if (r < 0) errno = EMSGSIZE; - return r; -} - diff --git a/src/network/res_msend.c b/src/network/res_msend.c index de7f6157..fd3431f1 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -16,7 +16,11 @@ static void cleanup(void *p) { +#ifdef __EMSCRIPTEN__ + __wasi_fd_close((intptr_t)p); +#else __syscall(SYS_close, (intptr_t)p); +#endif } static unsigned long mtime() diff --git a/src/sched/sched_yield.c b/src/sched/sched_yield.c index ee6f0e7f..3f50030a 100644 --- a/src/sched/sched_yield.c +++ b/src/sched/sched_yield.c @@ -3,5 +3,12 @@ int sched_yield() { +#if __EMSCRIPTEN__ + // SharedArrayBuffer and wasm threads do not support explicit yielding, + // but in practice it should happen automatically well enough anyhow, so + // report success in order to not break apps. + return 0; +#else return syscall(SYS_sched_yield); +#endif } diff --git a/src/stat/fchmod.c b/src/stat/fchmod.c index 93e1b64c..5d90ecce 100644 --- a/src/stat/fchmod.c +++ b/src/stat/fchmod.c @@ -1,3 +1,6 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif #include #include #include @@ -8,8 +11,13 @@ void __procfdname(char *, unsigned); int fchmod(int fd, mode_t mode) { int ret = __syscall(SYS_fchmod, fd, mode); +#if __EMSCRIPTEN__ + if (ret != -EBADF || !__wasi_fd_is_valid(fd)) + return __syscall_ret(ret); +#else if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) return __syscall_ret(ret); +#endif char buf[15+3*sizeof(int)]; __procfdname(buf, fd); diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c index d94667ae..9ff4a592 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -34,6 +34,10 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode); } +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd2); +#else __syscall(SYS_close, fd2); +#endif return __syscall_ret(ret); } diff --git a/src/stat/fstat.c b/src/stat/fstat.c index ab4afc0f..46c53511 100644 --- a/src/stat/fstat.c +++ b/src/stat/fstat.c @@ -1,3 +1,6 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif #include #include #include @@ -9,8 +12,13 @@ void __procfdname(char *, unsigned); int fstat(int fd, struct stat *st) { int ret = __syscall(SYS_fstat, fd, st); +#if __EMSCRIPTEN__ + if (ret != -EBADF || !__wasi_fd_is_valid(fd)) + return __syscall_ret(ret); +#else if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) return __syscall_ret(ret); +#endif char buf[15+3*sizeof(int)]; __procfdname(buf, fd); diff --git a/src/stdio/__fdopen.c b/src/stdio/__fdopen.c index 8d6ce813..eceee1a6 100644 --- a/src/stdio/__fdopen.c +++ b/src/stdio/__fdopen.c @@ -25,8 +25,10 @@ FILE *__fdopen(int fd, const char *mode) /* Impose mode restrictions */ if (!strchr(mode, '+')) f->flags = (*mode == 'r') ? F_NOWR : F_NORD; +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process /* Apply close-on-exec flag */ if (strchr(mode, 'e')) __syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC); +#endif /* Set append mode on fd if opened for append */ if (*mode == 'a') { diff --git a/src/stdio/__fopen_rb_ca.c b/src/stdio/__fopen_rb_ca.c index 183a5d55..2f3acb83 100644 --- a/src/stdio/__fopen_rb_ca.c +++ b/src/stdio/__fopen_rb_ca.c @@ -8,7 +8,9 @@ FILE *__fopen_rb_ca(const char *filename, FILE *f, unsigned char *buf, size_t le f->fd = sys_open(filename, O_RDONLY|O_CLOEXEC); if (f->fd < 0) return 0; +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process __syscall(SYS_fcntl, f->fd, F_SETFD, FD_CLOEXEC); +#endif f->flags = F_NOWR | F_PERM; f->buf = buf + UNGET; diff --git a/src/stdio/__lockfile.c b/src/stdio/__lockfile.c index 9d967d6e..7932d4a1 100644 --- a/src/stdio/__lockfile.c +++ b/src/stdio/__lockfile.c @@ -3,16 +3,19 @@ int __lockfile(FILE *f) { +#if defined(__EMSCRIPTEN_PTHREADS__) int owner, tid = __pthread_self()->tid; if (f->lock == tid) return 0; while ((owner = a_cas(&f->lock, 0, tid))) __wait(&f->lock, &f->waiters, owner, 1); +#endif return 1; } void __unlockfile(FILE *f) { +#if defined(__EMSCRIPTEN_PTHREADS__) a_store(&f->lock, 0); /* The following read is technically invalid under situations @@ -25,4 +28,5 @@ void __unlockfile(FILE *f) * malloc changes, this assumption needs revisiting. */ if (f->waiters) __wake(&f->lock, 1, 1); +#endif } diff --git a/src/stdio/__stdio_close.c b/src/stdio/__stdio_close.c index 79452bdb..0fba4916 100644 --- a/src/stdio/__stdio_close.c +++ b/src/stdio/__stdio_close.c @@ -9,5 +9,9 @@ weak_alias(dummy, __aio_close); int __stdio_close(FILE *f) { +#ifdef __EMSCRIPTEN__ + return __wasi_fd_close(__aio_close(f->fd)); +#else return syscall(SYS_close, __aio_close(f->fd)); +#endif } diff --git a/src/stdio/__stdio_read.c b/src/stdio/__stdio_read.c index f8fa6d3b..bff641e8 100644 --- a/src/stdio/__stdio_read.c +++ b/src/stdio/__stdio_read.c @@ -9,7 +9,15 @@ size_t __stdio_read(FILE *f, unsigned char *buf, size_t len) }; ssize_t cnt; +#if __EMSCRIPTEN__ + size_t num; + if (__wasi_syscall_ret(__wasi_fd_read(f->fd, (struct __wasi_iovec_t*)iov, 2, &num))) { + num = -1; + } + cnt = num; +#else cnt = syscall(SYS_readv, f->fd, iov, 2); +#endif if (cnt <= 0) { f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt); return cnt; diff --git a/src/stdio/__stdio_seek.c b/src/stdio/__stdio_seek.c index 13e06a66..37d09f8d 100644 --- a/src/stdio/__stdio_seek.c +++ b/src/stdio/__stdio_seek.c @@ -3,11 +3,16 @@ off_t __stdio_seek(FILE *f, off_t off, int whence) { off_t ret; +#ifdef __EMSCRIPTEN__ + if (__wasi_syscall_ret(__wasi_fd_seek(f->fd, off, whence, &ret))) + ret = -1; +#else #ifdef SYS__llseek if (syscall(SYS__llseek, f->fd, off>>32, off, &ret, whence)<0) ret = -1; #else ret = syscall(SYS_lseek, f->fd, off, whence); #endif +#endif // __EMSCRIPTEN__ return ret; } diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c index d2d89475..cce9f6a1 100644 --- a/src/stdio/__stdio_write.c +++ b/src/stdio/__stdio_write.c @@ -12,7 +12,15 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len) int iovcnt = 2; ssize_t cnt; for (;;) { +#if __EMSCRIPTEN__ + size_t num; + if (__wasi_syscall_ret(__wasi_fd_write(f->fd, (struct __wasi_ciovec_t*)iov, iovcnt, &num))) { + num = -1; + } + cnt = num; +#else cnt = syscall(SYS_writev, f->fd, iov, iovcnt); +#endif if (cnt == rem) { f->wend = f->buf + f->buf_size; f->wpos = f->wbase = f->buf; diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c index 252f0824..8fa9c63a 100644 --- a/src/stdio/fopen.c +++ b/src/stdio/fopen.c @@ -20,13 +20,19 @@ FILE *fopen(const char *restrict filename, const char *restrict mode) fd = sys_open(filename, flags, 0666); if (fd < 0) return 0; +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process if (flags & O_CLOEXEC) __syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC); +#endif f = __fdopen(fd, mode); if (f) return f; +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd); +#else __syscall(SYS_close, fd); +#endif return 0; } diff --git a/src/stdio/fprintf.c b/src/stdio/fprintf.c index 948743f7..b8b77976 100644 --- a/src/stdio/fprintf.c +++ b/src/stdio/fprintf.c @@ -1,3 +1,4 @@ +#include "stdio_impl.h" #include #include @@ -10,3 +11,24 @@ int fprintf(FILE *restrict f, const char *restrict fmt, ...) va_end(ap); return ret; } + +// XXX EMSCRIPTEN +int fiprintf(FILE *restrict f, const char *restrict fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = vfiprintf(f, fmt, ap); + va_end(ap); + return ret; +} + +int __small_fprintf(FILE *restrict f, const char *restrict fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = __small_vfprintf(f, fmt, ap); + va_end(ap); + return ret; +} diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c index 6c1b575f..9895023d 100644 --- a/src/stdio/freopen.c +++ b/src/stdio/freopen.c @@ -21,8 +21,10 @@ FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *re fflush(f); if (!filename) { +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process if (fl&O_CLOEXEC) __syscall(SYS_fcntl, f->fd, F_SETFD, FD_CLOEXEC); +#endif fl &= ~(O_CREAT|O_EXCL|O_CLOEXEC); if (syscall(SYS_fcntl, f->fd, F_SETFL, fl) < 0) goto fail; diff --git a/src/stdio/printf.c b/src/stdio/printf.c index cebfe404..c1722dea 100644 --- a/src/stdio/printf.c +++ b/src/stdio/printf.c @@ -1,3 +1,4 @@ +#include "stdio_impl.h" #include #include @@ -10,3 +11,25 @@ int printf(const char *restrict fmt, ...) va_end(ap); return ret; } + +// XXX EMSCRIPTEN +int iprintf(const char *restrict fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = vfiprintf(stdout, fmt, ap); + va_end(ap); + return ret; +} + +int __small_printf(const char *restrict fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = __small_vfprintf(stdout, fmt, ap); + va_end(ap); + return ret; +} + diff --git a/src/stdio/sprintf.c b/src/stdio/sprintf.c index 9dff524c..0b984e5e 100644 --- a/src/stdio/sprintf.c +++ b/src/stdio/sprintf.c @@ -1,3 +1,4 @@ +#include "stdio_impl.h" #include #include @@ -10,3 +11,25 @@ int sprintf(char *restrict s, const char *restrict fmt, ...) va_end(ap); return ret; } + +// XXX EMSCRIPTEN +int siprintf(char *restrict s, const char *restrict fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = vsiprintf(s, fmt, ap); + va_end(ap); + return ret; +} + +int __small_sprintf(char *restrict s, const char *restrict fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = __small_vsprintf(s, fmt, ap); + va_end(ap); + return ret; +} + diff --git a/src/stdio/stdout.c b/src/stdio/stdout.c index 6b188942..862a7f47 100644 --- a/src/stdio/stdout.c +++ b/src/stdio/stdout.c @@ -1,5 +1,19 @@ #include "stdio_impl.h" +#if __EMSCRIPTEN__ +// Emscripten doesn't support terminal seeking. +static off_t __emscripten_stdout_seek(FILE *f, off_t off, int whence) +{ + return 0; +} + +// No special work is needed to close stdout. +static int __emscripten_stdout_close(FILE *f) +{ + return 0; +} +#endif + static unsigned char buf[BUFSIZ+UNGET]; static FILE f = { .buf = buf+UNGET, @@ -7,9 +21,16 @@ static FILE f = { .fd = 1, .flags = F_PERM | F_NORD, .lbf = '\n', +#if __EMSCRIPTEN__ + // avoid stout_write which adds special terminal window size handling, which emscripten doesn't support anyhow + .write = __stdio_write, + .seek = __emscripten_stdout_seek, + .close = __emscripten_stdout_close, +#else .write = __stdout_write, .seek = __stdio_seek, .close = __stdio_close, +#endif .lock = -1, }; FILE *const stdout = &f; diff --git a/src/stdio/tmpfile.c b/src/stdio/tmpfile.c index 525090aa..db20849b 100644 --- a/src/stdio/tmpfile.c +++ b/src/stdio/tmpfile.c @@ -22,7 +22,11 @@ FILE *tmpfile(void) __syscall(SYS_unlinkat, AT_FDCWD, s, 0); #endif f = __fdopen(fd, "w+"); +#ifdef __EMSCRIPTEN__ + if (!f) __wasi_fd_close(fd); +#else if (!f) __syscall(SYS_close, fd); +#endif return f; } } diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 2ecf7692..90269795 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -9,6 +9,39 @@ #include #include +#ifndef EMSCRIPTEN_PRINTF_LONG_DOUBLE +// XXX EMSCRIPTEN - while wasm32 has long double = float128, we don't support +// printing at full precision by default. instead, we lower to +// 64-bit double. These macros makes our changes a little less +// invasive. +typedef double long_double; +#undef LDBL_TRUE_MIN +#define LDBL_TRUE_MIN DBL_DENORM_MIN +#undef LDBL_MIN +#define LDBL_MIN DBL_MIN +#undef LDBL_MAX +#define LDBL_MAX DBL_MAX +#undef LDBL_EPSILON +#define LDBL_EPSILON DBL_EPSILON +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG DBL_MANT_DIG +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP DBL_MIN_EXP +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#undef LDBL_DIG +#define LDBL_DIG DBL_DIG +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP +#undef frexpl +#define frexpl(x, exp) frexp(x, exp) +#else // EMSCRIPTEN_FULL_LONG_DOUBLE_PRINTING +// XXX EMSCRIPTEN - full long double printing support +typedef long double long_double; +#endif + /* Some useful macros */ #define MAX(a,b) ((a)>(b) ? (a) : (b)) @@ -74,7 +107,9 @@ static const unsigned char states[]['z'-'A'+1] = { S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, S('c') = CHAR, S('C') = INT, S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR, +#ifndef __EMSCRIPTEN__ // 'm' is a gnu extension, and strerror brings in 2.5K of strings S('m') = NOARG, +#endif S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE, }, { /* 1: l-prefixed */ @@ -122,11 +157,20 @@ static const unsigned char states[]['z'-'A'+1] = { union arg { uintmax_t i; - long double f; + long_double f; void *p; }; -static void pop_arg(union arg *arg, int type, va_list *ap) +// XXX EMSCRIPTEN - split out long double, so we don't always link in +// long double support for float printf. +typedef void (*pop_arg_long_double_t)(union arg *arg, va_list *ap); + +static void pop_arg_long_double(union arg *arg, va_list *ap) +{ + arg->f = va_arg(*ap, long double); +} + +static void pop_arg(union arg *arg, int type, va_list *ap, pop_arg_long_double_t pop_arg_long_double) { /* Give the compiler a hint for optimizing the switch. */ if ((unsigned)type > MAXSTATE) return; @@ -152,7 +196,7 @@ static void pop_arg(union arg *arg, int type, va_list *ap) break; case UIPTR: arg->i = (uintptr_t)va_arg(*ap, void *); #endif break; case DBL: arg->f = va_arg(*ap, double); - break; case LDBL: arg->f = va_arg(*ap, long double); + break; case LDBL: pop_arg_long_double(arg, ap); } } @@ -200,10 +244,16 @@ static char *fmt_u(uintmax_t x, char *s) * depends on the float.h constants being right. If they are wrong, it * may overflow the stack. */ #if LDBL_MANT_DIG == 53 -typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; +typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long_double)]; #endif -static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) +// XXX EMSCRIPTEN - access fmt_fp indirectly, so that iprintf doesn't +// get it linked in +// also use a double argument here, as mentioned before, +// we print float128s at double precision +typedef int (*fmt_fp_t)(FILE *f, long_double y, int w, int p, int fl, int t); + +static int fmt_fp(FILE *f, long_double y, int w, int p, int fl, int t) { uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion @@ -237,7 +287,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) if (y) e2--; if ((t|32)=='a') { - long double round = 8.0; + long_double round = 8.0; int re; if (t&32) prefix += 9; @@ -341,8 +391,8 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) x = *d % i; /* Are there any significant digits past j? */ if (x || d+1!=z) { - long double round = 2/LDBL_EPSILON; - long double small; + long_double round = 2/LDBL_EPSILON; + long_double small; if (*d/i & 1) round += 2; if (x=0) return -1; } else { if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos]; - else if (f) pop_arg(&arg, st, ap); + else if (f) pop_arg(&arg, st, ap, pop_arg_long_double); else return 0; } @@ -595,8 +647,10 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, *(a=z-(p=1))=arg.i; fl &= ~ZERO_PAD; break; +#ifndef __EMSCRIPTEN__ // 'm' is a gnu extension, and strerror brings in 2.5K of strings case 'm': if (1) a = strerror(errno); else +#endif case 's': a = arg.p ? arg.p : "(null)"; z = memchr(a, 0, p); @@ -644,13 +698,15 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, if (!l10n) return 0; for (i=1; i<=NL_ARGMAX && nl_type[i]; i++) - pop_arg(nl_arg+i, nl_type[i], ap); + pop_arg(nl_arg+i, nl_type[i], ap, pop_arg_long_double); for (; i<=NL_ARGMAX && !nl_type[i]; i++); if (i<=NL_ARGMAX) return -1; return 1; } -int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) +// XXX EMSCRIPTEN: pass in fmt_fp and pop_arg as a function pointer, so iprintf/__small_printf don't +// force linking in of floating-point code. +int __vfprintf_internal(FILE *restrict f, const char *restrict fmt, va_list ap, fmt_fp_t fmt_fp, pop_arg_long_double_t pop_arg_long_double) { va_list ap2; int nl_type[NL_ARGMAX+1] = {0}; @@ -661,7 +717,7 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) /* the copy allows passing va_list* even if va_list is an array */ va_copy(ap2, ap); - if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) { + if (printf_core(0, fmt, &ap2, nl_arg, nl_type, fmt_fp, pop_arg_long_double) < 0) { va_end(ap2); return -1; } @@ -675,7 +731,7 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) f->buf_size = sizeof internal_buf; f->wend = internal_buf + sizeof internal_buf; } - ret = printf_core(f, fmt, &ap2, nl_arg, nl_type); + ret = printf_core(f, fmt, &ap2, nl_arg, nl_type, fmt_fp, pop_arg_long_double); if (saved_buf) { f->write(f, 0, 0); if (!f->wpos) ret = -1; @@ -689,3 +745,20 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) va_end(ap2); return ret; } + +int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) +{ + return __vfprintf_internal(f, fmt, ap, fmt_fp, pop_arg_long_double); +} + +// XXX EMSCRIPTEN +int vfiprintf(FILE *restrict f, const char *restrict fmt, va_list ap) +{ + return __vfprintf_internal(f, fmt, ap, NULL, NULL); +} + +// XXX EMSCRIPTEN +int __small_vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) +{ + return __vfprintf_internal(f, fmt, ap, fmt_fp, NULL); +} diff --git a/src/stdio/vsnprintf.c b/src/stdio/vsnprintf.c index be2c44eb..4a234b76 100644 --- a/src/stdio/vsnprintf.c +++ b/src/stdio/vsnprintf.c @@ -40,3 +40,58 @@ int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) if (n) f.wpos[-(f.wpos == f.wend)] = 0; return r; } + +// XXX EMSCRIPTEN +int vsniprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) +{ + int r; + char b; + FILE f = { .lbf = EOF, .write = sn_write, .lock = -1 }; + + if (n-1 > INT_MAX-1) { + if (n) { + errno = EOVERFLOW; + return -1; + } + s = &b; + n = 1; + } + + /* Ensure pointers don't wrap if "infinite" n is passed in */ + if (n > (char *)0+SIZE_MAX-s-1) n = (char *)0+SIZE_MAX-s-1; + f.buf_size = n; + f.buf = f.wpos = (void *)s; + f.wbase = f.wend = (void *)(s+n); + r = vfiprintf(&f, fmt, ap); + + /* Null-terminate, overwriting last char if dest buffer is full */ + if (n) f.wpos[-(f.wpos == f.wend)] = 0; + return r; +} + +int __small_vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) +{ + int r; + char b; + FILE f = { .lbf = EOF, .write = sn_write, .lock = -1 }; + + if (n-1 > INT_MAX-1) { + if (n) { + errno = EOVERFLOW; + return -1; + } + s = &b; + n = 1; + } + + /* Ensure pointers don't wrap if "infinite" n is passed in */ + if (n > (char *)0+SIZE_MAX-s-1) n = (char *)0+SIZE_MAX-s-1; + f.buf_size = n; + f.buf = f.wpos = (void *)s; + f.wbase = f.wend = (void *)(s+n); + r = __small_vfprintf(&f, fmt, ap); + + /* Null-terminate, overwriting last char if dest buffer is full */ + if (n) f.wpos[-(f.wpos == f.wend)] = 0; + return r; +} diff --git a/src/stdio/vsprintf.c b/src/stdio/vsprintf.c index c57349d4..c171886f 100644 --- a/src/stdio/vsprintf.c +++ b/src/stdio/vsprintf.c @@ -1,3 +1,4 @@ +#include "stdio_impl.h" #include #include @@ -5,3 +6,15 @@ int vsprintf(char *restrict s, const char *restrict fmt, va_list ap) { return vsnprintf(s, INT_MAX, fmt, ap); } + +// XXX EMSCRIPTEN +int vsiprintf(char *restrict s, const char *restrict fmt, va_list ap) +{ + return vsniprintf(s, INT_MAX, fmt, ap); +} + +int __small_vsprintf(char *restrict s, const char *restrict fmt, va_list ap) +{ + return __small_vsnprintf(s, INT_MAX, fmt, ap); +} + diff --git a/src/stdio/vswprintf.c b/src/stdio/vswprintf.c index 7d237bae..7f98c5c9 100644 --- a/src/stdio/vswprintf.c +++ b/src/stdio/vswprintf.c @@ -1,8 +1,8 @@ #include "stdio_impl.h" #include -#include #include #include +#include #include struct cookie { @@ -24,23 +24,30 @@ static size_t sw_write(FILE *f, const unsigned char *s, size_t l) c->ws++; } *c->ws = 0; - return i<0 ? i : l0; + if (i < 0) { + f->wpos = f->wbase = f->wend = 0; + f->flags |= F_ERR; + return i; + } + f->wend = f->buf + f->buf_size; + f->wpos = f->wbase = f->buf; + return l0; } int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, va_list ap) { int r; - FILE f; unsigned char buf[256]; struct cookie c = { s, n-1 }; + FILE f = { + .lbf = EOF, + .write = sw_write, + .lock = -1, + .buf = buf, + .buf_size = sizeof buf, + .cookie = &c, + }; - memset(&f, 0, sizeof(FILE)); - f.lbf = EOF; - f.write = sw_write; - f.buf_size = sizeof buf; - f.buf = buf; - f.lock = -1; - f.cookie = &c; if (!n) { return -1; } else if (n > INT_MAX) { diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c index 461dcf85..07cd599a 100644 --- a/src/stdlib/strtod.c +++ b/src/stdlib/strtod.c @@ -32,9 +32,28 @@ long double strtold(const char *restrict s, char **restrict p) return strtox(s, p, 2); } +#ifndef __EMSCRIPTEN__ weak_alias(strtof, strtof_l); weak_alias(strtod, strtod_l); weak_alias(strtold, strtold_l); weak_alias(strtof, __strtof_l); weak_alias(strtod, __strtod_l); weak_alias(strtold, __strtold_l); +#else +// can't just drop last parameter in emscripten, undefined behavior +float strtof_l(const char *restrict s, char **restrict p, struct __locale_struct *l) +{ + return strtof(s, p); +} + +double strtod_l(const char *restrict s, char **restrict p, struct __locale_struct *l) +{ + return strtod(s, p); +} + +long double strtold_l(const char *restrict s, char **restrict p, struct __locale_struct *l) +{ + return strtold(s, p); +} +#endif + diff --git a/src/string/memccpy.c b/src/string/memccpy.c index 7c233d5e..f515581c 100644 --- a/src/string/memccpy.c +++ b/src/string/memccpy.c @@ -11,19 +11,22 @@ void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n) { unsigned char *d = dest; const unsigned char *s = src; - size_t *wd, k; - const size_t *ws; c = (unsigned char)c; +#ifdef __GNUC__ + typedef size_t __attribute__((__may_alias__)) word; + word *wd; + const word *ws; if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) { for (; ((uintptr_t)s & ALIGN) && n && (*d=*s)!=c; n--, s++, d++); if ((uintptr_t)s & ALIGN) goto tail; - k = ONES * c; + size_t k = ONES * c; wd=(void *)d; ws=(const void *)s; for (; n>=sizeof(size_t) && !HASZERO(*ws^k); n-=sizeof(size_t), ws++, wd++) *wd = *ws; d=(void *)wd; s=(const void *)ws; } +#endif for (; n && (*d=*s)!=c; n--, s++, d++); tail: if (*s==c) return d+1; diff --git a/src/string/memchr.c b/src/string/memchr.c index 4daff7bb..65f0d789 100644 --- a/src/string/memchr.c +++ b/src/string/memchr.c @@ -12,12 +12,16 @@ void *memchr(const void *src, int c, size_t n) { const unsigned char *s = src; c = (unsigned char)c; +#ifdef __GNUC__ for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--); if (n && *s != c) { - const size_t *w; + typedef size_t __attribute__((__may_alias__)) word; + const word *w; size_t k = ONES * c; for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS); - for (s = (const void *)w; n && *s != c; s++, n--); + s = (const void *)w; } +#endif + for (; n && *s != c; s++, n--); return n ? (void *)s : 0; } diff --git a/src/string/memmove.c b/src/string/memmove.c index 27f670e1..5dc9cdb9 100644 --- a/src/string/memmove.c +++ b/src/string/memmove.c @@ -1,8 +1,10 @@ #include #include -#define WT size_t +#ifdef __GNUC__ +typedef __attribute__((__may_alias__)) size_t WT; #define WS (sizeof(WT)) +#endif void *memmove(void *dest, const void *src, size_t n) { @@ -10,9 +12,10 @@ void *memmove(void *dest, const void *src, size_t n) const char *s = src; if (d==s) return d; - if (s+n <= d || d+n <= s) return memcpy(d, s, n); + if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n); if (d=WS; n-=WS, d+=WS, s+=WS) *(WT *)d = *(WT *)s; } +#endif for (; n; n--) *d++ = *s++; } else { +#ifdef __GNUC__ if ((uintptr_t)s % WS == (uintptr_t)d % WS) { while ((uintptr_t)(d+n) % WS) { if (!n--) return dest; @@ -29,6 +34,7 @@ void *memmove(void *dest, const void *src, size_t n) } while (n>=WS) n-=WS, *(WT *)(d+n) = *(WT *)(s+n); } +#endif while (n) n--, d[n] = s[n]; } diff --git a/src/string/stpcpy.c b/src/string/stpcpy.c index 06623c44..4db46a9e 100644 --- a/src/string/stpcpy.c +++ b/src/string/stpcpy.c @@ -1,7 +1,6 @@ #include #include #include -#include "libc.h" #define ALIGN (sizeof(size_t)) #define ONES ((size_t)-1/UCHAR_MAX) @@ -10,9 +9,10 @@ char *__stpcpy(char *restrict d, const char *restrict s) { - size_t *wd; - const size_t *ws; - +#ifdef __GNUC__ + typedef size_t __attribute__((__may_alias__)) word; + word *wd; + const word *ws; if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) { for (; (uintptr_t)s % ALIGN; s++, d++) if (!(*d=*s)) return d; @@ -20,6 +20,7 @@ char *__stpcpy(char *restrict d, const char *restrict s) for (; !HASZERO(*ws); *wd++ = *ws++); d=(void *)wd; s=(const void *)ws; } +#endif for (; (*d=*s); s++, d++); return d; diff --git a/src/string/stpncpy.c b/src/string/stpncpy.c index 1f57a4dd..c699cfe5 100644 --- a/src/string/stpncpy.c +++ b/src/string/stpncpy.c @@ -1,7 +1,6 @@ #include #include #include -#include "libc.h" #define ALIGN (sizeof(size_t)-1) #define ONES ((size_t)-1/UCHAR_MAX) @@ -10,9 +9,10 @@ char *__stpncpy(char *restrict d, const char *restrict s, size_t n) { - size_t *wd; - const size_t *ws; - +#ifdef __GNUC__ + typedef size_t __attribute__((__may_alias__)) word; + word *wd; + const word *ws; if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) { for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++); if (!n || !*s) goto tail; @@ -21,6 +21,7 @@ char *__stpncpy(char *restrict d, const char *restrict s, size_t n) n-=sizeof(size_t), ws++, wd++) *wd = *ws; d=(void *)wd; s=(const void *)ws; } +#endif for (; n && (*d=*s); n--, s++, d++); tail: memset(d, 0, n); @@ -28,4 +29,3 @@ char *__stpncpy(char *restrict d, const char *restrict s, size_t n) } weak_alias(__stpncpy, stpncpy); - diff --git a/src/string/strchrnul.c b/src/string/strchrnul.c index 05700ad6..39e2635b 100644 --- a/src/string/strchrnul.c +++ b/src/string/strchrnul.c @@ -1,7 +1,6 @@ #include #include #include -#include "libc.h" #define ALIGN (sizeof(size_t)) #define ONES ((size_t)-1/UCHAR_MAX) @@ -10,16 +9,19 @@ char *__strchrnul(const char *s, int c) { - size_t *w, k; - c = (unsigned char)c; if (!c) return (char *)s + strlen(s); +#ifdef __GNUC__ + typedef size_t __attribute__((__may_alias__)) word; + const word *w; for (; (uintptr_t)s % ALIGN; s++) if (!*s || *(unsigned char *)s == c) return (char *)s; - k = ONES * c; + size_t k = ONES * c; for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++); - for (s = (void *)w; *s && *(unsigned char *)s != c; s++); + s = (void *)w; +#endif + for (; *s && *(unsigned char *)s != c; s++); return (char *)s; } diff --git a/src/string/strlcpy.c b/src/string/strlcpy.c index 193d7241..ffa0b0b0 100644 --- a/src/string/strlcpy.c +++ b/src/string/strlcpy.c @@ -2,7 +2,6 @@ #include #include #include -#include "libc.h" #define ALIGN (sizeof(size_t)-1) #define ONES ((size_t)-1/UCHAR_MAX) @@ -13,9 +12,11 @@ size_t strlcpy(char *d, const char *s, size_t n) { char *d0 = d; size_t *wd; - const size_t *ws; if (!n--) goto finish; +#ifdef __GNUC__ + typedef size_t __attribute__((__may_alias__)) word; + const word *ws; if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) { for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++); if (n && *s) { @@ -25,6 +26,7 @@ size_t strlcpy(char *d, const char *s, size_t n) d=(void *)wd; s=(const void *)ws; } } +#endif for (; n && (*d=*s); n--, s++, d++); *d = 0; finish: diff --git a/src/string/strlen.c b/src/string/strlen.c index 929ddcbc..309990f0 100644 --- a/src/string/strlen.c +++ b/src/string/strlen.c @@ -10,9 +10,13 @@ size_t strlen(const char *s) { const char *a = s; - const size_t *w; +#ifdef __GNUC__ + typedef size_t __attribute__((__may_alias__)) word; + const word *w; for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a; for (w = (const void *)s; !HASZERO(*w); w++); - for (s = (const void *)w; *s; s++); + s = (const void *)w; +#endif + for (; *s; s++); return s-a; } diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index 13d8465a..71abe8e7 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -1,13 +1,24 @@ #include #include #include +#ifdef __EMSCRIPTEN__ +#include +#include +#include +#include "pthread_impl.h" +#else #include "futex.h" +#endif #include "syscall.h" #include "pthread_impl.h" int __pthread_setcancelstate(int, int *); int __clock_gettime(clockid_t, struct timespec *); +#ifdef __EMSCRIPTEN__ +int _pthread_isduecanceled(struct pthread *pthread_ptr); +#endif + int __timedwait_cp(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int priv) { @@ -28,8 +39,38 @@ int __timedwait_cp(volatile int *addr, int val, top = &to; } +#ifdef __EMSCRIPTEN__ + double msecsToSleep = top ? (top->tv_sec * 1000 + top->tv_nsec / 1000000.0) : INFINITY; + int is_main_thread = emscripten_is_main_browser_thread(); + if (is_main_thread || pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { + double sleepUntilTime = emscripten_get_now() + msecsToSleep; + do { + if (_pthread_isduecanceled(pthread_self())) { + // Emscripten-specific return value: The wait was canceled by user calling + // pthread_cancel() for this thread, and the caller needs to cooperatively + // cancel execution. + return ECANCELED; + } + // Assist other threads by executing proxied operations that are effectively singlethreaded. + if (is_main_thread) emscripten_main_thread_process_queued_calls(); + // Must wait in slices in case this thread is cancelled in between. + double waitMsecs = sleepUntilTime - emscripten_get_now(); + if (waitMsecs <= 0) { + r = ETIMEDOUT; + break; + } + if (waitMsecs > 100) waitMsecs = 100; // non-main threads can sleep in longer slices. + if (is_main_thread && waitMsecs > 1) waitMsecs = 1; // main thread may need to run proxied calls, so sleep in very small slices to be responsive. + r = -emscripten_futex_wait((void*)addr, val, waitMsecs); + } while(r == ETIMEDOUT); + } else { + // Can wait in one go. + r = -emscripten_futex_wait((void*)addr, val, msecsToSleep); + } +#else r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT|priv, val, top); if (r == ENOSYS) r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top); +#endif if (r != EINTR && r != ETIMEDOUT && r != ECANCELED) r = 0; return r; @@ -40,7 +81,14 @@ int __timedwait(volatile int *addr, int val, { int cs, r; __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); +#ifdef __EMSCRIPTEN__ + emscripten_conditional_set_current_thread_status(EM_THREAD_STATUS_RUNNING, EM_THREAD_STATUS_WAITMUTEX); +#endif r = __timedwait_cp(addr, val, clk, at, priv); +#ifdef __EMSCRIPTEN__ + emscripten_conditional_set_current_thread_status(EM_THREAD_STATUS_WAITMUTEX, EM_THREAD_STATUS_RUNNING); +#endif __pthread_setcancelstate(cs, 0); + return r; } diff --git a/src/thread/__wait.c b/src/thread/__wait.c index dc33c1a3..265451da 100644 --- a/src/thread/__wait.c +++ b/src/thread/__wait.c @@ -1,5 +1,11 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif + #include "pthread_impl.h" +int _pthread_isduecanceled(struct pthread *pthread_ptr); + void __wait(volatile int *addr, volatile int *waiters, int val, int priv) { int spins=100; @@ -9,9 +15,33 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv) else return; } if (waiters) a_inc(waiters); +#ifdef __EMSCRIPTEN__ + int is_main_thread = emscripten_is_main_runtime_thread(); + while (*addr==val) { + if (pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { + // Must wait in slices in case this thread is cancelled in between. + int e; + do { + if (_pthread_isduecanceled(pthread_self())) { + if (waiters) a_dec(waiters); + return; + } + // Assist other threads by executing proxied operations that are effectively singlethreaded. + if (is_main_thread) emscripten_main_thread_process_queued_calls(); + // Main thread waits in _very_ small slices so that it stays responsive to assist proxied + // pthread calls. + e = emscripten_futex_wait((void*)addr, val, is_main_thread ? 1 : 100); + } while(e == -ETIMEDOUT); + } else { + // Can wait in one go. + emscripten_futex_wait((void*)addr, val, INFINITY); + } + } +#else while (*addr==val) { __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS || __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); } +#endif if (waiters) a_dec(waiters); } diff --git a/src/thread/pthread_atfork.c b/src/thread/pthread_atfork.c index a40d7f63..792b7eda 100644 --- a/src/thread/pthread_atfork.c +++ b/src/thread/pthread_atfork.c @@ -1,6 +1,7 @@ #include #include "libc.h" +#ifndef __EMSCRIPTEN__ // XXX Emscripten fork() is not supported: pthread_atfork is a no-op static struct atfork_funcs { void (*prepare)(void); void (*parent)(void); @@ -29,9 +30,13 @@ void __fork_handler(int who) UNLOCK(lock); } } +#endif int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) { +#ifdef __EMSCRIPTEN__ // XXX Emscripten fork() is not supported: pthread_atfork is a no-op + return 0; +#else struct atfork_funcs *new = malloc(sizeof *new); if (!new) return -1; @@ -45,4 +50,5 @@ int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(vo funcs = new; UNLOCK(lock); return 0; +#endif } diff --git a/src/thread/pthread_attr_get.c b/src/thread/pthread_attr_get.c index 3d296bf3..e2a44d19 100644 --- a/src/thread/pthread_attr_get.c +++ b/src/thread/pthread_attr_get.c @@ -37,8 +37,12 @@ int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope) int pthread_attr_getstack(const pthread_attr_t *restrict a, void **restrict addr, size_t *restrict size) { - if (!a->_a_stackaddr) - return EINVAL; +/// XXX musl is not standard-conforming? It should not report EINVAL if _a_stackaddr is zero, and it should +/// report EINVAL if a is null: http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_attr_getstack.html + if (!a) return EINVAL; +// if (!a->_a_stackaddr) +// return EINVAL; + *size = a->_a_stacksize + DEFAULT_STACK_SIZE; *addr = (void *)(a->_a_stackaddr - *size); return 0; diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c index 06b83db9..46b85661 100644 --- a/src/thread/pthread_barrier_wait.c +++ b/src/thread/pthread_barrier_wait.c @@ -1,3 +1,7 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif + #include "pthread_impl.h" static int pshared_barrier_wait(pthread_barrier_t *b) @@ -83,9 +87,14 @@ int pthread_barrier_wait(pthread_barrier_t *b) while (spins-- && !inst->finished) a_spin(); a_inc(&inst->finished); - while (inst->finished == 1) + while (inst->finished == 1) { +#ifdef __EMSCRIPTEN__ + emscripten_futex_wait(&inst->finished, 1, INFINITY); +#else __syscall(SYS_futex,&inst->finished,FUTEX_WAIT|128,1,0) != -ENOSYS || __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0); +#endif + } return PTHREAD_BARRIER_SERIAL_THREAD; } diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index 3526ecfb..90869b18 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -53,9 +53,19 @@ static inline void unlock(volatile int *l) static inline void unlock_requeue(volatile int *l, volatile int *r, int w) { a_store(l, 0); +#ifdef __EMSCRIPTEN__ + // Here the intent is to wake one waiter, and requeue all other waiters from waiting on address 'l' + // to wait on address 'r' instead. This is not possible at the moment with SharedArrayBuffer Atomics, + // as it does not have a "wake X waiters and requeue the rest" primitive. However this kind of + // primitive is strictly not needed, since it is more like an optimization to avoid spuriously waking + // all waiters, just to make them wait on another location immediately afterwards. Here we do exactly + // that: wake every waiter. + emscripten_futex_wake(l, 0x7FFFFFFF); +#else if (w) __wake(l, 1, 1); else __syscall(SYS_futex, l, FUTEX_REQUEUE|128, 0, 1, r) != -ENOSYS || __syscall(SYS_futex, l, FUTEX_REQUEUE, 0, 1, r); +#endif } enum { @@ -70,6 +80,13 @@ int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restri int e, seq, clock = c->_c_clock, cs, shared=0, oldstate, tmp; volatile int *fut; +#ifdef __EMSCRIPTEN__ + // TODO: Optimize this away in MINIMAL_RUNTIME. + if (pthread_self() == emscripten_main_browser_thread_id()) { + emscripten_check_blocking_allowed(); + } +#endif + if ((m->_m_type&15) && (m->_m_lock&INT_MAX) != __pthread_self()->tid) return EPERM; @@ -171,6 +188,10 @@ int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restri __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); } +#ifdef __EMSCRIPTEN__ + pthread_testcancel(); +#endif + return e; } diff --git a/src/thread/pthread_getconcurrency.c b/src/thread/pthread_getconcurrency.c index 269429a8..4ab5f1b9 100644 --- a/src/thread/pthread_getconcurrency.c +++ b/src/thread/pthread_getconcurrency.c @@ -1,5 +1,7 @@ #include +// XXX Emscripten marked as obsolescent in pthreads specification: +// http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getconcurrency.html int pthread_getconcurrency() { return 0; diff --git a/src/thread/pthread_getcpuclockid.c b/src/thread/pthread_getcpuclockid.c index 9df14fb6..62355f43 100644 --- a/src/thread/pthread_getcpuclockid.c +++ b/src/thread/pthread_getcpuclockid.c @@ -2,6 +2,11 @@ int pthread_getcpuclockid(pthread_t t, clockid_t *clockid) { +#ifdef __EMSCRIPTEN__ // XXX Emscipten per-thread CPU time clocks are not supported + // pthread API recommends returning this error when "Per-thread CPU time clocks are not supported by the system." + return ENOENT; +#else *clockid = (-t->tid-1)*8U + 6; return 0; +#endif } diff --git a/src/thread/pthread_getschedparam.c b/src/thread/pthread_getschedparam.c index 3053c186..1e81ea84 100644 --- a/src/thread/pthread_getschedparam.c +++ b/src/thread/pthread_getschedparam.c @@ -2,6 +2,10 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param *restrict param) { +#ifdef __EMSCRIPTEN__ // XXX Emscripten web or Node workers doesn't support prioritizing threads + // no-op + return 0; +#else int r; __lock(t->killlock); if (t->dead) { @@ -14,4 +18,5 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param } __unlock(t->killlock); return r; +#endif } diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c index a78e507a..e77deb1a 100644 --- a/src/thread/pthread_key_create.c +++ b/src/thread/pthread_key_create.c @@ -1,5 +1,9 @@ #include "pthread_impl.h" +#ifdef __EMSCRIPTEN__ +#include +#endif + volatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX; void *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 }; @@ -35,7 +39,11 @@ int __pthread_key_delete(pthread_key_t k) return 0; } +#ifdef __EMSCRIPTEN__ +void EMSCRIPTEN_KEEPALIVE __pthread_tsd_run_dtors() +#else void __pthread_tsd_run_dtors() +#endif { pthread_t self = __pthread_self(); int i, j, not_finished = self->tsd_used; diff --git a/src/thread/pthread_mutex_trylock.c b/src/thread/pthread_mutex_trylock.c index 54876a61..fa530915 100644 --- a/src/thread/pthread_mutex_trylock.c +++ b/src/thread/pthread_mutex_trylock.c @@ -19,7 +19,9 @@ int __pthread_mutex_trylock_owner(pthread_mutex_t *m) if (m->_m_type & 128) { if (!self->robust_list.off) { self->robust_list.off = (char*)&m->_m_lock-(char *)&m->_m_next; +#ifndef __EMSCRIPTEN__ // XXX Emscripten does not have a concept of multiple processes or kernel space, so robust mutex lists don't need to register to kernel. __syscall(SYS_set_robust_list, &self->robust_list, 3*sizeof(long)); +#endif } if (m->_m_waiters) tid |= 0x80000000; self->robust_list.pending = &m->_m_next; diff --git a/src/thread/pthread_rwlock_timedwrlock.c b/src/thread/pthread_rwlock_timedwrlock.c index 7f26dad1..e1d6162f 100644 --- a/src/thread/pthread_rwlock_timedwrlock.c +++ b/src/thread/pthread_rwlock_timedwrlock.c @@ -2,6 +2,11 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct timespec *restrict at) { +#ifdef __EMSCRIPTEN__ + /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. + /// If attempting to lock the write lock that we already own, error out. + if (rw->_rw_wr_owner == (int)pthread_self()) return EDEADLK; +#endif int r, t; r = pthread_rwlock_trywrlock(rw); @@ -19,5 +24,10 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct times a_dec(&rw->_rw_waiters); if (r && r != EINTR) return r; } +#ifdef __EMSCRIPTEN__ + /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. + /// Mark this thread as the owner of this write lock. + rw->_rw_wr_owner = (int)pthread_self(); +#endif return r; } diff --git a/src/thread/pthread_rwlock_trywrlock.c b/src/thread/pthread_rwlock_trywrlock.c index bb3d3a99..fdd08d39 100644 --- a/src/thread/pthread_rwlock_trywrlock.c +++ b/src/thread/pthread_rwlock_trywrlock.c @@ -3,5 +3,10 @@ int pthread_rwlock_trywrlock(pthread_rwlock_t *rw) { if (a_cas(&rw->_rw_lock, 0, 0x7fffffff)) return EBUSY; +#ifdef __EMSCRIPTEN__ + /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. + /// Mark this thread to own the write lock, to ignore multiple attempts to lock. + rw->_rw_wr_owner = (int)pthread_self(); +#endif return 0; } diff --git a/src/thread/pthread_rwlock_unlock.c b/src/thread/pthread_rwlock_unlock.c index 7b5eec84..61d5e386 100644 --- a/src/thread/pthread_rwlock_unlock.c +++ b/src/thread/pthread_rwlock_unlock.c @@ -4,6 +4,12 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rw) { int val, cnt, waiters, new, priv = rw->_rw_shared^128; +#ifdef __EMSCRIPTEN__ + /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. + /// Mark this thread to not own the write lock anymore. + if (rw->_rw_wr_owner == (int)pthread_self()) rw->_rw_wr_owner = 0; +#endif + do { val = rw->_rw_lock; cnt = val & 0x7fffffff; diff --git a/src/thread/pthread_setconcurrency.c b/src/thread/pthread_setconcurrency.c index 091abf98..deadf26b 100644 --- a/src/thread/pthread_setconcurrency.c +++ b/src/thread/pthread_setconcurrency.c @@ -3,7 +3,9 @@ int pthread_setconcurrency(int val) { +#ifndef __EMSCRIPTEN__ // XXX Emscripten marked as obsolescent in pthreads specification if (val < 0) return EINVAL; if (val > 0) return EAGAIN; +#endif return 0; } diff --git a/src/thread/pthread_setschedparam.c b/src/thread/pthread_setschedparam.c index c4738d64..203a625e 100644 --- a/src/thread/pthread_setschedparam.c +++ b/src/thread/pthread_setschedparam.c @@ -2,9 +2,14 @@ int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *param) { +#ifdef __EMSCRIPTEN__ // XXX Emscripten web or Node workers doesn't support prioritizing threads + // no-op + return 0; +#else int r; __lock(t->killlock); r = t->dead ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param); __unlock(t->killlock); return r; +#endif } diff --git a/src/thread/pthread_setschedprio.c b/src/thread/pthread_setschedprio.c index e0bdc03b..ed9b2d66 100644 --- a/src/thread/pthread_setschedprio.c +++ b/src/thread/pthread_setschedprio.c @@ -2,9 +2,14 @@ int pthread_setschedprio(pthread_t t, int prio) { +#ifdef __EMSCRIPTEN__ // XXX Emscripten web or Node workers doesn't support prioritizing threads + // no-op + return 0; +#else int r; __lock(t->killlock); r = t->dead ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio); __unlock(t->killlock); return r; +#endif } diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c index 8132eb1b..9782e6ab 100644 --- a/src/thread/sem_timedwait.c +++ b/src/thread/sem_timedwait.c @@ -23,6 +23,9 @@ int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) r = __timedwait_cp(sem->__val, -1, CLOCK_REALTIME, at, sem->__val[2]); pthread_cleanup_pop(1); if (r && r != EINTR) { +#ifdef __EMSCRIPTEN__ + if (r == ECANCELED) r = EINTR; +#endif errno = r; return -1; } diff --git a/src/thread/thrd_create.c b/src/thread/thrd_create.c index e0336695..891d227b 100644 --- a/src/thread/thrd_create.c +++ b/src/thread/thrd_create.c @@ -1,6 +1,11 @@ #include "pthread_impl.h" #include +// XXX Emscripten implements pthread_create directly rather than __pthread_create +#ifdef __EMSCRIPTEN__ +#define __pthread_create pthread_create +#endif + int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict); int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) diff --git a/src/thread/thrd_exit.c b/src/thread/thrd_exit.c index b66bd996..270d3704 100644 --- a/src/thread/thrd_exit.c +++ b/src/thread/thrd_exit.c @@ -1,6 +1,11 @@ #include "pthread_impl.h" #include +// XXX Emscripten implements pthread_exit directly rather than __pthread_exit +#ifdef __EMSCRIPTEN__ +#define __pthread_exit pthread_exit +#endif + _Noreturn void __pthread_exit(void *); _Noreturn void thrd_exit(int result) diff --git a/src/thread/thrd_join.c b/src/thread/thrd_join.c index ac667893..0149c89f 100644 --- a/src/thread/thrd_join.c +++ b/src/thread/thrd_join.c @@ -1,6 +1,11 @@ #include #include +// XXX Emscripten implements implements pthread_join directly rather than __pthread_join +#ifdef __EMSCRIPTEN__ +#define __pthread_join pthread_join +#endif + int __pthread_join(thrd_t, void**); int thrd_join(thrd_t t, int *res) diff --git a/src/thread/thrd_sleep.c b/src/thread/thrd_sleep.c index e8dfe400..37af3e21 100644 --- a/src/thread/thrd_sleep.c +++ b/src/thread/thrd_sleep.c @@ -4,7 +4,11 @@ int thrd_sleep(const struct timespec *req, struct timespec *rem) { +#ifdef __EMSCRIPTEN__ + int ret = nanosleep(req, rem); +#else int ret = __syscall(SYS_nanosleep, req, rem); +#endif switch (ret) { case 0: return 0; case -EINTR: return -1; /* value specified by C11 */ diff --git a/src/thread/thrd_yield.c b/src/thread/thrd_yield.c index f7ad1321..d30d8843 100644 --- a/src/thread/thrd_yield.c +++ b/src/thread/thrd_yield.c @@ -3,5 +3,7 @@ void thrd_yield() { +#ifndef __EMSCRIPTEN__ __syscall(SYS_sched_yield); +#endif } diff --git a/src/time/__map_file.c b/src/time/__map_file.c index b91eb8ed..de8f7a1e 100644 --- a/src/time/__map_file.c +++ b/src/time/__map_file.c @@ -15,6 +15,10 @@ const char unsigned *__map_file(const char *pathname, size_t *size) map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); *size = st.st_size; } +#ifdef __EMSCRIPTEN__ + __wasi_fd_close(fd); +#else __syscall(SYS_close, fd); +#endif return map == MAP_FAILED ? 0 : map; } diff --git a/src/time/asctime.c b/src/time/asctime.c index 3102eb87..57d15fe0 100644 --- a/src/time/asctime.c +++ b/src/time/asctime.c @@ -1,9 +1,9 @@ #include -char *__asctime(const struct tm *, char *); +char *__asctime_r(const struct tm *, char *); char *asctime(const struct tm *tm) { static char buf[26]; - return __asctime(tm, buf); + return __asctime_r(tm, buf); } diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index 24128804..bada2563 100644 --- a/src/time/clock_gettime.c +++ b/src/time/clock_gettime.c @@ -24,6 +24,19 @@ static void *volatile vdso_func = (void *)cgt_init; #endif +#if __EMSCRIPTEN__ +_Static_assert(CLOCK_REALTIME == __WASI_CLOCKID_REALTIME, "monotonic clock must match"); +_Static_assert(CLOCK_MONOTONIC == __WASI_CLOCKID_MONOTONIC, "monotonic clock must match"); + +int __clock_gettime(clockid_t clk, struct timespec *ts) { + __wasi_timestamp_t timestamp; + if (__wasi_syscall_ret(__wasi_clock_time_get(clk, 1, ×tamp))) { + return -1; + } + *ts = __wasi_timestamp_to_timespec(timestamp); + return 0; +} +#else // __EMSCRIPTEN__ int __clock_gettime(clockid_t clk, struct timespec *ts) { int r; @@ -54,5 +67,6 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) } return __syscall_ret(r); } +#endif //__EMSCRIPTEN__ weak_alias(__clock_gettime, clock_gettime); diff --git a/src/time/clock_settime.c b/src/time/clock_settime.c index 66b8162d..d3d94174 100644 --- a/src/time/clock_settime.c +++ b/src/time/clock_settime.c @@ -1,7 +1,16 @@ #include #include "syscall.h" +#ifdef __EMSCRIPTEN__ +#include +#endif int clock_settime(clockid_t clk, const struct timespec *ts) { +#ifdef __EMSCRIPTEN__ + // JS and wasm VMs do not allow setting the time. + errno = EPERM; + return -1; +#else return syscall(SYS_clock_settime, clk, ts); +#endif } diff --git a/src/time/localtime_r.c b/src/time/localtime_r.c index 2e62c29f..4804a465 100644 --- a/src/time/localtime_r.c +++ b/src/time/localtime_r.c @@ -6,7 +6,8 @@ struct tm *__localtime_r(const time_t *restrict t, struct tm *restrict tm) { /* Reject time_t values whose year would overflow int because * __secs_to_zone cannot safely handle them. */ - if (*t < INT_MIN * 31622400LL || *t > INT_MAX * 31622400LL) { + // XXX EMSCRIPTEN: add casts to (long long) to avoid a new clang warning + if (((long long)*t) < INT_MIN * 31622400LL || ((long long)*t) > INT_MAX * 31622400LL) { errno = EOVERFLOW; return 0; } diff --git a/src/time/nanosleep.c b/src/time/nanosleep.c index a2ff4839..4fd31e64 100644 --- a/src/time/nanosleep.c +++ b/src/time/nanosleep.c @@ -1,8 +1,21 @@ #include #include "syscall.h" #include "libc.h" +#if __EMSCRIPTEN__ +#include +#include +#endif int nanosleep(const struct timespec *req, struct timespec *rem) { +#if __EMSCRIPTEN__ + if (!req || req->tv_nsec < 0 || req->tv_nsec > 999999999L || req->tv_sec < 0) { + errno = EINVAL; + return -1; + } + emscripten_thread_sleep(req->tv_sec * 1000.0 + req->tv_nsec / 1e6); + return 0; +#else return syscall_cp(SYS_nanosleep, req, rem); +#endif } diff --git a/src/time/strftime.c b/src/time/strftime.c index f1ccc4dd..e21a3513 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -181,7 +181,7 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm * *l = 0; return ""; } - *l = snprintf(*s, sizeof *s, "%+.2d%.2d", + *l = snprintf(*s, sizeof *s, "%+.2ld%.2d", // XXX EMSCRIPTEN: %d => %ld (tm->__tm_gmtoff)/3600, abs(tm->__tm_gmtoff%3600)/60); return *s; diff --git a/src/unistd/close.c b/src/unistd/close.c index fa3c6cab..9cee18ef 100644 --- a/src/unistd/close.c +++ b/src/unistd/close.c @@ -13,7 +13,13 @@ weak_alias(dummy, __aio_close); int close(int fd) { fd = __aio_close(fd); +#ifdef __EMSCRIPTEN__ + int r = __wasi_fd_close(fd); + if (r == __WASI_ERRNO_INTR) r = __WASI_ERRNO_SUCCESS; + return __wasi_syscall_ret(r); +#else int r = __syscall_cp(SYS_close, fd); if (r == -EINTR) r = 0; return __syscall_ret(r); +#endif } diff --git a/src/unistd/dup2.c b/src/unistd/dup2.c index 8f43c6dd..88d281e4 100644 --- a/src/unistd/dup2.c +++ b/src/unistd/dup2.c @@ -1,3 +1,6 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif #include #include #include @@ -10,7 +13,11 @@ int dup2(int old, int new) while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); #else if (old==new) { +#if __EMSCRIPTEN__ r = __syscall(SYS_fcntl, old, F_GETFD); +#else + r = __wasi_fd_is_valid(old); +#endif if (r >= 0) return old; } else { while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY); diff --git a/src/unistd/dup3.c b/src/unistd/dup3.c index 0eb6caf5..bb48dbe9 100644 --- a/src/unistd/dup3.c +++ b/src/unistd/dup3.c @@ -15,7 +15,9 @@ int __dup3(int old, int new, int flags) if (r!=-ENOSYS) return __syscall_ret(r); } while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process if (flags & O_CLOEXEC) __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC); +#endif #else while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY); #endif diff --git a/src/unistd/fchdir.c b/src/unistd/fchdir.c index 72c3915e..6da9530e 100644 --- a/src/unistd/fchdir.c +++ b/src/unistd/fchdir.c @@ -1,3 +1,6 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif #include #include #include @@ -8,8 +11,13 @@ void __procfdname(char *, unsigned); int fchdir(int fd) { int ret = __syscall(SYS_fchdir, fd); +#if __EMSCRIPTEN__ + if (ret != -EBADF || !__wasi_fd_is_valid(fd)) + return __syscall_ret(ret); +#else if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) return __syscall_ret(ret); +#endif char buf[15+3*sizeof(int)]; __procfdname(buf, fd); diff --git a/src/unistd/fchown.c b/src/unistd/fchown.c index 03459849..c73b2896 100644 --- a/src/unistd/fchown.c +++ b/src/unistd/fchown.c @@ -1,3 +1,6 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif #include #include #include @@ -8,8 +11,13 @@ void __procfdname(char *, unsigned); int fchown(int fd, uid_t uid, gid_t gid) { int ret = __syscall(SYS_fchown, fd, uid, gid); +#if __EMSCRIPTEN__ + if (ret != -EBADF || !__wasi_fd_is_valid(fd)) + return __syscall_ret(ret); +#else if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) return __syscall_ret(ret); +#endif char buf[15+3*sizeof(int)]; __procfdname(buf, fd); diff --git a/src/unistd/fsync.c b/src/unistd/fsync.c index 7a1c80b5..2b26be53 100644 --- a/src/unistd/fsync.c +++ b/src/unistd/fsync.c @@ -3,5 +3,9 @@ int fsync(int fd) { +#if __EMSCRIPTEN__ + return __wasi_syscall_ret(__wasi_fd_sync(fd)); +#else return syscall_cp(SYS_fsync, fd); +#endif } diff --git a/src/unistd/isatty.c b/src/unistd/isatty.c index c8badaf5..bbe7c835 100644 --- a/src/unistd/isatty.c +++ b/src/unistd/isatty.c @@ -1,9 +1,30 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif #include #include #include "syscall.h" int isatty(int fd) { +#ifdef __EMSCRIPTEN__ + __wasi_fdstat_t statbuf; + int err = __wasi_fd_fdstat_get(fd, &statbuf); + if (err != 0) { + errno = err; + return 0; + } + + // All character devices are terminals (other things a Linux system would + // assume is a character device, like the mouse, we have special APIs for). + if (statbuf.fs_filetype != __WASI_FILETYPE_CHARACTER_DEVICE) { + errno = __WASI_ERRNO_NOTTY; + return 0; + } + + return 1; +#else struct winsize wsz; - return !__syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz); + return !syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz); +#endif } diff --git a/src/unistd/lseek.c b/src/unistd/lseek.c index 0a5ed392..d2425e72 100644 --- a/src/unistd/lseek.c +++ b/src/unistd/lseek.c @@ -4,12 +4,17 @@ off_t lseek(int fd, off_t offset, int whence) { +#ifdef __EMSCRIPTEN__ + off_t result; + return __wasi_syscall_ret(__wasi_fd_seek(fd, offset, whence, &result)) ? -1 : result; +#else #ifdef SYS__llseek off_t result; return syscall(SYS__llseek, fd, offset>>32, offset, &result, whence) ? -1 : result; #else return syscall(SYS_lseek, fd, offset, whence); #endif +#endif // __EMSCRIPTEN__ } LFS64(lseek); diff --git a/src/unistd/pipe2.c b/src/unistd/pipe2.c index f24f74fb..9e4e8549 100644 --- a/src/unistd/pipe2.c +++ b/src/unistd/pipe2.c @@ -10,10 +10,12 @@ int pipe2(int fd[2], int flag) if (ret != -ENOSYS) return __syscall_ret(ret); ret = pipe(fd); if (ret) return ret; +#ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process if (flag & O_CLOEXEC) { __syscall(SYS_fcntl, fd[0], F_SETFD, FD_CLOEXEC); __syscall(SYS_fcntl, fd[1], F_SETFD, FD_CLOEXEC); } +#endif if (flag & O_NONBLOCK) { __syscall(SYS_fcntl, fd[0], F_SETFL, O_NONBLOCK); __syscall(SYS_fcntl, fd[1], F_SETFL, O_NONBLOCK); diff --git a/src/unistd/pread.c b/src/unistd/pread.c index 3d2799fd..a1278b38 100644 --- a/src/unistd/pread.c +++ b/src/unistd/pread.c @@ -4,7 +4,19 @@ ssize_t pread(int fd, void *buf, size_t size, off_t ofs) { +#if __EMSCRIPTEN__ + __wasi_iovec_t iov = { + .buf = buf, + .buf_len = size + }; + size_t num; + if (__wasi_syscall_ret(__wasi_fd_pread(fd, &iov, 1, ofs, &num))) { + return -1; + } + return num; +#else return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL_O(ofs)); +#endif } LFS64(pread); diff --git a/src/unistd/preadv.c b/src/unistd/preadv.c index 46d9ece7..8cdf6613 100644 --- a/src/unistd/preadv.c +++ b/src/unistd/preadv.c @@ -6,8 +6,16 @@ ssize_t preadv(int fd, const struct iovec *iov, int count, off_t ofs) { +#if __EMSCRIPTEN__ + size_t num; + if (__wasi_syscall_ret(__wasi_fd_pread(fd, (struct __wasi_iovec_t*)iov, count, ofs, &num))) { + return -1; + } + return num; +#else return syscall_cp(SYS_preadv, fd, iov, count, (long)(ofs), (long)(ofs>>32)); +#endif } LFS64(preadv); diff --git a/src/unistd/pwrite.c b/src/unistd/pwrite.c index bbe4c345..7e83fec7 100644 --- a/src/unistd/pwrite.c +++ b/src/unistd/pwrite.c @@ -4,7 +4,19 @@ ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs) { +#if __EMSCRIPTEN__ + __wasi_ciovec_t iov = { + .buf = buf, + .buf_len = size + }; + size_t num; + if (__wasi_syscall_ret(__wasi_fd_pwrite(fd, &iov, 1, ofs, &num))) { + return -1; + } + return num; +#else return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL_O(ofs)); +#endif } LFS64(pwrite); diff --git a/src/unistd/pwritev.c b/src/unistd/pwritev.c index aec5d323..1c3e3139 100644 --- a/src/unistd/pwritev.c +++ b/src/unistd/pwritev.c @@ -6,8 +6,16 @@ ssize_t pwritev(int fd, const struct iovec *iov, int count, off_t ofs) { +#if __EMSCRIPTEN__ + size_t num; + if (__wasi_syscall_ret(__wasi_fd_pwrite(fd, (struct __wasi_ciovec_t*)iov, count, ofs, &num))) { + return -1; + } + return num; +#else return syscall_cp(SYS_pwritev, fd, iov, count, (long)(ofs), (long)(ofs>>32)); +#endif } LFS64(pwritev); diff --git a/src/unistd/read.c b/src/unistd/read.c index eb882fcc..12835fe8 100644 --- a/src/unistd/read.c +++ b/src/unistd/read.c @@ -4,5 +4,17 @@ ssize_t read(int fd, void *buf, size_t count) { +#if __EMSCRIPTEN__ + __wasi_iovec_t iov = { + .buf = buf, + .buf_len = count + }; + size_t num; + if (__wasi_syscall_ret(__wasi_fd_read(fd, &iov, 1, &num))) { + return -1; + } + return num; +#else return syscall_cp(SYS_read, fd, buf, count); +#endif } diff --git a/src/unistd/readv.c b/src/unistd/readv.c index e45cb484..ea736a2a 100644 --- a/src/unistd/readv.c +++ b/src/unistd/readv.c @@ -4,5 +4,13 @@ ssize_t readv(int fd, const struct iovec *iov, int count) { +#if __EMSCRIPTEN__ + size_t num; + if (__wasi_syscall_ret(__wasi_fd_read(fd, (struct __wasi_iovec_t*)iov, count, &num))) { + num = -1; + } + return num; +#else return syscall_cp(SYS_readv, fd, iov, count); +#endif } diff --git a/src/unistd/setxid.c b/src/unistd/setxid.c index 0239f8af..dc1377f7 100644 --- a/src/unistd/setxid.c +++ b/src/unistd/setxid.c @@ -13,6 +13,10 @@ static void do_setxid(void *p) { struct ctx *c = p; if (c->err>0) return; +#ifdef __EMSCRIPTEN__ + c->err = EPERM; // we don't allow dynamic syscalls, and don't need to support these anyhow + return; +#else int ret = -__syscall(c->nr, c->id, c->eid, c->sid); if (ret && !c->err) { /* If one thread fails to set ids after another has already @@ -23,6 +27,7 @@ static void do_setxid(void *p) __syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL); } c->err = ret; +#endif } int __setxid(int nr, int id, int eid, int sid) diff --git a/src/unistd/usleep.c b/src/unistd/usleep.c index 6c966526..e850a30b 100644 --- a/src/unistd/usleep.c +++ b/src/unistd/usleep.c @@ -1,12 +1,20 @@ #define _GNU_SOURCE #include #include +#ifdef __EMSCRTIPEN__ +#include +#endif int usleep(unsigned useconds) { +#ifdef __EMSCRTIPEN__ + emscripten_thread_sleep(usec / 1e3); + return 0; +#else struct timespec tv = { .tv_sec = useconds/1000000, .tv_nsec = (useconds%1000000)*1000 }; return nanosleep(&tv, &tv); +#endif } diff --git a/src/unistd/write.c b/src/unistd/write.c index e2f7e1f2..f78d06c1 100644 --- a/src/unistd/write.c +++ b/src/unistd/write.c @@ -4,5 +4,17 @@ ssize_t write(int fd, const void *buf, size_t count) { +#if __EMSCRIPTEN__ + __wasi_ciovec_t iov = { + .buf = buf, + .buf_len = count + }; + size_t num; + if (__wasi_syscall_ret(__wasi_fd_write(fd, &iov, 1, &num))) { + return -1; + } + return num; +#else return syscall_cp(SYS_write, fd, buf, count); +#endif } diff --git a/src/unistd/writev.c b/src/unistd/writev.c index ef300ddf..c68b50f9 100644 --- a/src/unistd/writev.c +++ b/src/unistd/writev.c @@ -1,8 +1,17 @@ #include #include "syscall.h" #include "libc.h" +#include ssize_t writev(int fd, const struct iovec *iov, int count) { +#if __EMSCRIPTEN__ + size_t num; + if (__wasi_syscall_ret(__wasi_fd_write(fd, (struct __wasi_ciovec_t*)iov, count, &num))) { + return -1; + } + return num; +#else return syscall_cp(SYS_writev, fd, iov, count); +#endif } From 144d56a1c0159cb8ebee9b02013e9ba9e17a2cc3 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 18 Jan 2021 08:42:27 -0800 Subject: [PATCH 002/297] Update to emscripten master@540d3ba16 --- arch/emscripten/bits/alltypes.h | 12 ++++++++++-- include/threads.h | 5 ----- src/internal/pthread_impl.h | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/emscripten/bits/alltypes.h b/arch/emscripten/bits/alltypes.h index 32c14dc5..c3768afe 100644 --- a/arch/emscripten/bits/alltypes.h +++ b/arch/emscripten/bits/alltypes.h @@ -95,16 +95,24 @@ typedef struct { union { int __i[10]; volatile int __vi[10]; unsigned __s[10]; } #if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t) typedef struct { union { int __i[7]; volatile int __vi[7]; volatile void *__p[7]; } __u; } pthread_mutex_t; -typedef pthread_mutex_t mtx_t; #define __DEFINED_pthread_mutex_t #endif +#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t) +typedef struct { union { int __i[7]; volatile int __vi[7]; volatile void *__p[7]; } __u; } mtx_t; +#define __DEFINED_mtx_t +#endif + #if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t) typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t; -typedef pthread_cond_t cnd_t; #define __DEFINED_pthread_cond_t #endif +#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t) +typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t; +#define __DEFINED_cnd_t +#endif + #if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t) typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t; #define __DEFINED_pthread_rwlock_t diff --git a/include/threads.h b/include/threads.h index a9024028..01794826 100644 --- a/include/threads.h +++ b/include/threads.h @@ -20,11 +20,6 @@ typedef void (*tss_dtor_t)(void *); #define __NEED_cnd_t #define __NEED_mtx_t -// XXX Emscripten: Fix musl libc issue, where the above defines are wrong, but instead should be the following: (https://github.com/emscripten-core/emscripten/issues/5343) -#define __NEED_pthread_cond_t -#define __NEED_pthread_mutex_t -// XXX - #include #define TSS_DTOR_ITERATIONS 4 diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index bcdda727..4bf78350 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -22,7 +22,7 @@ struct pthread { // by direct pointer arithmetic in worker.js. int threadStatus; // 0: thread not exited, 1: exited. int threadExitCode; // Thread exit code. - void *profilerBlock; // If --threadprofiling is enabled, this pointer is allocated to contain internal information about the thread state for profiling purposes. + void *profilerBlock; // If --threadprofiler is enabled, this pointer is allocated to contain internal information about the thread state for profiling purposes. #endif struct pthread *self; From dd5b6384712fb554bb6e291f2bbcdc9ec2f66554 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 30 Jan 2021 16:09:22 -0500 Subject: [PATCH 003/297] fail posix_spawn file_actions operations with negative fds these functions are specified to fail with EBADF on negative fd arguments. apart from close, they are also specified to fail if the value exceeds OPEN_MAX, but as written it is not clear that this imposes any requirement when OPEN_MAX is not defined, and it's undesirable to impose a dynamic limit (via setrlimit) here since the limit at the time of posix_spawn may be different from the limit at the time of setting up the file actions. this may require revisiting later. --- src/process/posix_spawn_file_actions_addclose.c | 1 + src/process/posix_spawn_file_actions_adddup2.c | 1 + src/process/posix_spawn_file_actions_addfchdir.c | 1 + src/process/posix_spawn_file_actions_addopen.c | 1 + 4 files changed, 4 insertions(+) diff --git a/src/process/posix_spawn_file_actions_addclose.c b/src/process/posix_spawn_file_actions_addclose.c index cdda5979..0c2ef8fa 100644 --- a/src/process/posix_spawn_file_actions_addclose.c +++ b/src/process/posix_spawn_file_actions_addclose.c @@ -5,6 +5,7 @@ int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, int fd) { + if (fd < 0) return EBADF; struct fdop *op = malloc(sizeof *op); if (!op) return ENOMEM; op->cmd = FDOP_CLOSE; diff --git a/src/process/posix_spawn_file_actions_adddup2.c b/src/process/posix_spawn_file_actions_adddup2.c index 0367498f..addca4d4 100644 --- a/src/process/posix_spawn_file_actions_adddup2.c +++ b/src/process/posix_spawn_file_actions_adddup2.c @@ -5,6 +5,7 @@ int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, int srcfd, int fd) { + if (srcfd < 0 || fd < 0) return EBADF; struct fdop *op = malloc(sizeof *op); if (!op) return ENOMEM; op->cmd = FDOP_DUP2; diff --git a/src/process/posix_spawn_file_actions_addfchdir.c b/src/process/posix_spawn_file_actions_addfchdir.c index 436c683d..e89ede8c 100644 --- a/src/process/posix_spawn_file_actions_addfchdir.c +++ b/src/process/posix_spawn_file_actions_addfchdir.c @@ -6,6 +6,7 @@ int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *fa, int fd) { + if (fd < 0) return EBADF; struct fdop *op = malloc(sizeof *op); if (!op) return ENOMEM; op->cmd = FDOP_FCHDIR; diff --git a/src/process/posix_spawn_file_actions_addopen.c b/src/process/posix_spawn_file_actions_addopen.c index 368922c7..82bbcec9 100644 --- a/src/process/posix_spawn_file_actions_addopen.c +++ b/src/process/posix_spawn_file_actions_addopen.c @@ -6,6 +6,7 @@ int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict fa, int fd, const char *restrict path, int flags, mode_t mode) { + if (fd < 0) return EBADF; struct fdop *op = malloc(sizeof *op + strlen(path) + 1); if (!op) return ENOMEM; op->cmd = FDOP_OPEN; From 9afed99c224ab33578623744f40d31bee84ec6ba Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 30 Jan 2021 16:42:26 -0500 Subject: [PATCH 004/297] fix inconsistent signature of __libc_start_main commit 7586360badcae6e73f04eb1b8189ce630281c4b2 removed the unused arguments from the definition of __libc_start_main, making it incompatible with the declaration at the point of call, which still passed 6 arguments. calls with mismatched function type have undefined behavior, breaking LTO and any other tooling that checks for function signature mismatch. removing the extra arguments from the point of call (crt1) is not an option for fixing this, since that would be a change in ABI surface between application and libc. adding back the extra arguments requires some care. on archs that pass arguments on the stack or that reserve argument spill space for the callee on the stack, it imposes an ABI requirement on the caller to provide such space. the modern crt1.c entry point provides such space, but originally there was arch-specific asm for the call to __libc_start_main. the last of this asm was removed in commit 6fef8cafbd0f6f185897bc87feb1ff66e2e204e1, and manual review of the code removed and its prior history was performed to check that all archs/variants passed the legacy init/fini/ldso_fini arguments. --- src/env/__libc_start_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c index 8fbe5262..c5b277bd 100644 --- a/src/env/__libc_start_main.c +++ b/src/env/__libc_start_main.c @@ -69,7 +69,8 @@ weak_alias(libc_start_init, __libc_start_init); typedef int lsm2_fn(int (*)(int,char **,char **), int, char **); static lsm2_fn libc_start_main_stage2; -int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv) +int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv, + void (*init_dummy)(), void(*fini_dummy)(), void(*ldso_dummy)()) { char **envp = argv+argc+1; From 2010df0d64570db4ce29cc7df0e31f81aa26ae4a Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 30 Jan 2021 17:14:20 -0500 Subject: [PATCH 005/297] preserve errno across free as an outcome of Austin Group issue #385, future versions of the standard will require free not to alter the value of errno. save and restore it individually around the calls to madvise and munmap so that the cost is not imposed on calls to free that do not result in any syscall. --- src/malloc/mallocng/free.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/malloc/mallocng/free.c b/src/malloc/mallocng/free.c index 40745f97..418a085c 100644 --- a/src/malloc/mallocng/free.c +++ b/src/malloc/mallocng/free.c @@ -119,7 +119,11 @@ void free(void *p) if (((uintptr_t)(start-1) ^ (uintptr_t)end) >= 2*PGSZ && g->last_idx) { unsigned char *base = start + (-(uintptr_t)start & (PGSZ-1)); size_t len = (end-base) & -PGSZ; - if (len) madvise(base, len, MADV_FREE); + if (len) { + int e = errno; + madvise(base, len, MADV_FREE); + errno = e; + } } // atomic free without locking if this is neither first or last slot @@ -139,5 +143,9 @@ void free(void *p) wrlock(); struct mapinfo mi = nontrivial_free(g, idx); unlock(); - if (mi.len) munmap(mi.base, mi.len); + if (mi.len) { + int e = errno; + munmap(mi.base, mi.len); + errno = e; + } } From 98b9df994c85dcb6a8a5a9099495dd44c7cf2bce Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 30 Jan 2021 17:26:34 -0500 Subject: [PATCH 006/297] fix build regression in oldmalloc commit 8d37958d58cf36f53d5fcc7a8aa6d633da6071b2 inadvertently broke oldmalloc by having it implement __libc_malloc rather than __libc_malloc_impl. --- src/malloc/oldmalloc/malloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/malloc/oldmalloc/malloc.c b/src/malloc/oldmalloc/malloc.c index 53f5f959..a5cbdb68 100644 --- a/src/malloc/oldmalloc/malloc.c +++ b/src/malloc/oldmalloc/malloc.c @@ -11,7 +11,7 @@ #include "malloc_impl.h" #include "fork_impl.h" -#define malloc __libc_malloc +#define malloc __libc_malloc_impl #define realloc __libc_realloc #define free __libc_free From 9b77aaca86b53c367f23505c24dd3c02e240efad Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 30 Jan 2021 17:28:08 -0500 Subject: [PATCH 007/297] oldmalloc: preserve errno across free as an outcome of Austin Group issue #385, future versions of the standard will require free not to alter the value of errno. save and restore it individually around the calls to madvise and munmap so that the cost is not imposed on calls to free that do not result in any syscall. --- src/malloc/oldmalloc/malloc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/malloc/oldmalloc/malloc.c b/src/malloc/oldmalloc/malloc.c index a5cbdb68..25d00d44 100644 --- a/src/malloc/oldmalloc/malloc.c +++ b/src/malloc/oldmalloc/malloc.c @@ -481,12 +481,14 @@ void __bin_chunk(struct chunk *self) if (size > RECLAIM && (size^(size-osize)) > size-osize) { uintptr_t a = (uintptr_t)self + SIZE_ALIGN+PAGE_SIZE-1 & -PAGE_SIZE; uintptr_t b = (uintptr_t)next - SIZE_ALIGN & -PAGE_SIZE; + int e = errno; #if 1 __madvise((void *)a, b-a, MADV_DONTNEED); #else __mmap((void *)a, b-a, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); #endif + errno = e; } unlock_bin(i); @@ -499,7 +501,9 @@ static void unmap_chunk(struct chunk *self) size_t len = CHUNK_SIZE(self) + extra; /* Crash on double free */ if (extra & 1) a_crash(); + int e = errno; __munmap(base, len); + errno = e; } void free(void *p) From 074932c84d34273821e3bfc2511e60a5ce78b8d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Rolim?= Date: Thu, 24 Dec 2020 01:18:04 -0300 Subject: [PATCH 008/297] fix possible fd leak via missing O_CLOEXEC in pthread_setname_np the omission of the flag here seems to have been an oversight when the function was added in 8fb28b0b3e7a5e958fb844722a4b2ef9bc244af1 --- src/thread/pthread_setname_np.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thread/pthread_setname_np.c b/src/thread/pthread_setname_np.c index 82d35e17..fc2d2306 100644 --- a/src/thread/pthread_setname_np.c +++ b/src/thread/pthread_setname_np.c @@ -19,7 +19,7 @@ int pthread_setname_np(pthread_t thread, const char *name) snprintf(f, sizeof f, "/proc/self/task/%d/comm", thread->tid); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); - if ((fd = open(f, O_WRONLY)) < 0 || write(fd, name, len) < 0) status = errno; + if ((fd = open(f, O_WRONLY|O_CLOEXEC)) < 0 || write(fd, name, len) < 0) status = errno; if (fd >= 0) close(fd); pthread_setcancelstate(cs, 0); return status; From c4c38e6364323b6d83ba3428464e19987b981d7a Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 5 Feb 2021 18:48:19 +0000 Subject: [PATCH 009/297] math: fix acoshf for negative inputs on some negative inputs (e.g. -0x1.1e6ae8p+5) acoshf failed to return nan. ensure that negative inputs result nan without introducing new branches. this was tried before in commit 101e6012856918440b5d7474739c3fc22a8d3b85 math: fix acoshf on negative values but that fix was wrong. there are 3 formulas used: log1p(x-1 + sqrt((x-1)*(x-1)+2*(x-1))) log(2*x - 1/(x+sqrt(x*x-1))) log(x) + 0.693147180559945309417232121458176568 the first fails on large negative inputs (may compute log1p(0) or log1p(inf)), the second one fails on some mid range or large negative inputs (may compute log(large) or log(inf)) and the last one fails on -0 (returns -inf). --- src/math/acoshf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/math/acoshf.c b/src/math/acoshf.c index 8a4ec4d5..b773d48e 100644 --- a/src/math/acoshf.c +++ b/src/math/acoshf.c @@ -15,12 +15,12 @@ float acoshf(float x) uint32_t a = u.i & 0x7fffffff; if (a < 0x3f800000+(1<<23)) - /* |x| < 2, invalid if x < 1 or nan */ + /* |x| < 2, invalid if x < 1 */ /* up to 2ulp error in [1,1.125] */ return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1))); - if (a < 0x3f800000+(12<<23)) - /* |x| < 0x1p12 */ + if (u.i < 0x3f800000+(12<<23)) + /* 2 <= x < 0x1p12 */ return logf(2*x - 1/(x+sqrtf(x*x-1))); - /* x >= 0x1p12 */ + /* x >= 0x1p12 or x <= -2 or nan */ return logf(x) + 0.693147180559945309417232121458176568f; } From 964104f9f0e056cf58d9defa0b716d7756f040f6 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 5 Feb 2021 19:51:36 +0000 Subject: [PATCH 010/297] math: fix expm1f overflow threshold the threshold was wrong so expm1f overflowed to inf a bit too early and on most targets uint32_t compare is faster than float compare so use that. this also fixes sinhf incorrectly returning nan for some values where the internal expm1f overflowed. --- src/math/expm1f.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/math/expm1f.c b/src/math/expm1f.c index 297e0b44..09a41afe 100644 --- a/src/math/expm1f.c +++ b/src/math/expm1f.c @@ -16,7 +16,6 @@ #include "libm.h" static const float -o_threshold = 8.8721679688e+01, /* 0x42b17180 */ ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */ @@ -41,7 +40,7 @@ float expm1f(float x) return x; if (sign) return -1; - if (x > o_threshold) { + if (hx > 0x42b17217) { /* x > log(FLT_MAX) */ x *= 0x1p127f; return x; } From e5d2823631bbfebacf48e1a34ed28f28d7cb2570 Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Mon, 11 Jan 2021 09:40:33 -0800 Subject: [PATCH 011/297] riscv64: define ELF_NFPREG ELF_NFPREG is used by some userspace applications like gdb --- arch/riscv64/bits/user.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/riscv64/bits/user.h b/arch/riscv64/bits/user.h index 2da743ea..0d37de0b 100644 --- a/arch/riscv64/bits/user.h +++ b/arch/riscv64/bits/user.h @@ -1,5 +1,6 @@ #include #define ELF_NGREG 32 +#define ELF_NFPREG 33 typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG]; typedef union __riscv_mc_fp_state elf_fpregset_t; From ef137da6428c342baabd3bcf9b5e91f75acefa64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Wed, 29 Jan 2020 12:20:07 +0100 Subject: [PATCH 012/297] cuserid: support invocation with a null pointer argument this function was removed from the standard in 2001 but appeared in SUSv2 with an obligation to support calls with a null pointer argument, using a static buffer. --- src/legacy/cuserid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/legacy/cuserid.c b/src/legacy/cuserid.c index 4e78798d..fd7832e4 100644 --- a/src/legacy/cuserid.c +++ b/src/legacy/cuserid.c @@ -5,10 +5,12 @@ char *cuserid(char *buf) { + static char usridbuf[L_cuserid]; struct passwd pw, *ppw; long pwb[256]; if (getpwuid_r(geteuid(), &pw, (void *)pwb, sizeof pwb, &ppw)) return 0; + if (!buf) buf = usridbuf; snprintf(buf, L_cuserid, "%s", pw.pw_name); return buf; } From a75283d777ed1827ed247dbb465818a0ce371c8f Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 13 Feb 2021 13:54:00 -0500 Subject: [PATCH 013/297] cuserid: don't return truncated results checking the length also drops the need to pull in snprintf. --- src/legacy/cuserid.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/legacy/cuserid.c b/src/legacy/cuserid.c index fd7832e4..3ff115a1 100644 --- a/src/legacy/cuserid.c +++ b/src/legacy/cuserid.c @@ -2,6 +2,7 @@ #include #include #include +#include char *cuserid(char *buf) { @@ -10,7 +11,10 @@ char *cuserid(char *buf) long pwb[256]; if (getpwuid_r(geteuid(), &pw, (void *)pwb, sizeof pwb, &ppw)) return 0; + size_t len = strnlen(pw.pw_name, L_cuserid); + if (len == L_cuserid) + return 0; if (!buf) buf = usridbuf; - snprintf(buf, L_cuserid, "%s", pw.pw_name); + memcpy(buf, pw.pw_name, len+1); return buf; } From cc577d0e058b53df5c0fe2ac17890a41d77e94c5 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 13 Feb 2021 13:59:44 -0500 Subject: [PATCH 014/297] fix misuse of getpwuid_r in cuserid getpwuid_r can return 0 but without a result in the case where there was no error but no record exists. in that case cuserid was treating it as success and copying junk out of pw.pw_name to the output buffer. --- src/legacy/cuserid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/legacy/cuserid.c b/src/legacy/cuserid.c index 3ff115a1..07866acf 100644 --- a/src/legacy/cuserid.c +++ b/src/legacy/cuserid.c @@ -9,7 +9,8 @@ char *cuserid(char *buf) static char usridbuf[L_cuserid]; struct passwd pw, *ppw; long pwb[256]; - if (getpwuid_r(geteuid(), &pw, (void *)pwb, sizeof pwb, &ppw)) + getpwuid_r(geteuid(), &pw, (void *)pwb, sizeof pwb, &ppw); + if (!ppw) return 0; size_t len = strnlen(pw.pw_name, L_cuserid); if (len == L_cuserid) From 49b6df3d9f3645de55607f1ac60095b22661b334 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 13 Feb 2021 14:03:23 -0500 Subject: [PATCH 015/297] fix error return value for cuserid the historical function was specified to return an empty string in the caller-provided buffer, not a null pointer, to indicate error when the argument is non-null. only when the argument is null should it return a null pointer on error. --- src/legacy/cuserid.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/legacy/cuserid.c b/src/legacy/cuserid.c index 07866acf..dcaf73d4 100644 --- a/src/legacy/cuserid.c +++ b/src/legacy/cuserid.c @@ -9,12 +9,13 @@ char *cuserid(char *buf) static char usridbuf[L_cuserid]; struct passwd pw, *ppw; long pwb[256]; + if (buf) *buf = 0; getpwuid_r(geteuid(), &pw, (void *)pwb, sizeof pwb, &ppw); if (!ppw) - return 0; + return buf; size_t len = strnlen(pw.pw_name, L_cuserid); if (len == L_cuserid) - return 0; + return buf; if (!buf) buf = usridbuf; memcpy(buf, pw.pw_name, len+1); return buf; From fd285f9dec226ca9e5377888ee24e3f8f5ada49f Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 20:12:31 +0000 Subject: [PATCH 016/297] bits/syscall.h: add process_madvise from linux v5.10 mainly added to linux to allow a central process management service in android to give MADV_COLD|PAGEOUT hints for other processes, see linux commit ecb8ac8b1f146915aa6b96449b66dd48984caacc mm/madvise: introduce process_madvise() syscall: an external memory hinting API --- arch/aarch64/bits/syscall.h.in | 1 + arch/arm/bits/syscall.h.in | 1 + arch/i386/bits/syscall.h.in | 1 + arch/m68k/bits/syscall.h.in | 1 + arch/microblaze/bits/syscall.h.in | 1 + arch/mips/bits/syscall.h.in | 1 + arch/mips64/bits/syscall.h.in | 1 + arch/mipsn32/bits/syscall.h.in | 1 + arch/or1k/bits/syscall.h.in | 1 + arch/powerpc/bits/syscall.h.in | 1 + arch/powerpc64/bits/syscall.h.in | 1 + arch/riscv64/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/sh/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 16 files changed, 16 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index f9457c18..1ad467c0 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -293,4 +293,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index 7e2fc266..cf9e3411 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -393,6 +393,7 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index abdb210d..5d1c4d7a 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -430,4 +430,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index e10969a2..6794b1a0 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -410,3 +410,4 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index 9d469047..7f71df3b 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -431,4 +431,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index 2bb03f06..d54845b2 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -412,4 +412,5 @@ #define __NR_openat2 4437 #define __NR_pidfd_getfd 4438 #define __NR_faccessat2 4439 +#define __NR_process_madvise 4440 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index 045e8238..920b4358 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -342,4 +342,5 @@ #define __NR_openat2 5437 #define __NR_pidfd_getfd 5438 #define __NR_faccessat2 5439 +#define __NR_process_madvise 5440 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index 5b322558..e6dad688 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -366,4 +366,5 @@ #define __NR_openat2 6437 #define __NR_pidfd_getfd 6438 #define __NR_faccessat2 6439 +#define __NR_process_madvise 6440 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index b3603891..463ee901 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -315,4 +315,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index 5c6fae3e..db4d0ca4 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -419,4 +419,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index edf73d3d..a128890b 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -391,4 +391,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index 5def016b..f9c421d0 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -293,6 +293,7 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index fb2e60e3..9c8d984e 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -356,4 +356,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index 158afc09..17dd7e07 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -403,4 +403,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index cfd9856f..5361442e 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -302,6 +302,7 @@ #define __NR_openat2 (0x40000000 + 437) #define __NR_pidfd_getfd (0x40000000 + 438) #define __NR_faccessat2 (0x40000000 + 439) +#define __NR_process_madvise (0x40000000 + 440) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index a6117951..e943883d 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -349,4 +349,5 @@ #define __NR_openat2 437 #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 +#define __NR_process_madvise 440 From 54ca1cc7f1bce1c19593c0176aead964a2534933 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 20:27:22 +0000 Subject: [PATCH 017/297] sys/membarrier.h: add new constants from linux v5.10 can cause rseq restart on another cpu to synchronize with global memory access from rseq critical sections, see linux commit 2a36ab717e8fe678d98f81c14a0b124712719840 rseq/membarrier: Add MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ --- include/sys/membarrier.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/sys/membarrier.h b/include/sys/membarrier.h index 10cb3108..11193eda 100644 --- a/include/sys/membarrier.h +++ b/include/sys/membarrier.h @@ -9,9 +9,13 @@ #define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED 16 #define MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE 32 #define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE 64 +#define MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ 128 +#define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ 256 #define MEMBARRIER_CMD_SHARED MEMBARRIER_CMD_GLOBAL +#define MEMBARRIER_CMD_FLAG_CPU 1 + int membarrier(int, int); #endif From a7456524d7bc95db76998804c8dc4bcfbeccab22 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 20:56:23 +0000 Subject: [PATCH 018/297] sys/mount.h: add MS_NOSYMFOLLOW from linux v5.10 path resolution does not follow symlinks on nosymfollow mounts (but readlink still does), see linux commit dab741e0e02bd3c4f5e2e97be74b39df2523fc6e Add a "nosymfollow" mount option. --- include/sys/mount.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sys/mount.h b/include/sys/mount.h index 57a89c09..09bd6e9d 100644 --- a/include/sys/mount.h +++ b/include/sys/mount.h @@ -31,6 +31,7 @@ extern "C" { #define MS_REMOUNT 32 #define MS_MANDLOCK 64 #define MS_DIRSYNC 128 +#define MS_NOSYMFOLLOW 256 #define MS_NOATIME 1024 #define MS_NODIRATIME 2048 #define MS_BIND 4096 From d7210f0c123c4de5110b80f26b8ea460b9799eeb Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 21:02:21 +0000 Subject: [PATCH 019/297] sys/mman.h: add MAP_HUGE_16KB from linux v5.10 see linux commit e47168f3d1b14af5281cf50c59561d59d28201f9 powerpc/8xx: Support 16k hugepages with 4k pages --- include/sys/mman.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sys/mman.h b/include/sys/mman.h index 4d603e91..80a3baae 100644 --- a/include/sys/mman.h +++ b/include/sys/mman.h @@ -40,6 +40,7 @@ extern "C" { #define MAP_HUGE_SHIFT 26 #define MAP_HUGE_MASK 0x3f +#define MAP_HUGE_16KB (14 << 26) #define MAP_HUGE_64KB (16 << 26) #define MAP_HUGE_512KB (19 << 26) #define MAP_HUGE_1MB (20 << 26) From 8b29f02370cb3d789da4f57a1db726e5709fccde Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 21:06:06 +0000 Subject: [PATCH 020/297] elf.h: add NT_ARM_TAGGED_ADDR_CTRL from linux v5.10 see linux commit 2200aa7154cb7ef76bac93e98326883ba64bfa2e arm64: mte: ptrace: Add NT_ARM_TAGGED_ADDR_CTRL regset --- include/elf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/elf.h b/include/elf.h index b5e7befb..5170f3e2 100644 --- a/include/elf.h +++ b/include/elf.h @@ -686,6 +686,7 @@ typedef struct { #define NT_ARM_PAC_MASK 0x406 #define NT_ARM_PACA_KEYS 0x407 #define NT_ARM_PACG_KEYS 0x408 +#define NT_ARM_TAGGED_ADDR_CTRL 0x409 #define NT_METAG_CBUF 0x500 #define NT_METAG_RPIPE 0x501 #define NT_METAG_TLS 0x502 From 19239cde94ff08c008b72f041676712dc447b80f Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 21:10:26 +0000 Subject: [PATCH 021/297] sys/prctl.h: add MTE related constants from linux v5.10 these are for the aarch64 MTE (memory tagging extension), see linux commit 1c101da8b971a36695319dce7a24711dc567a0dd arm64: mte: Allow user control of the tag check mode via prctl() linux commit af5ce95282dc99d08a27a407a02c763dde1c5558 arm64: mte: Allow user control of the generated random tags via prctl() --- include/sys/prctl.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/sys/prctl.h b/include/sys/prctl.h index 4b9fcc05..4ba73f42 100644 --- a/include/sys/prctl.h +++ b/include/sys/prctl.h @@ -157,6 +157,13 @@ struct prctl_mm_map { #define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_GET_TAGGED_ADDR_CTRL 56 #define PR_TAGGED_ADDR_ENABLE (1UL << 0) +#define PR_MTE_TCF_SHIFT 1 +#define PR_MTE_TCF_NONE (0UL << 1) +#define PR_MTE_TCF_SYNC (1UL << 1) +#define PR_MTE_TCF_ASYNC (2UL << 1) +#define PR_MTE_TCF_MASK (3UL << 1) +#define PR_MTE_TAG_SHIFT 3 +#define PR_MTE_TAG_MASK (0xffffUL << 3) #define PR_SET_IO_FLUSHER 57 #define PR_GET_IO_FLUSHER 58 From 87b8f14811abe5b707ebe109296bcb0efbebcce2 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 22:12:50 +0000 Subject: [PATCH 022/297] signal.h: add MTE specific SIGSEGV codes from linux v5.10 add synchronouse and asynchronous tag check failure codes, see linux commit 74f1082487feb90bbf880af14beb8e29c3030c9f arm64: mte: Add specific SIGSEGV codes --- include/signal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/signal.h b/include/signal.h index 9ed929e4..f270a594 100644 --- a/include/signal.h +++ b/include/signal.h @@ -75,6 +75,8 @@ typedef struct sigaltstack stack_t; #define SEGV_ACCERR 2 #define SEGV_BNDERR 3 #define SEGV_PKUERR 4 +#define SEGV_MTEAERR 8 +#define SEGV_MTESERR 9 #define BUS_ADRALN 1 #define BUS_ADRERR 2 From b7554b5e12c2ce129eae8626028f91316df6771a Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 22:22:58 +0000 Subject: [PATCH 023/297] aarch64/bits/hwcap.h: add HWCAP2_BTI from linux v5.8 hwcap for BTI was missing, see linux commit 8ef8f360cf30be12382f89ff48a57fbbd9b31c14 arm64: Basic Branch Target Identification support --- arch/aarch64/bits/hwcap.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/aarch64/bits/hwcap.h b/arch/aarch64/bits/hwcap.h index 7ab73f99..725afeb2 100644 --- a/arch/aarch64/bits/hwcap.h +++ b/arch/aarch64/bits/hwcap.h @@ -48,3 +48,4 @@ #define HWCAP2_BF16 (1 << 14) #define HWCAP2_DGH (1 << 15) #define HWCAP2_RNG (1 << 16) +#define HWCAP2_BTI (1 << 17) From 42aa19a0fefc5c38f6e00734afae80d42ab3bd48 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 22:25:03 +0000 Subject: [PATCH 024/297] add aarch64/bits/mman.h with PROT_BTI from linux v5.8 this was missing, see linux commit 8ef8f360cf30be12382f89ff48a57fbbd9b31c14 arm64: Basic Branch Target Identification support --- arch/aarch64/bits/mman.h | 1 + 1 file changed, 1 insertion(+) create mode 100644 arch/aarch64/bits/mman.h diff --git a/arch/aarch64/bits/mman.h b/arch/aarch64/bits/mman.h new file mode 100644 index 00000000..6d9d8850 --- /dev/null +++ b/arch/aarch64/bits/mman.h @@ -0,0 +1 @@ +#define PROT_BTI 0x10 From 44331150c19064594abbad2d34dd7851dc0a0b31 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 22:26:51 +0000 Subject: [PATCH 025/297] aarch64/bits/hwcap.h: add HWCAP2_MTE from linux v5.10 see linux commit 3b714d24ef173f81c78af16f73dcc9b40428c803 arm64: mte: CPU feature detection and initial sysreg configuration --- arch/aarch64/bits/hwcap.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/aarch64/bits/hwcap.h b/arch/aarch64/bits/hwcap.h index 725afeb2..424cc4d4 100644 --- a/arch/aarch64/bits/hwcap.h +++ b/arch/aarch64/bits/hwcap.h @@ -49,3 +49,4 @@ #define HWCAP2_DGH (1 << 15) #define HWCAP2_RNG (1 << 16) #define HWCAP2_BTI (1 << 17) +#define HWCAP2_MTE (1 << 18) From 3309e2d7a1aa82e52d7ac0facd64f9b5c28f923b Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 19 Dec 2020 22:29:19 +0000 Subject: [PATCH 026/297] aarch64/bits/mman.h: add PROT_MTE from linux v5.10 see linux commit 9f3419315f3cdc41a7318e4d50ba18a592b30c8c arm64: mte: Add PROT_MTE support to mmap() and mprotect() --- arch/aarch64/bits/mman.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/aarch64/bits/mman.h b/arch/aarch64/bits/mman.h index 6d9d8850..8fad5ceb 100644 --- a/arch/aarch64/bits/mman.h +++ b/arch/aarch64/bits/mman.h @@ -1 +1,2 @@ #define PROT_BTI 0x10 +#define PROT_MTE 0x20 From b129cd8690da492b25b66061e29e52aae235f1e3 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 22 Feb 2021 15:52:21 -0500 Subject: [PATCH 027/297] guard against compilers failing to handle setjmp specially by default since 4.1, gcc has had the __returns_twice__ attribute and has required functions which return twice to carry it; however it's always applied it automatically to known setjmp-like function names. clang however does not do this reliably, at least not with -ffreestanding and possibly under other conditions, resulting in silent emission of wrong code. since the symbol name setjmp is in no way special (setjmp is specified as a macro that could expand to use any implementation-specific symbol name or names), a compiler is justified not to do anything special without further hints, and it's reasonable to do what we can to provide such hints. gcc 4.0.x and earlier do not recognize the attribute, so make use conditional on __GNUC__ macros. clang and other gcc-like compilers report (and have always reported) a later "GNUC" version so the preprocessor conditional should function as desired for them as too. undefine the internal macro after use so that nothing abuses it as a public feature. --- include/setjmp.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/include/setjmp.h b/include/setjmp.h index 2d43abf8..1976af23 100644 --- a/include/setjmp.h +++ b/include/setjmp.h @@ -15,25 +15,33 @@ typedef struct __jmp_buf_tag { unsigned long __ss[128/sizeof(long)]; } jmp_buf[1]; +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) +#define __setjmp_attr __attribute__((__returns_twice__)) +#else +#define __setjmp_attr +#endif + #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ || defined(_BSD_SOURCE) typedef jmp_buf sigjmp_buf; -int sigsetjmp (sigjmp_buf, int); +int sigsetjmp (sigjmp_buf, int) __setjmp_attr; _Noreturn void siglongjmp (sigjmp_buf, int); #endif #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ || defined(_BSD_SOURCE) -int _setjmp (jmp_buf); +int _setjmp (jmp_buf) __setjmp_attr; _Noreturn void _longjmp (jmp_buf, int); #endif -int setjmp (jmp_buf); +int setjmp (jmp_buf) __setjmp_attr; _Noreturn void longjmp (jmp_buf, int); #define setjmp setjmp +#undef __setjmp_attr + #ifdef __cplusplus } #endif From e48e99c112246fb580596404074445cb25d7858d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Rolim?= Date: Mon, 4 Jan 2021 22:48:34 -0300 Subject: [PATCH 028/297] suppress isascii() macro for C++ analogous to commit a60457c84a4b59ab564d7f4abb660a70283ba98d. --- include/ctype.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/ctype.h b/include/ctype.h index 7936536f..32bcef4d 100644 --- a/include/ctype.h +++ b/include/ctype.h @@ -64,7 +64,9 @@ int isascii(int); int toascii(int); #define _tolower(a) ((a)|0x20) #define _toupper(a) ((a)&0x5f) +#ifndef __cplusplus #define isascii(a) (0 ? isascii(a) : (unsigned)(a) < 128) +#endif #endif From cfdfd5ea3ce14c6abf7fb22a531f3d99518b5a1b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 5 Mar 2021 11:09:32 -0500 Subject: [PATCH 029/297] don't fail to map library/executable with zero-length segment maps reportedly the GNU linker can emit such segments, causing spurious failure to load due to mmap with a length of zero producing EINVAL. no action is required for such a load map (it's effectively a nop in the program headers table) so just treat it as always successful. --- ldso/dynlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 6b868c84..aaadcce0 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -579,6 +579,7 @@ static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t of { static int no_map_fixed; char *q; + if (!n) return p; if (!no_map_fixed) { q = mmap(p, n, prot, flags|MAP_FIXED, fd, off); if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL) From 8ef9d46f4d0ff4f0073da6bee7ed0cb5f9035ead Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 15 Mar 2021 10:21:29 -0400 Subject: [PATCH 030/297] use internal malloc for posix_spawn file actions objects this makes it possible to perform actions on file actions objects with a libc-internal lock held without creating lock order relationships that are silently imposed on an application-provided malloc. --- src/process/fdop.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/process/fdop.h b/src/process/fdop.h index 5adf1443..7cf733b2 100644 --- a/src/process/fdop.h +++ b/src/process/fdop.h @@ -10,3 +10,8 @@ struct fdop { mode_t mode; char path[]; }; + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc undef +#define free __libc_free From 122002f0ddf267977282f05066a0794e31661501 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 15 Mar 2021 10:26:21 -0400 Subject: [PATCH 031/297] remove no-longer-needed special case handling in popen popen was special-casing the possibility (only possible when the parent closed stdin and/or stdout) that the child's end of the pipe was already on the final desired fd number, in which case there was no way to get rid of its close-on-exec flag in the child. commit 6fc6ca1a323bc0b6b9e9cdc8fa72221ae18fe206 made this unnecessary by implementing the POSIX-future requirement that dup2 file actions with equal source and destination fd values remove the close-on-exec flag. --- src/stdio/popen.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/stdio/popen.c b/src/stdio/popen.c index 92cb57ee..b53a5572 100644 --- a/src/stdio/popen.c +++ b/src/stdio/popen.c @@ -33,21 +33,6 @@ FILE *popen(const char *cmd, const char *mode) } FLOCK(f); - /* If the child's end of the pipe happens to already be on the final - * fd number to which it will be assigned (either 0 or 1), it must - * be moved to a different fd. Otherwise, there is no safe way to - * remove the close-on-exec flag in the child without also creating - * a file descriptor leak race condition in the parent. */ - if (p[1-op] == 1-op) { - int tmp = fcntl(1-op, F_DUPFD_CLOEXEC, 0); - if (tmp < 0) { - e = errno; - goto fail; - } - __syscall(SYS_close, p[1-op]); - p[1-op] = tmp; - } - e = ENOMEM; if (!posix_spawn_file_actions_init(&fa)) { if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) { @@ -64,7 +49,6 @@ FILE *popen(const char *cmd, const char *mode) } posix_spawn_file_actions_destroy(&fa); } -fail: fclose(f); __syscall(SYS_close, p[1-op]); From 521b4d27a00b12b238b3d4284a2c490daf851ab1 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 26 Mar 2021 13:35:41 -0400 Subject: [PATCH 032/297] fix dl_iterate_phdr dlpi_tls_data reporting to match spec dl_iterate_phdr was wrongly reporting the address of the DSO's PT_TLS image rather than the calling thread's instance of the TLS. the man page, which is essentially normative for a nonstandard function of this sort, clearly specifies the latter. it does not clarify where exactly within/relative-to the image the pointer should point, but the reasonable thing to do is match the ABI's DTP offset, and this seems to be what other implementations do. --- ldso/dynlink.c | 2 +- src/ldso/dl_iterate_phdr.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index aaadcce0..b66ad537 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -2331,7 +2331,7 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void info.dlpi_adds = gencnt; info.dlpi_subs = 0; info.dlpi_tls_modid = current->tls_id; - info.dlpi_tls_data = current->tls.image; + info.dlpi_tls_data = __tls_get_addr((tls_mod_off_t[]){current->tls_id,0}); ret = (callback)(&info, sizeof (info), data); diff --git a/src/ldso/dl_iterate_phdr.c b/src/ldso/dl_iterate_phdr.c index 86c87ef8..9546dd36 100644 --- a/src/ldso/dl_iterate_phdr.c +++ b/src/ldso/dl_iterate_phdr.c @@ -1,5 +1,6 @@ #include #include +#include "pthread_impl.h" #include "libc.h" #define AUX_CNT 38 @@ -35,7 +36,7 @@ static int static_dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size info.dlpi_subs = 0; if (tls_phdr) { info.dlpi_tls_modid = 1; - info.dlpi_tls_data = (void *)(base + tls_phdr->p_vaddr); + info.dlpi_tls_data = __tls_get_addr((tls_mod_off_t[]){1,0}); } else { info.dlpi_tls_modid = 0; info.dlpi_tls_data = 0; From 2c00f95c1ac7dd50f53d9e361847ebd2513c8da0 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 3 Apr 2021 21:16:41 -0400 Subject: [PATCH 033/297] make epoll_[p]wait a cancellation point this is a Linux-specific function and not covered by POSIX's requirements for which interfaces are cancellation points, but glibc makes it one and existing software relies on it being one. at some point a review for similar functions that should be made cancellation points should be done. --- src/linux/epoll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linux/epoll.c b/src/linux/epoll.c index deff5b10..93baa814 100644 --- a/src/linux/epoll.c +++ b/src/linux/epoll.c @@ -24,9 +24,9 @@ int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev) int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs) { - int r = __syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8); + int r = __syscall_cp(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8); #ifdef SYS_epoll_wait - if (r==-ENOSYS && !sigs) r = __syscall(SYS_epoll_wait, fd, ev, cnt, to); + if (r==-ENOSYS && !sigs) r = __syscall_cp(SYS_epoll_wait, fd, ev, cnt, to); #endif return __syscall_ret(r); } From 95a540e176b3ebd57d6033fd23cf9fec8a5ddbe8 Mon Sep 17 00:00:00 2001 From: Dominic Chen Date: Thu, 25 Mar 2021 18:20:14 -0400 Subject: [PATCH 034/297] mallocng/aligned_alloc: check for malloc failure With mallocng, calling posix_memalign() or aligned_alloc() will SIGSEGV if the internal malloc() call returns NULL. This does not occur with oldmalloc, which explicitly checks for allocation failure. --- src/malloc/mallocng/aligned_alloc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/malloc/mallocng/aligned_alloc.c b/src/malloc/mallocng/aligned_alloc.c index 34116896..e0862a83 100644 --- a/src/malloc/mallocng/aligned_alloc.c +++ b/src/malloc/mallocng/aligned_alloc.c @@ -22,6 +22,9 @@ void *aligned_alloc(size_t align, size_t len) if (align <= UNIT) align = UNIT; unsigned char *p = malloc(len + align - UNIT); + if (!p) + return 0; + struct meta *g = get_meta(p); int idx = get_slot_index(p); size_t stride = get_stride(g); From 0ea78a6421322cab24d448670006ee2f99af3ac9 Mon Sep 17 00:00:00 2001 From: Joakim Sindholt Date: Sat, 3 Apr 2021 12:50:18 +0200 Subject: [PATCH 035/297] nscd: fall back gracefully on kernels without AF_UNIX support --- src/passwd/nscd_query.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/passwd/nscd_query.c b/src/passwd/nscd_query.c index d38e371b..dc3406b8 100644 --- a/src/passwd/nscd_query.c +++ b/src/passwd/nscd_query.c @@ -40,7 +40,15 @@ FILE *__nscd_query(int32_t req, const char *key, int32_t *buf, size_t len, int * buf[0] = NSCDVERSION; fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd < 0) return NULL; + if (fd < 0) { + if (errno == EAFNOSUPPORT) { + f = fopen("/dev/null", "re"); + if (f) + errno = errno_save; + return f; + } + return 0; + } if(!(f = fdopen(fd, "r"))) { close(fd); From aad50fcd791e009961621ddfbe3d4c245fd689a3 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 16 Apr 2021 10:20:46 -0400 Subject: [PATCH 036/297] fix regression in dl_iterate_phdr reporting of modules with no TLS __tls_get_addr should not be called with an invalid TLS module id of 0. in practice it probably "works", returning the DTV length as if it were a pointer, and the callback should probably not inspect dlpi_tls_data in this case, but it's likely that some real-world callbacks use a check on dlpi_tls_data being non-null, rather than on dlpi_tls_modid being nonzero, to conclude that the module has TLS. --- ldso/dynlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index b66ad537..8b67ef59 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -2331,7 +2331,8 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void info.dlpi_adds = gencnt; info.dlpi_subs = 0; info.dlpi_tls_modid = current->tls_id; - info.dlpi_tls_data = __tls_get_addr((tls_mod_off_t[]){current->tls_id,0}); + info.dlpi_tls_data = !current->tls_id ? 0 : + __tls_get_addr((tls_mod_off_t[]){current->tls_id,0}); ret = (callback)(&info, sizeof (info), data); From 9a40e842dfa5659c149778c5870435eb14439ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira?= Date: Thu, 15 Apr 2021 21:35:20 -0300 Subject: [PATCH 037/297] define __STDC_UTF_{16,32}__ macros these macros are used to indicate that the implementation uses, respectively, utf-16 and utf-32 encoding for char16_t and char32_t. --- include/stdc-predef.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/stdc-predef.h b/include/stdc-predef.h index f8cd4b89..af1a2799 100644 --- a/include/stdc-predef.h +++ b/include/stdc-predef.h @@ -7,4 +7,7 @@ #define __STDC_IEC_559__ 1 #endif +#define __STDC_UTF_16__ 1 +#define __STDC_UTF_32__ 1 + #endif From e74acd59a5c7d56ae0e64c4ffa5043da13ee896e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 20 Apr 2021 14:52:08 -0400 Subject: [PATCH 038/297] remove spurious lock in popen the newly allocated FILE * has not yet leaked to the application and is only visible to stdio internals until popen returns. since we do not change any fields of the structure observed by libc internals, only the pipe_pid member, locking is not necessary. --- src/stdio/popen.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/stdio/popen.c b/src/stdio/popen.c index b53a5572..19bbe7cf 100644 --- a/src/stdio/popen.c +++ b/src/stdio/popen.c @@ -31,7 +31,6 @@ FILE *popen(const char *cmd, const char *mode) __syscall(SYS_close, p[1]); return NULL; } - FLOCK(f); e = ENOMEM; if (!posix_spawn_file_actions_init(&fa)) { @@ -43,7 +42,6 @@ FILE *popen(const char *cmd, const char *mode) if (!strchr(mode, 'e')) fcntl(p[op], F_SETFD, 0); __syscall(SYS_close, p[1-op]); - FUNLOCK(f); return f; } } From e1a51185ceb4386481491e11f6dd39569b9e54f7 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 20 Apr 2021 14:55:10 -0400 Subject: [PATCH 039/297] fix popen not to leak pipes from one child to another POSIX places an obscure requirement on popen which is like a limited version of close-on-exec: "The popen() function shall ensure that any streams from previous popen() calls that remain open in the parent process are closed in the new child process." if the POSIX-future 'e' mode flag is passed, producing a pipe FILE with FD_CLOEXEC on the underlying pipe, this requirement is automatically satisfied. however, for applications which use multiple concurrent popen pipes but don't request close-on-exec, fd leaks from earlier popen calls to later ones could produce deadlock situations where processes are waiting for a pipe EOF that will never happen. to fix this, iterate through all open FILEs and add close actions for those obtained from popen. this requires holding a lock on the open file list across the posix_spawn call so that additional popen FILEs are not created after the list is traversed. note that it's still possible for another popen call to start and create its pipe while the lock is held, but such pipes are created with O_CLOEXEC and only drop close-on-exec status (when 'e' flag is omitted) under control of the lock. --- src/stdio/popen.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/stdio/popen.c b/src/stdio/popen.c index 19bbe7cf..3ec83394 100644 --- a/src/stdio/popen.c +++ b/src/stdio/popen.c @@ -34,6 +34,9 @@ FILE *popen(const char *cmd, const char *mode) e = ENOMEM; if (!posix_spawn_file_actions_init(&fa)) { + for (FILE *l = *__ofl_lock(); l; l=l->next) + if (l->pipe_pid && posix_spawn_file_actions_addclose(&fa, l->fd)) + goto fail; if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) { if (!(e = posix_spawn(&pid, "/bin/sh", &fa, 0, (char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) { @@ -42,9 +45,12 @@ FILE *popen(const char *cmd, const char *mode) if (!strchr(mode, 'e')) fcntl(p[op], F_SETFD, 0); __syscall(SYS_close, p[1-op]); + __ofl_unlock(); return f; } } +fail: + __ofl_unlock(); posix_spawn_file_actions_destroy(&fa); } fclose(f); From bd3b9c4ca5e93f10f7fd891b8c07cc0c5dfd198f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Rolim?= Date: Tue, 20 Apr 2021 16:15:15 -0300 Subject: [PATCH 040/297] add pthread_getname_np function based on the pthread_setname_np implementation --- include/pthread.h | 1 + src/thread/pthread_getname_np.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/thread/pthread_getname_np.c diff --git a/include/pthread.h b/include/pthread.h index 0492f26a..89fd9ff7 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -221,6 +221,7 @@ int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *); int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *); int pthread_getattr_np(pthread_t, pthread_attr_t *); int pthread_setname_np(pthread_t, const char *); +int pthread_getname_np(pthread_t, char *, size_t); int pthread_getattr_default_np(pthread_attr_t *); int pthread_setattr_default_np(const pthread_attr_t *); int pthread_tryjoin_np(pthread_t, void **); diff --git a/src/thread/pthread_getname_np.c b/src/thread/pthread_getname_np.c new file mode 100644 index 00000000..48d1a294 --- /dev/null +++ b/src/thread/pthread_getname_np.c @@ -0,0 +1,25 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include "pthread_impl.h" + +int pthread_getname_np(pthread_t thread, char *name, size_t len) +{ + int fd, cs, status = 0; + char f[sizeof "/proc/self/task//comm" + 3*sizeof(int)]; + + if (len < 16) return ERANGE; + + if (thread == pthread_self()) + return prctl(PR_GET_NAME, (unsigned long)name, 0UL, 0UL, 0UL) ? errno : 0; + + snprintf(f, sizeof f, "/proc/self/task/%d/comm", thread->tid); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + if ((fd = open(f, O_RDONLY|O_CLOEXEC)) < 0 || (len = read(fd, name, len)) < 0) status = errno; + else name[len-1] = 0; /* remove trailing new line only if successful */ + if (fd >= 0) close(fd); + pthread_setcancelstate(cs, 0); + return status; +} From b7a130e0b9195625ea96044ea9fbe99167b112bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira?= Date: Tue, 20 Apr 2021 16:15:18 -0300 Subject: [PATCH 041/297] remove unnecessary cast for map_library return the function already returns (void *) --- ldso/dynlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 8b67ef59..5b9c8be4 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1831,7 +1831,7 @@ void __dls3(size_t *sp, size_t *auxv) dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno)); _exit(1); } - Ehdr *ehdr = (void *)map_library(fd, &app); + Ehdr *ehdr = map_library(fd, &app); if (!ehdr) { dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]); _exit(1); From d8cb888db9329d0e1b41060ec953c586c99a4a9f Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Tue, 27 Apr 2021 15:59:55 -0700 Subject: [PATCH 042/297] remove return with expression in void function --- src/malloc/free.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/malloc/free.c b/src/malloc/free.c index f17a952c..3944f7b2 100644 --- a/src/malloc/free.c +++ b/src/malloc/free.c @@ -2,5 +2,5 @@ void free(void *p) { - return __libc_free(p); + __libc_free(p); } From 1f0c7cb1cc2170bf230623dc0b57d9a9f001af08 Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Wed, 19 May 2021 00:34:03 -0700 Subject: [PATCH 043/297] riscv: rename __NR_fstatat __NR_newfstatat on riscv64 this syscall is called __NR_newfstatat this helps the name match kernel UAPI for external programs --- arch/riscv64/bits/syscall.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index f9c421d0..39c0d650 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -76,7 +76,7 @@ #define __NR_splice 76 #define __NR_tee 77 #define __NR_readlinkat 78 -#define __NR_fstatat 79 +#define __NR_newfstatat 79 #define __NR_fstat 80 #define __NR_sync 81 #define __NR_fsync 82 From 937822abb6ac48880939be3c60e6b57bddf62cf6 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 23 Jun 2021 17:22:47 -0400 Subject: [PATCH 044/297] fix TZ parsing logic for identifying POSIX-form strings previously, the contents of the TZ variable were considered a candidate for a file/path name only if they began with a colon or contained a slash before any comma. the latter was very sloppy logic to avoid treating any valid POSIX TZ string as a file name, but it also triggered on values that are not valid POSIX TZ strings, including 3-letter timezone names without any offset. instead, only treat the TZ variable as POSIX form if it begins with a nonzero standard time name followed by +, -, or a digit. also, special case GMT and UTC to always be treated as POSIX form (with implicit zero offset) so that a stray file by the same name cannot break software that depends on setting TZ=GMT or TZ=UTC. --- src/time/__tz.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/time/__tz.c b/src/time/__tz.c index 09a6317e..3e2fcdcb 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "libc.h" #include "lock.h" #include "fork_impl.h" @@ -154,10 +155,21 @@ static void do_tzset() } if (old_tz) memcpy(old_tz, s, i+1); + int posix_form = 0; + if (*s != ':') { + p = s; + char dummy_name[TZNAME_MAX+1]; + getname(dummy_name, &p); + if (p!=s && (*p == '+' || *p == '-' || isdigit(*p) + || !strcmp(dummy_name, "UTC") + || !strcmp(dummy_name, "GMT"))) + posix_form = 1; + } + /* Non-suid can use an absolute tzfile pathname or a relative * pathame beginning with "."; in secure mode, only the * standard path will be searched. */ - if (*s == ':' || ((p=strchr(s, '/')) && !memchr(s, ',', p-s))) { + if (!posix_form) { if (*s == ':') s++; if (*s == '/' || *s == '.') { if (!libc.secure || !strcmp(s, "/etc/localtime")) From 4f3d346bffdf9ed2b1803653643dc31242490944 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Mon, 5 Jul 2021 22:37:22 +0000 Subject: [PATCH 045/297] math: fix fmaf not to depend on FE_TOWARDZERO --- src/math/fmaf.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/math/fmaf.c b/src/math/fmaf.c index 80f5cd8a..7c65acf1 100644 --- a/src/math/fmaf.c +++ b/src/math/fmaf.c @@ -77,17 +77,16 @@ float fmaf(float x, float y, float z) * If result is inexact, and exactly halfway between two float values, * we need to adjust the low-order bit in the direction of the error. */ -#ifdef FE_TOWARDZERO - fesetround(FE_TOWARDZERO); -#endif - volatile double vxy = xy; /* XXX work around gcc CSE bug */ - double adjusted_result = vxy + z; - fesetround(FE_TONEAREST); - if (result == adjusted_result) { - u.f = adjusted_result; + double err; + int neg = u.i >> 63; + if (neg == (z > xy)) + err = xy - result + z; + else + err = z - result + xy; + if (neg == (err < 0)) u.i++; - adjusted_result = u.f; - } - z = adjusted_result; + else + u.i--; + z = u.f; return z; } From 0fbd7d6683d04dcaa636df53e7fce69ece746241 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 6 Jul 2021 21:12:02 -0400 Subject: [PATCH 046/297] fix broken struct shmid_ds on powerpc (32-bit) the kernel structure has padding of the shm_segsz member up to 64 bits, as well as 2 unused longs at the end. somehow that was overlooked when the powerpc port was added, and it has been broken ever since; applications compiled with the wrong definition do not correctly see the shm_segsz, shm_cpid, and shm_lpid members. fixing the definition just by adding the missing padding would break the ABI size of the structure as well as the position of the time64 shm_atime and shm_dtime members we added at the end. instead, just move one of the unused padding members from the original end (before time64) of the structure to the position of the missing padding. this preserves size and preserves correct behavior of any compiled code that was already working. programs affected by the wrong definition need to be recompiled with the correct one. --- arch/powerpc/bits/shm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/bits/shm.h b/arch/powerpc/bits/shm.h index fb1d4020..7f1ca17e 100644 --- a/arch/powerpc/bits/shm.h +++ b/arch/powerpc/bits/shm.h @@ -8,11 +8,11 @@ struct shmid_ds { unsigned long __shm_dtime_lo; unsigned long __shm_ctime_hi; unsigned long __shm_ctime_lo; + unsigned long __pad1; size_t shm_segsz; pid_t shm_cpid; pid_t shm_lpid; unsigned long shm_nattch; - unsigned long __pad1; unsigned long __pad2; time_t shm_atime; time_t shm_dtime; From 3f701faace7addc75d16dea8a6cd769fa5b3f260 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 29 Jul 2021 23:24:58 -0400 Subject: [PATCH 047/297] fix libc-internal signal blocking on mips archs due to historical reasons, the mips signal set has 128 bits rather than 64 like on every other arch. this was special-cased correctly, at least for 32-bit mips, at one time, but was inadvertently broken in commit 7c440977db9444d7e6b1c3dcb1fdf4ee49ca4158, and seems never to have been right on mips64/n32. as consequenct of this bug, applications making use of high realtime signal numbers on mips may have been able to execute application code in contexts where doing so was unsafe. --- src/signal/block.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/signal/block.c b/src/signal/block.c index d7f61001..cc8698f0 100644 --- a/src/signal/block.c +++ b/src/signal/block.c @@ -3,9 +3,9 @@ #include static const unsigned long all_mask[] = { -#if ULONG_MAX == 0xffffffff && _NSIG == 129 +#if ULONG_MAX == 0xffffffff && _NSIG > 65 -1UL, -1UL, -1UL, -1UL -#elif ULONG_MAX == 0xffffffff +#elif ULONG_MAX == 0xffffffff || _NSIG > 65 -1UL, -1UL #else -1UL From 3eed6a6f0a400763313bc5dca6e3b22a75166dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira?= Date: Sat, 10 Jul 2021 00:24:59 -0300 Subject: [PATCH 048/297] fix error checking in pthread_getname_np len is unsigned and can never be smaller than 0. though unlikely, an error in read() would have lead to an out of bounds write to name. Reported-by: Michael Forney --- src/thread/pthread_getname_np.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thread/pthread_getname_np.c b/src/thread/pthread_getname_np.c index 48d1a294..85504e45 100644 --- a/src/thread/pthread_getname_np.c +++ b/src/thread/pthread_getname_np.c @@ -17,7 +17,7 @@ int pthread_getname_np(pthread_t thread, char *name, size_t len) snprintf(f, sizeof f, "/proc/self/task/%d/comm", thread->tid); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); - if ((fd = open(f, O_RDONLY|O_CLOEXEC)) < 0 || (len = read(fd, name, len)) < 0) status = errno; + if ((fd = open(f, O_RDONLY|O_CLOEXEC)) < 0 || (len = read(fd, name, len)) == -1) status = errno; else name[len-1] = 0; /* remove trailing new line only if successful */ if (fd >= 0) close(fd); pthread_setcancelstate(cs, 0); From b713b8b2e4b9595eec72ec3c4fe7714076d60478 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 12 Aug 2021 18:07:44 -0400 Subject: [PATCH 049/297] fix excessively slow TLS performance on some mips models commit 6d99ad91e869aab35a4d76d34c3c9eaf29482bad introduced this regression as part of a larger change, based on an incorrect assumption that rdhwr being part of the mips r2 ISA level meant that the TLS register, known in the mips documentation as UserLocal, was unconditionally present on chips providing this ISA level and would not need trap-and-emulate. this turns out to be false. based on research by Stanislav Kljuhhin and Abilio Marques, who reported the problem as a performance regression on certain routers using OpenWRT vs older uclibc-based versions, it turns out the mips manuals document the UserLocal register as a feature that might or might not be implemented or enabled, reflected by a cpu capability bit in the CONFIG3 register, and that Linux checks for this and has to explicitly enable it on models that have it. thus, it's indeed possible that r2+ chips can lack the feature, bringing us back to the situation where Linux only has a fast trap-and-emulate path for the case where the destination register is $3. so, always read the thread pointer through $3. this may incur a gratuitous move to the desired final register on chips where it's not needed, but it really doesn't matter. --- arch/mips/pthread_arch.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/mips/pthread_arch.h b/arch/mips/pthread_arch.h index c45347ab..376b7741 100644 --- a/arch/mips/pthread_arch.h +++ b/arch/mips/pthread_arch.h @@ -1,10 +1,9 @@ static inline uintptr_t __get_tp() { -#if __mips_isa_rev < 2 register uintptr_t tp __asm__("$3"); +#if __mips_isa_rev < 2 __asm__ (".word 0x7c03e83b" : "=r" (tp) ); #else - uintptr_t tp; __asm__ ("rdhwr %0, $29" : "=r" (tp) ); #endif return tp; From e3e7189c11d909199155327fd6a93dcc6b68c7b3 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Sep 2021 21:21:43 -0400 Subject: [PATCH 050/297] fix undefined behavior in getdelim via null pointer arithmetic and memcpy both passing a null pointer to memcpy with length 0, and adding 0 to a null pointer, are undefined. in some sense this is 'benign' UB, but having it precludes use of tooling that strictly traps on UB. there may be better ways to fix it, but conditioning the operations which are intended to be no-ops in the k==0 case on k being nonzero is a simple and safe solution. --- src/stdio/getdelim.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/stdio/getdelim.c b/src/stdio/getdelim.c index d2f5b15a..df114441 100644 --- a/src/stdio/getdelim.c +++ b/src/stdio/getdelim.c @@ -55,9 +55,11 @@ ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restric *s = tmp; *n = m; } - memcpy(*s+i, f->rpos, k); - f->rpos += k; - i += k; + if (k) { + memcpy(*s+i, f->rpos, k); + f->rpos += k; + i += k; + } if (z) break; if ((c = getc_unlocked(f)) == EOF) { if (!i || !feof(f)) { From 7be59733d71ada3a32a98622507399253f1d5e48 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 23 Sep 2021 19:11:46 -0400 Subject: [PATCH 051/297] add SPE FPU support to powerpc-sf When the soft-float ABI for PowerPC was added in commit 5a92dd95c77cee81755f1a441ae0b71e3ae2bcdb, with Freescale cpus using the alternative SPE FPU as the main use case, it was noted that we could probably support hard float on them, but that it would involve determining some difficult ABI constraints. This commit is the completion of that work. The Power-Arch-32 ABI supplement defines the ABI profiles, and indeed ATR-SPE is built on ATR-SOFT-FLOAT. But setjmp/longjmp compatibility are problematic for the same reason they're problematic on ARM, where optional float-related parts of the register file are "call-saved if present". This requires testing __hwcap, which is now done. In keeping with the existing powerpc-sf subarch definition, which did not have fenv, the fenv macros are not defined for SPE and the SPEFSCR control register is left (and assumed to start in) the default mode. --- arch/powerpc/bits/fenv.h | 2 +- arch/powerpc/reloc.h | 2 +- configure | 4 +--- src/fenv/powerpc/fenv-sf.c | 2 +- src/fenv/powerpc/fenv.S | 2 +- src/math/powerpc/fabs.c | 2 +- src/math/powerpc/fabsf.c | 2 +- src/math/powerpc/fma.c | 2 +- src/math/powerpc/fmaf.c | 2 +- src/setjmp/powerpc/longjmp.S | 32 +++++++++++++++++++++++++++++++- src/setjmp/powerpc/setjmp.S | 32 +++++++++++++++++++++++++++++++- 11 files changed, 71 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/bits/fenv.h b/arch/powerpc/bits/fenv.h index c5a3e5c5..5b15c69a 100644 --- a/arch/powerpc/bits/fenv.h +++ b/arch/powerpc/bits/fenv.h @@ -1,4 +1,4 @@ -#ifdef _SOFT_FLOAT +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) #define FE_ALL_EXCEPT 0 #define FE_TONEAREST 0 #else diff --git a/arch/powerpc/reloc.h b/arch/powerpc/reloc.h index 527b6b7c..fdfbf827 100644 --- a/arch/powerpc/reloc.h +++ b/arch/powerpc/reloc.h @@ -1,4 +1,4 @@ -#ifdef _SOFT_FLOAT +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) #define FP_SUFFIX "-sf" #else #define FP_SUFFIX "" diff --git a/configure b/configure index a5231a0e..e1aefed7 100755 --- a/configure +++ b/configure @@ -671,9 +671,7 @@ trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf fi if test "$ARCH" = "powerpc" ; then -trycppif "__NO_FPRS__ && !_SOFT_FLOAT" "$t" && fail \ - "$0: error: compiler's floating point configuration is unsupported" -trycppif _SOFT_FLOAT "$t" && SUBARCH=${SUBARCH}-sf +trycppif "_SOFT_FLOAT || __NO_FPRS__" "$t" && SUBARCH=${SUBARCH}-sf printf "checking whether compiler can use 'd' constraint in asm... " echo 'double f(double x) { __asm__ ("fabs %0, %1" : "=d"(x) : "d"(x)); return x; }' > "$tmpc" if $CC $CFLAGS_C99FSE $CPPFLAGS $CFLAGS -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then diff --git a/src/fenv/powerpc/fenv-sf.c b/src/fenv/powerpc/fenv-sf.c index 85bef40f..d4248f26 100644 --- a/src/fenv/powerpc/fenv-sf.c +++ b/src/fenv/powerpc/fenv-sf.c @@ -1,3 +1,3 @@ -#ifdef _SOFT_FLOAT +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) #include "../fenv.c" #endif diff --git a/src/fenv/powerpc/fenv.S b/src/fenv/powerpc/fenv.S index 22cea216..55055d0b 100644 --- a/src/fenv/powerpc/fenv.S +++ b/src/fenv/powerpc/fenv.S @@ -1,4 +1,4 @@ -#ifndef _SOFT_FLOAT +#if !defined(_SOFT_FLOAT) && !defined(__NO_FPRS__) .global feclearexcept .type feclearexcept,@function feclearexcept: diff --git a/src/math/powerpc/fabs.c b/src/math/powerpc/fabs.c index 0efc21ef..9453a3aa 100644 --- a/src/math/powerpc/fabs.c +++ b/src/math/powerpc/fabs.c @@ -1,6 +1,6 @@ #include -#if defined(_SOFT_FLOAT) || defined(BROKEN_PPC_D_ASM) +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) || defined(BROKEN_PPC_D_ASM) #include "../fabs.c" diff --git a/src/math/powerpc/fabsf.c b/src/math/powerpc/fabsf.c index d88b5911..2e9da588 100644 --- a/src/math/powerpc/fabsf.c +++ b/src/math/powerpc/fabsf.c @@ -1,6 +1,6 @@ #include -#ifdef _SOFT_FLOAT +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) #include "../fabsf.c" diff --git a/src/math/powerpc/fma.c b/src/math/powerpc/fma.c index 135c9903..0eb2ba1e 100644 --- a/src/math/powerpc/fma.c +++ b/src/math/powerpc/fma.c @@ -1,6 +1,6 @@ #include -#if defined(_SOFT_FLOAT) || defined(BROKEN_PPC_D_ASM) +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) || defined(BROKEN_PPC_D_ASM) #include "../fma.c" diff --git a/src/math/powerpc/fmaf.c b/src/math/powerpc/fmaf.c index a99a2a3b..dc1a749d 100644 --- a/src/math/powerpc/fmaf.c +++ b/src/math/powerpc/fmaf.c @@ -1,6 +1,6 @@ #include -#ifdef _SOFT_FLOAT +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) #include "../fmaf.c" diff --git a/src/setjmp/powerpc/longjmp.S b/src/setjmp/powerpc/longjmp.S index e598bd05..34aecb4c 100644 --- a/src/setjmp/powerpc/longjmp.S +++ b/src/setjmp/powerpc/longjmp.S @@ -37,7 +37,37 @@ longjmp: lwz 29, 72(3) lwz 30, 76(3) lwz 31, 80(3) -#ifndef _SOFT_FLOAT +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) + mflr 0 + bl 1f + .hidden __hwcap + .long __hwcap-. +1: mflr 4 + lwz 5, 0(4) + add 4, 4, 5 + andis. 4, 4, 0x80 + beq 1f + .long 0x11c35b01 /* evldd 14,88(3) */ + .long 0x11e36301 /* ... */ + .long 0x12036b01 + .long 0x12237301 + .long 0x12437b01 + .long 0x12638301 + .long 0x12838b01 + .long 0x12a39301 + .long 0x12c39b01 + .long 0x12e3a301 + .long 0x1303ab01 + .long 0x1323b301 + .long 0x1343bb01 + .long 0x1363c301 + .long 0x1383cb01 + .long 0x13a3d301 + .long 0x13c3db01 + .long 0x13e3e301 /* evldd 31,224(3) */ + .long 0x11a3eb01 /* evldd 13,232(3) */ +1: mtlr 0 +#else lfd 14,88(3) lfd 15,96(3) lfd 16,104(3) diff --git a/src/setjmp/powerpc/setjmp.S b/src/setjmp/powerpc/setjmp.S index cd91a207..413e6a81 100644 --- a/src/setjmp/powerpc/setjmp.S +++ b/src/setjmp/powerpc/setjmp.S @@ -37,7 +37,37 @@ setjmp: stw 29, 72(3) stw 30, 76(3) stw 31, 80(3) -#ifndef _SOFT_FLOAT +#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) + mflr 0 + bl 1f + .hidden __hwcap + .long __hwcap-. +1: mflr 4 + lwz 5, 0(4) + add 4, 4, 5 + andis. 4, 4, 0x80 + beq 1f + .long 0x11c35b21 /* evstdd 14,88(3) */ + .long 0x11e36321 /* ... */ + .long 0x12036b21 + .long 0x12237321 + .long 0x12437b21 + .long 0x12638321 + .long 0x12838b21 + .long 0x12a39321 + .long 0x12c39b21 + .long 0x12e3a321 + .long 0x1303ab21 + .long 0x1323b321 + .long 0x1343bb21 + .long 0x1363c321 + .long 0x1383cb21 + .long 0x13a3d321 + .long 0x13c3db21 + .long 0x13e3e321 /* evstdd 31,224(3) */ + .long 0x11a3eb21 /* evstdd 13,232(3) */ +1: mtlr 0 +#else stfd 14,88(3) stfd 15,96(3) stfd 16,104(3) From b76f37fd5625d038141b52184956fb4b7838e9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira?= Date: Tue, 9 Mar 2021 18:02:13 -0300 Subject: [PATCH 052/297] add qsort_r and make qsort a wrapper around it we make qsort a wrapper by providing a wrapper_cmp function that uses the extra argument as a function pointer. should be optimized to a tail call on most architectures, as long as it's built with -fomit-frame-pointer, so the performance impact should be minimal. to keep the git history clean, for now qsort_r is implemented in qsort.c and qsort is implemented in qsort_nr.c. qsort.c also received a few trivial cleanups, including replacing (*cmp)() calls with cmp(). qsort_nr.c contains only wrapper_cmp and qsort as a qsort_r wrapper itself. --- include/stdlib.h | 1 + src/include/stdlib.h | 1 + src/stdlib/qsort.c | 37 ++++++++++++++++++++----------------- src/stdlib/qsort_nr.c | 14 ++++++++++++++ 4 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 src/stdlib/qsort_nr.c diff --git a/include/stdlib.h b/include/stdlib.h index b54a051f..7af86e3b 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -146,6 +146,7 @@ int clearenv(void); #define WCOREDUMP(s) ((s) & 0x80) #define WIFCONTINUED(s) ((s) == 0xffff) void *reallocarray (void *, size_t, size_t); +void qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *); #endif #ifdef _GNU_SOURCE diff --git a/src/include/stdlib.h b/src/include/stdlib.h index e9da2015..812b04de 100644 --- a/src/include/stdlib.h +++ b/src/include/stdlib.h @@ -8,6 +8,7 @@ hidden void __env_rm_add(char *, char *); hidden int __mkostemps(char *, int, int); hidden int __ptsname_r(int, char *, size_t); hidden char *__randname(char *); +hidden void __qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *); hidden void *__libc_malloc(size_t); hidden void *__libc_malloc_impl(size_t); diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c index da58fd31..314ddc29 100644 --- a/src/stdlib/qsort.c +++ b/src/stdlib/qsort.c @@ -24,6 +24,7 @@ /* Smoothsort, an adaptive variant of Heapsort. Memory usage: O(1). Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */ +#define _BSD_SOURCE #include #include #include @@ -31,7 +32,7 @@ #include "atomic.h" #define ntz(x) a_ctz_l((x)) -typedef int (*cmpfun)(const void *, const void *); +typedef int (*cmpfun)(const void *, const void *, void *); static inline int pntz(size_t p[2]) { int r = ntz(p[0] - 1); @@ -88,7 +89,7 @@ static inline void shr(size_t p[2], int n) p[1] >>= n; } -static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size_t lp[]) +static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[]) { unsigned char *rt, *lf; unsigned char *ar[14 * sizeof(size_t) + 1]; @@ -99,10 +100,10 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size rt = head - width; lf = head - width - lp[pshift - 2]; - if((*cmp)(ar[0], lf) >= 0 && (*cmp)(ar[0], rt) >= 0) { + if(cmp(ar[0], lf, arg) >= 0 && cmp(ar[0], rt, arg) >= 0) { break; } - if((*cmp)(lf, rt) >= 0) { + if(cmp(lf, rt, arg) >= 0) { ar[i++] = lf; head = lf; pshift -= 1; @@ -115,7 +116,7 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size cycle(width, ar, i); } -static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], int pshift, int trusty, size_t lp[]) +static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[]) { unsigned char *stepson, *rt, *lf; @@ -130,13 +131,13 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], ar[0] = head; while(p[0] != 1 || p[1] != 0) { stepson = head - lp[pshift]; - if((*cmp)(stepson, ar[0]) <= 0) { + if(cmp(stepson, ar[0], arg) <= 0) { break; } if(!trusty && pshift > 1) { rt = head - width; lf = head - width - lp[pshift - 2]; - if((*cmp)(rt, stepson) >= 0 || (*cmp)(lf, stepson) >= 0) { + if(cmp(rt, stepson, arg) >= 0 || cmp(lf, stepson, arg) >= 0) { break; } } @@ -150,11 +151,11 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], } if(!trusty) { cycle(width, ar, i); - sift(head, width, cmp, pshift, lp); + sift(head, width, cmp, arg, pshift, lp); } } -void qsort(void *base, size_t nel, size_t width, cmpfun cmp) +void __qsort_r(void *base, size_t nel, size_t width, cmpfun cmp, void *arg) { size_t lp[12*sizeof(size_t)]; size_t i, size = width * nel; @@ -173,16 +174,16 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp) while(head < high) { if((p[0] & 3) == 3) { - sift(head, width, cmp, pshift, lp); + sift(head, width, cmp, arg, pshift, lp); shr(p, 2); pshift += 2; } else { if(lp[pshift - 1] >= high - head) { - trinkle(head, width, cmp, p, pshift, 0, lp); + trinkle(head, width, cmp, arg, p, pshift, 0, lp); } else { - sift(head, width, cmp, pshift, lp); + sift(head, width, cmp, arg, pshift, lp); } - + if(pshift == 1) { shl(p, 1); pshift = 0; @@ -191,12 +192,12 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp) pshift = 1; } } - + p[0] |= 1; head += width; } - trinkle(head, width, cmp, p, pshift, 0, lp); + trinkle(head, width, cmp, arg, p, pshift, 0, lp); while(pshift != 1 || p[0] != 1 || p[1] != 0) { if(pshift <= 1) { @@ -208,11 +209,13 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp) pshift -= 2; p[0] ^= 7; shr(p, 1); - trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp); + trinkle(head - lp[pshift] - width, width, cmp, arg, p, pshift + 1, 1, lp); shl(p, 1); p[0] |= 1; - trinkle(head - width, width, cmp, p, pshift, 1, lp); + trinkle(head - width, width, cmp, arg, p, pshift, 1, lp); } head -= width; } } + +weak_alias(__qsort_r, qsort_r); diff --git a/src/stdlib/qsort_nr.c b/src/stdlib/qsort_nr.c new file mode 100644 index 00000000..efe7ccec --- /dev/null +++ b/src/stdlib/qsort_nr.c @@ -0,0 +1,14 @@ +#define _BSD_SOURCE +#include + +typedef int (*cmpfun)(const void *, const void *); + +static int wrapper_cmp(const void *v1, const void *v2, void *cmp) +{ + return ((cmpfun)cmp)(v1, v2); +} + +void qsort(void *base, size_t nel, size_t width, cmpfun cmp) +{ + __qsort_r(base, nel, width, wrapper_cmp, cmp); +} From 3733c831f293b3bbfd0e51faec8ee71112c62c3e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 19 Oct 2021 16:07:14 -0400 Subject: [PATCH 053/297] fix struct layout mismatch in sound ioctl time32 fallback conversion the snd_pcm_mmap_control struct used with SNDRV_PCM_IOCTL_SYNC_PTR was mistakenly defined in the kernel uapi with "before u32" padding both before and after the first u32 member. our conversion between the modern struct and the legacy time32 struct was written without awareness of that mistake, and assumed the time64 version of the struct was the intended form with padding to match the layout on 64-bit archs. as a result, the struct was not converted correctly when running on old kernels, with audio glitches as the likely result. this was discovered thanks to a related bug in the kernel, whereby 32-bit userspace running on a 64-bit kernel also suffered from the types mismatching. the mistaken layout is now the ABI and can't be changed -- or at least making a new ioctl to change it would just result in a worse situation. our conversion here is changed to treat the snd_pcm_mmap_control substruct as two separate substructs at locations dependent on endianness (since the displacement depends on endianness), using the existing conversion framework. --- src/misc/ioctl.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/misc/ioctl.c b/src/misc/ioctl.c index 49282811..35804f02 100644 --- a/src/misc/ioctl.c +++ b/src/misc/ioctl.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "syscall.h" #define alignof(t) offsetof(struct { char c; t x; }, x) @@ -53,7 +54,7 @@ static const struct ioctl_compat_map compat_map[] = { { _IOWR('A', 0x23, char[136]), _IOWR('A', 0x23, char[132]), 0, WR, 1, 0 }, { 0, 0, 4, WR, 1, 0 }, /* snd_pcm_sync_ptr (flags only) */ { 0, 0, 32, WR, 1, OFFS(8,12,16,24,28) }, /* snd_pcm_mmap_status */ - { 0, 0, 8, WR, 1, OFFS(0,4) }, /* snd_pcm_mmap_control */ + { 0, 0, 4, WR, 1, 0 }, /* snd_pcm_mmap_control (each member) */ /* VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF */ { _IOWR('V', 9, new_misaligned(68)), _IOWR('V', 9, char[68]), 68, WR, 1, OFFS(20, 24) }, @@ -90,7 +91,11 @@ static void convert_ioctl_struct(const struct ioctl_compat_map *map, char *old, * if another exception appears this needs changing. */ convert_ioctl_struct(map+1, old, new, dir); convert_ioctl_struct(map+2, old+4, new+8, dir); - convert_ioctl_struct(map+3, old+68, new+72, dir); + /* snd_pcm_mmap_control, special-cased due to kernel + * type definition having been botched. */ + int adj = BYTE_ORDER==BIG_ENDIAN ? 4 : 0; + convert_ioctl_struct(map+3, old+68, new+72+adj, dir); + convert_ioctl_struct(map+3, old+72, new+76+3*adj, dir); return; } for (int i=0; i < map->noffs; i++) { From eac396daefa59473ac238741ecc50b44d4626418 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 4 Nov 2021 09:55:47 -0700 Subject: [PATCH 054/297] Update to emscripten 2.0.33 --- arch/emscripten/atomic_arch.h | 10 +- arch/emscripten/bits/alltypes.h | 17 +- arch/emscripten/bits/limits.h | 6 +- arch/emscripten/bits/stdint.h | 13 + arch/emscripten/bits/syscall.h | 345 ++++++++---------------- arch/emscripten/syscall_arch.h | 254 +++++++++-------- include/features.h | 3 - include/inttypes.h | 5 + include/pthread.h | 7 - include/setjmp.h | 3 +- include/signal.h | 2 +- include/unistd.h | 5 + ldso/dlstart.c | 7 - ldso/dynlink.c | 7 - src/conf/confstr.c | 19 ++ src/conf/sysconf.c | 87 +++--- src/env/__environ.c | 17 +- src/exit/_Exit.c | 4 + src/fcntl/fcntl.c | 19 +- src/internal/dynlink.h | 27 ++ src/internal/libc.h | 6 + src/internal/pthread_impl.h | 34 ++- src/internal/syscall.h | 31 +-- src/legacy/getpagesize.c | 6 - src/linux/gettid.c | 8 + src/locale/newlocale.c | 2 + src/network/recvmmsg.c | 2 +- src/network/recvmsg.c | 4 +- src/network/sendmsg.c | 2 +- src/stat/fstat.c | 3 +- src/stdlib/strtol.c | 84 ++++++ src/string/memchr.c | 3 +- src/string/memcmp.c | 24 ++ src/string/stpcpy.c | 4 +- src/string/stpncpy.c | 4 +- src/string/strchrnul.c | 4 +- src/string/strlen.c | 3 +- src/thread/__timedwait.c | 7 +- src/thread/__wait.c | 5 +- src/thread/pthread_barrier_wait.c | 21 +- src/thread/pthread_detach.c | 10 + src/thread/pthread_getattr_np.c | 5 + src/thread/pthread_getspecific.c | 4 + src/thread/pthread_key_create.c | 4 - src/thread/pthread_rwlock_timedwrlock.c | 8 +- src/thread/pthread_rwlock_trywrlock.c | 2 +- src/thread/pthread_rwlock_unlock.c | 2 +- src/thread/thrd_create.c | 8 +- src/thread/thrd_exit.c | 5 - src/thread/thrd_join.c | 5 - src/time/asctime.c | 4 +- src/unistd/dup2.c | 6 +- src/unistd/setxid.c | 12 +- src/unistd/usleep.c | 8 - 54 files changed, 651 insertions(+), 546 deletions(-) create mode 100644 src/linux/gettid.c diff --git a/arch/emscripten/atomic_arch.h b/arch/emscripten/atomic_arch.h index 093edcd0..937fd43f 100644 --- a/arch/emscripten/atomic_arch.h +++ b/arch/emscripten/atomic_arch.h @@ -2,8 +2,6 @@ #define _INTERNAL_ATOMIC_H #include -#include -#include #define a_clz_l __builtin_clz #define a_ctz_l __builtin_ctz @@ -36,9 +34,9 @@ static inline void a_or_l(volatile void *p, long v) #define a_cas_p a_cas_p static inline void *a_cas_p(volatile void *p, void *t, void *s) { - void* expected = t; - __c11_atomic_compare_exchange_strong((_Atomic uintptr_t*)p, &expected, s, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); - return expected; + uintptr_t expected = (uintptr_t)t; + __c11_atomic_compare_exchange_strong((_Atomic uintptr_t*)p, &expected, (uintptr_t)s, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return (void*)expected; } #define a_cas_l a_cas_l @@ -107,7 +105,7 @@ static inline void a_spin() #define a_crash a_crash static inline void a_crash() { - EM_ASM( abort() ); + __builtin_trap(); } #endif diff --git a/arch/emscripten/bits/alltypes.h b/arch/emscripten/bits/alltypes.h index c3768afe..64ebb875 100644 --- a/arch/emscripten/bits/alltypes.h +++ b/arch/emscripten/bits/alltypes.h @@ -83,13 +83,18 @@ typedef long suseconds_t; #if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t) +typedef struct { + union { + int __i[10]; + volatile int __vi[10]; + unsigned __s[10]; + } __u; #ifdef __EMSCRIPTEN__ -// For canvas transfer implementation in Emscripten, use an extra 11th control field -// to pass a pointer to a string denoting the WebGL canvases to transfer. -typedef struct { union { int __i[11]; volatile int __vi[11]; unsigned __s[11]; } __u; } pthread_attr_t; -#else -typedef struct { union { int __i[10]; volatile int __vi[10]; unsigned __s[10]; } __u; } pthread_attr_t; + // For canvas transfer implementation in Emscripten, use an extra control field + // to pass a pointer to a string denoting the WebGL canvases to transfer. + const char *_a_transferredcanvases; #endif +} pthread_attr_t; #define __DEFINED_pthread_attr_t #endif @@ -114,7 +119,7 @@ typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __ #endif #if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t) -typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t; +typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t; #define __DEFINED_pthread_rwlock_t #endif diff --git a/arch/emscripten/bits/limits.h b/arch/emscripten/bits/limits.h index 3fd93311..338b2f2e 100644 --- a/arch/emscripten/bits/limits.h +++ b/arch/emscripten/bits/limits.h @@ -1,8 +1,12 @@ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define PAGE_SIZE 16384 +#define PAGE_SIZE 65536 #define LONG_BIT 32 #endif +#if __LP64__ +#define LONG_MAX 0x7fffffffffffffffL +#else #define LONG_MAX 0x7fffffffL +#endif #define LLONG_MAX 0x7fffffffffffffffLL diff --git a/arch/emscripten/bits/stdint.h b/arch/emscripten/bits/stdint.h index d1b27121..2621b613 100644 --- a/arch/emscripten/bits/stdint.h +++ b/arch/emscripten/bits/stdint.h @@ -12,9 +12,22 @@ typedef uint32_t uint_fast32_t; #define UINT_FAST16_MAX UINT32_MAX #define UINT_FAST32_MAX UINT32_MAX +#if __LP64__ + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX +#define SIZE_MAX UINT64_MAX + +#else + #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 + +#endif diff --git a/arch/emscripten/bits/syscall.h b/arch/emscripten/bits/syscall.h index dddf57e4..db2ae6b5 100644 --- a/arch/emscripten/bits/syscall.h +++ b/arch/emscripten/bits/syscall.h @@ -1,226 +1,119 @@ -/* - * The .h version of this file is generated from the .h.in. - * See update_syscall.sh. - */ -#define __NR_exit 1 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_chdir 12 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_getpid 20 -#define __NR_pause 29 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_sync 36 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_acct 51 -#define __NR_ioctl 54 -#define __NR_setpgid 57 -#define __NR_umask 60 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_setrlimit 75 -#define __NR_getrusage 77 -#define __NR_symlink 83 -#define __NR_readlink 85 -#define __NR_munmap 91 -#define __NR_fchmod 94 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_socketcall 102 -#define __NR_setitimer 104 -#define __NR_wait4 114 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_mprotect 125 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR__newselect 142 -#define __NR_msync 144 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_mremap 163 -#define __NR_poll 168 -#define __NR_rt_sigqueueinfo 178 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_getcwd 183 -#define __NR_ugetrlimit 191 -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_lchown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_chown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_mincore 218 -#define __NR_madvise 219 -#define __NR_madvise1 219 -#define __NR_getdents64 220 -#define __NR_fcntl64 221 -#define __NR_exit_group 252 -#define __NR_statfs64 268 -#define __NR_fstatfs64 269 -#define __NR_fadvise64_64 272 -#define __NR_openat 295 -#define __NR_mkdirat 296 -#define __NR_mknodat 297 -#define __NR_fchownat 298 -#define __NR_fstatat64 300 -#define __NR_unlinkat 301 -#define __NR_renameat 302 -#define __NR_linkat 303 -#define __NR_symlinkat 304 -#define __NR_readlinkat 305 -#define __NR_fchmodat 306 -#define __NR_faccessat 307 -#define __NR_pselect6 308 -#define __NR_utimensat 320 -#define __NR_fallocate 324 -#define __NR_dup3 330 -#define __NR_pipe2 331 -#define __NR_preadv 333 -#define __NR_pwritev 334 -#define __NR_recvmmsg 337 -#define __NR_prlimit64 340 -#define __NR_sendmmsg 345 -#define SYS_exit 1 -#define SYS_read 3 -#define SYS_write 4 -#define SYS_open 5 -#define SYS_link 9 -#define SYS_unlink 10 -#define SYS_chdir 12 -#define SYS_mknod 14 -#define SYS_chmod 15 -#define SYS_getpid 20 -#define SYS_pause 29 -#define SYS_access 33 -#define SYS_nice 34 -#define SYS_sync 36 -#define SYS_rename 38 -#define SYS_mkdir 39 -#define SYS_rmdir 40 -#define SYS_dup 41 -#define SYS_pipe 42 -#define SYS_acct 51 -#define SYS_ioctl 54 -#define SYS_setpgid 57 -#define SYS_umask 60 -#define SYS_dup2 63 -#define SYS_getppid 64 -#define SYS_getpgrp 65 -#define SYS_setsid 66 -#define SYS_setrlimit 75 -#define SYS_getrusage 77 -#define SYS_symlink 83 -#define SYS_readlink 85 -#define SYS_munmap 91 -#define SYS_fchmod 94 -#define SYS_getpriority 96 -#define SYS_setpriority 97 -#define SYS_socketcall 102 -#define SYS_setitimer 104 -#define SYS_wait4 114 -#define SYS_setdomainname 121 -#define SYS_uname 122 -#define SYS_mprotect 125 -#define SYS_getpgid 132 -#define SYS_fchdir 133 -#define SYS__newselect 142 -#define SYS_msync 144 -#define SYS_getsid 147 -#define SYS_fdatasync 148 -#define SYS_mlock 150 -#define SYS_munlock 151 -#define SYS_mlockall 152 -#define SYS_munlockall 153 -#define SYS_mremap 163 -#define SYS_poll 168 -#define SYS_rt_sigqueueinfo 178 -#define SYS_pread64 180 -#define SYS_pwrite64 181 -#define SYS_getcwd 183 -#define SYS_ugetrlimit 191 -#define SYS_mmap2 192 -#define SYS_truncate64 193 -#define SYS_ftruncate64 194 -#define SYS_stat64 195 -#define SYS_lstat64 196 -#define SYS_fstat64 197 -#define SYS_lchown32 198 -#define SYS_getuid32 199 -#define SYS_getgid32 200 -#define SYS_geteuid32 201 -#define SYS_getegid32 202 -#define SYS_setreuid32 203 -#define SYS_setregid32 204 -#define SYS_getgroups32 205 -#define SYS_fchown32 207 -#define SYS_setresuid32 208 -#define SYS_getresuid32 209 -#define SYS_setresgid32 210 -#define SYS_getresgid32 211 -#define SYS_chown32 212 -#define SYS_setuid32 213 -#define SYS_setgid32 214 -#define SYS_mincore 218 -#define SYS_madvise 219 -#define SYS_madvise1 219 -#define SYS_getdents64 220 -#define SYS_fcntl64 221 -#define SYS_exit_group 252 -#define SYS_statfs64 268 -#define SYS_fstatfs64 269 -#define SYS_fadvise64_64 272 -#define SYS_openat 295 -#define SYS_mkdirat 296 -#define SYS_mknodat 297 -#define SYS_fchownat 298 -#define SYS_fstatat64 300 -#define SYS_unlinkat 301 -#define SYS_renameat 302 -#define SYS_linkat 303 -#define SYS_symlinkat 304 -#define SYS_readlinkat 305 -#define SYS_fchmodat 306 -#define SYS_faccessat 307 -#define SYS_pselect6 308 -#define SYS_utimensat 320 -#define SYS_fallocate 324 -#define SYS_dup3 330 -#define SYS_pipe2 331 -#define SYS_preadv 333 -#define SYS_pwritev 334 -#define SYS_recvmmsg 337 -#define SYS_prlimit64 340 -#define SYS_sendmmsg 345 +#define SYS_exit __syscall_exit +#define SYS_read __syscall_read +#define SYS_write __syscall_write +#define SYS_open __syscall_open +#define SYS_link __syscall_link +#define SYS_unlink __syscall_unlink +#define SYS_chdir __syscall_chdir +#define SYS_mknod __syscall_mknod +#define SYS_chmod __syscall_chmod +#define SYS_getpid __syscall_getpid +#define SYS_pause __syscall_pause +#define SYS_access __syscall_access +#define SYS_nice __syscall_nice +#define SYS_sync __syscall_sync +#define SYS_rename __syscall_rename +#define SYS_mkdir __syscall_mkdir +#define SYS_rmdir __syscall_rmdir +#define SYS_dup __syscall_dup +#define SYS_pipe __syscall_pipe +#define SYS_acct __syscall_acct +#define SYS_ioctl __syscall_ioctl +#define SYS_setpgid __syscall_setpgid +#define SYS_umask __syscall_umask +#define SYS_dup2 __syscall_dup2 +#define SYS_getppid __syscall_getppid +#define SYS_setsid __syscall_setsid +#define SYS_setrlimit __syscall_setrlimit +#define SYS_getrusage __syscall_getrusage +#define SYS_symlink __syscall_symlink +#define SYS_readlink __syscall_readlink +#define SYS_munmap __syscall_munmap +#define SYS_fchmod __syscall_fchmod +#define SYS_getpriority __syscall_getpriority +#define SYS_setpriority __syscall_setpriority +#define SYS_setitimer __syscall_setitimer +#define SYS_getitimer __syscall_getitimer +#define SYS_wait4 __syscall_wait4 +#define SYS_setdomainname __syscall_setdomainname +#define SYS_uname __syscall_uname +#define SYS_mprotect __syscall_mprotect +#define SYS_getpgid __syscall_getpgid +#define SYS_fchdir __syscall_fchdir +#define SYS__newselect __syscall__newselect +#define SYS_msync __syscall_msync +#define SYS_getsid __syscall_getsid +#define SYS_fdatasync __syscall_fdatasync +#define SYS_mlock __syscall_mlock +#define SYS_munlock __syscall_munlock +#define SYS_mlockall __syscall_mlockall +#define SYS_munlockall __syscall_munlockall +#define SYS_mremap __syscall_mremap +#define SYS_poll __syscall_poll +#define SYS_rt_sigqueueinfo __syscall_rt_sigqueueinfo +#define SYS_pread64 __syscall_pread64 +#define SYS_pwrite64 __syscall_pwrite64 +#define SYS_getcwd __syscall_getcwd +#define SYS_ugetrlimit __syscall_ugetrlimit +#define SYS_mmap2 __syscall_mmap2 +#define SYS_truncate64 __syscall_truncate64 +#define SYS_ftruncate64 __syscall_ftruncate64 +#define SYS_stat64 __syscall_stat64 +#define SYS_lstat64 __syscall_lstat64 +#define SYS_fstat64 __syscall_fstat64 +#define SYS_lchown32 __syscall_lchown32 +#define SYS_getuid32 __syscall_getuid32 +#define SYS_getgid32 __syscall_getgid32 +#define SYS_geteuid32 __syscall_geteuid32 +#define SYS_getegid32 __syscall_getegid32 +#define SYS_getgroups32 __syscall_getgroups32 +#define SYS_fchown32 __syscall_fchown32 +#define SYS_getresuid32 __syscall_getresuid32 +#define SYS_getresgid32 __syscall_getresgid32 +#define SYS_chown32 __syscall_chown32 +#define SYS_mincore __syscall_mincore +#define SYS_madvise __syscall_madvise +#define SYS_madvise1 __syscall_madvise1 +#define SYS_getdents64 __syscall_getdents64 +#define SYS_fcntl64 __syscall_fcntl64 +#define SYS_exit_group __syscall_exit_group +#define SYS_statfs64 __syscall_statfs64 +#define SYS_fstatfs64 __syscall_fstatfs64 +#define SYS_fadvise64_64 __syscall_fadvise64_64 +#define SYS_openat __syscall_openat +#define SYS_mkdirat __syscall_mkdirat +#define SYS_mknodat __syscall_mknodat +#define SYS_fchownat __syscall_fchownat +#define SYS_fstatat64 __syscall_fstatat64 +#define SYS_unlinkat __syscall_unlinkat +#define SYS_renameat __syscall_renameat +#define SYS_linkat __syscall_linkat +#define SYS_symlinkat __syscall_symlinkat +#define SYS_readlinkat __syscall_readlinkat +#define SYS_fchmodat __syscall_fchmodat +#define SYS_faccessat __syscall_faccessat +#define SYS_pselect6 __syscall_pselect6 +#define SYS_utimensat __syscall_utimensat +#define SYS_fallocate __syscall_fallocate +#define SYS_dup3 __syscall_dup3 +#define SYS_pipe2 __syscall_pipe2 +#define SYS_preadv __syscall_preadv +#define SYS_pwritev __syscall_pwritev +#define SYS_recvmmsg __syscall_recvmmsg +#define SYS_prlimit64 __syscall_prlimit64 +#define SYS_sendmmsg __syscall_sendmmsg +#define SYS_socket __syscall_socket +#define SYS_socketpair __syscall_socketpair +#define SYS_bind __syscall_bind +#define SYS_connect __syscall_connect +#define SYS_listen __syscall_listen +#define SYS_accept4 __syscall_accept4 +#define SYS_getsockopt __syscall_getsockopt +#define SYS_setsockopt __syscall_setsockopt +#define SYS_getsockname __syscall_getsockname +#define SYS_getpeername __syscall_getpeername +#define SYS_sendto __syscall_sendto +#define SYS_sendmsg __syscall_sendmsg +#define SYS_recvfrom __syscall_recvfrom +#define SYS_recvmsg __syscall_recvmsg +#define SYS_shutdown __syscall_shutdown diff --git a/arch/emscripten/syscall_arch.h b/arch/emscripten/syscall_arch.h index 7ff67eca..69a77e9f 100644 --- a/arch/emscripten/syscall_arch.h +++ b/arch/emscripten/syscall_arch.h @@ -1,148 +1,134 @@ #include #include -#include +#include #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) 0, __SYSCALL_LL_E((x)) - -#define __SC_socket 1 -#define __SC_bind 2 -#define __SC_connect 3 -#define __SC_listen 4 -#define __SC_accept 5 -#define __SC_getsockname 6 -#define __SC_getpeername 7 -#define __SC_socketpair 8 -#define __SC_send 9 -#define __SC_recv 10 -#define __SC_sendto 11 -#define __SC_recvfrom 12 -#define __SC_shutdown 13 -#define __SC_setsockopt 14 -#define __SC_getsockopt 15 -#define __SC_sendmsg 16 -#define __SC_recvmsg 17 -#define __SC_accept4 18 -#define __SC_recvmmsg 19 -#define __SC_sendmmsg 20 +#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) #ifdef __cplusplus extern "C" { #endif -/* Causes the final import in the wasm binary be named "env.sys_" */ -#define SYS_IMPORT(NAME) EM_IMPORT(__sys_##NAME) - -long SYS_IMPORT(exit) __syscall1(long exit_code); -long SYS_IMPORT(open) __syscall5(long path, long flags, ...); // mode is optional -long SYS_IMPORT(link) __syscall9(long oldpath, long newpath); -long SYS_IMPORT(unlink) __syscall10(long path); -long SYS_IMPORT(chdir) __syscall12(long path); -long SYS_IMPORT(mknod) __syscall14(long path, long mode, long dev); -long SYS_IMPORT(chmod) __syscall15(long path, long mode); -long SYS_IMPORT(getpid) __syscall20(void); -long SYS_IMPORT(pause) __syscall29(void); -long SYS_IMPORT(access) __syscall33(long path, long amode); -long SYS_IMPORT(nice) __syscall34(long inc); -long SYS_IMPORT(sync) __syscall36(void); -long SYS_IMPORT(rename) __syscall38(long old_path, long new_path); -long SYS_IMPORT(mkdir) __syscall39(long path, long mode); -long SYS_IMPORT(rmdir) __syscall40(long path); -long SYS_IMPORT(dup) __syscall41(long fd); -long SYS_IMPORT(pipe) __syscall42(long fd); -long SYS_IMPORT(acct) __syscall51(long filename); -long SYS_IMPORT(ioctl) __syscall54(long fd, long request, ...); -long SYS_IMPORT(setpgid) __syscall57(long pid, long gpid); -long SYS_IMPORT(umask) __syscall60(long mask); -long SYS_IMPORT(dup2) __syscall63(long oldfd, long newfd); -long SYS_IMPORT(getppid) __syscall64(void); -long SYS_IMPORT(getpgrp) __syscall65(void); -long SYS_IMPORT(setsid) __syscall66(void); -long SYS_IMPORT(setrlimit) __syscall75(long resource, long limit); -long SYS_IMPORT(getrusage) __syscall77(long who, long usage); -long SYS_IMPORT(symlink) __syscall83(long target, long linkpath); -long SYS_IMPORT(readlink) __syscall85(long path, long buf, long bufsize); -long SYS_IMPORT(munmap) __syscall91(long addr, long len); -long SYS_IMPORT(fchmod) __syscall94(long fd, long mode); -long SYS_IMPORT(getpriority) __syscall96(long which, long who); -long SYS_IMPORT(setpriority) __syscall97(long which, long who, long prio); -long SYS_IMPORT(socketcall) __syscall102(long call, long args); -long SYS_IMPORT(setitimer) __syscall104(long which, long new_value, long old_value); -long SYS_IMPORT(wait4) __syscall114(long pid, long wstatus, long options, long rusage); -long SYS_IMPORT(setdomainname) __syscall121(long name, long size); -long SYS_IMPORT(uname) __syscall122(long buf); -long SYS_IMPORT(mprotect) __syscall125(long addr, long len, long size); -long SYS_IMPORT(getpgid) __syscall132(long pid); -long SYS_IMPORT(fchdir) __syscall133(long fd); -long SYS_IMPORT(_newselect) - __syscall142(long nfds, long readfds, long writefds, long exceptfds, long timeout); -long SYS_IMPORT(msync) __syscall144(long addr, long len, long flags); -long SYS_IMPORT(getsid) __syscall147(long pid); -long SYS_IMPORT(fdatasync) __syscall148(long fd); -long SYS_IMPORT(mlock) __syscall150(long addr, long len); -long SYS_IMPORT(munlock) __syscall151(long addr, long len); -long SYS_IMPORT(mlockall) __syscall152(long flags); -long SYS_IMPORT(munlockall) __syscall153(void); -long SYS_IMPORT(mremap) - __syscall163(long old_addr, long old_size, long new_size, long flags, long new_addr); -long SYS_IMPORT(poll) __syscall168(long fds, long nfds, long timeout); -long SYS_IMPORT(rt_sigqueueinfo) __syscall178(long tgid, long sig, long uinfo); -long SYS_IMPORT(getcwd) __syscall183(long buf, long size); -long SYS_IMPORT(ugetrlimit) __syscall191(long resource, long rlim); -long SYS_IMPORT(mmap2) __syscall192(long addr, long len, long prot, long flags, long fd, long off); -long SYS_IMPORT(truncate64) __syscall193(long path, long zero, long low, long high); -long SYS_IMPORT(ftruncate64) __syscall194(long fd, long zero, long low, long high); -long SYS_IMPORT(stat64) __syscall195(long path, long buf); -long SYS_IMPORT(lstat64) __syscall196(long path, long buf); -long SYS_IMPORT(fstat64) __syscall197(long fd, long buf); -long SYS_IMPORT(lchown32) __syscall198(long path, long owner, long group); -long SYS_IMPORT(getuid32) __syscall199(void); -long SYS_IMPORT(getgid32) __syscall200(void); -long SYS_IMPORT(geteuid32) __syscall201(void); -long SYS_IMPORT(getegid32) __syscall202(void); -long SYS_IMPORT(setreuid32) __syscall203(long ruid, long euid); -long SYS_IMPORT(setregid32) __syscall204(long rgid, long egid); -long SYS_IMPORT(getgroups32) __syscall205(long size, long list); -long SYS_IMPORT(fchown32) __syscall207(long fd, long owner, long group); -long SYS_IMPORT(setresuid32) __syscall208(long ruid, long euid, long suid); -long SYS_IMPORT(getresuid32) __syscall209(long ruid, long euid, long suid); -long SYS_IMPORT(setresgid32) __syscall210(long rgid, long egid, long sgid); -long SYS_IMPORT(getresgid32) __syscall211(long rgid, long egid, long sgid); -long SYS_IMPORT(chown32) __syscall212(long path, long owner, long group); -long SYS_IMPORT(setuid32) __syscall213(long uid); -long SYS_IMPORT(setgid32) __syscall214(long uid); -long SYS_IMPORT(mincore) __syscall218(long addr, long length, long vec); -long SYS_IMPORT(madvise1) __syscall219(long addr, long length, long advice); -long SYS_IMPORT(getdents64) __syscall220(long fd, long dirp, long count); -long SYS_IMPORT(fcntl64) __syscall221(long fd, long cmd, ...); -long SYS_IMPORT(exit_group) __syscall252(long status); -long SYS_IMPORT(statfs64) __syscall268(long path, long size, long buf); -long SYS_IMPORT(fstatfs64) __syscall269(long fd, long size, long buf); -long SYS_IMPORT(fadvise64_64) - __syscall272(long fd, long zero, long low, long high, long low2, long high2, long advice); -long SYS_IMPORT(openat) __syscall295(long dirfd, long path, long flags, ...); -long SYS_IMPORT(mkdirat) __syscall296(long dirfd, long path, long mode); -long SYS_IMPORT(mknodat) __syscall297(long dirfd, long path, long mode, long dev); -long SYS_IMPORT(fchownat) __syscall298(long dirfd, long path, long owner, long group, long flags); -long SYS_IMPORT(fstatat64) __syscall300(long dirfd, long path, long buf, long flags); -long SYS_IMPORT(unlinkat) __syscall301(long dirfd, long path, long flags); -long SYS_IMPORT(renameat) __syscall302(long olddirfd, long oldpath, long newdirfd, long newpath); -long SYS_IMPORT(linkat) - __syscall303(long olddirfd, long oldpath, long newdirfd, long newpath, long flags); -long SYS_IMPORT(symlinkat) __syscall304(long target, long newdirfd, long linkpath); -long SYS_IMPORT(readlinkat) __syscall305(long dirfd, long path, long bug, long bufsize); -long SYS_IMPORT(fchmodat) __syscall306(long dirfd, long path, long mode, ...); -long SYS_IMPORT(faccessat) __syscall307(long dirfd, long path, long amode, long flags); -long SYS_IMPORT(pselect6) __syscall308(long nfds, long readfds, long writefds, long exceptfds, long timeout, long sigmaks); -long SYS_IMPORT(utimensat) __syscall320(long dirfd, long path, long times, long flags); -long SYS_IMPORT(fallocate) __syscall324(long fd, long mode, long off_low, long off_high, long len_low, long len_high); -long SYS_IMPORT(dup3) __syscall330(long fd, long suggestfd, long flags); -long SYS_IMPORT(pipe2) __syscall331(long fds, long flags); -long SYS_IMPORT(recvmmsg) __syscall337(long sockfd, long msgvec, long vlen, long flags, ...); -long SYS_IMPORT(prlimit64) __syscall340(long pid, long resource, long new_limit, long old_limit); -long SYS_IMPORT(sendmmsg) __syscall345(long sockfd, long msgvec, long vlen, long flags, ...); +long __syscall_open(long path, long flags, ...); // mode is optional +long __syscall_link(long oldpath, long newpath); +long __syscall_unlink(long path); +long __syscall_chdir(long path); +long __syscall_mknod(long path, long mode, long dev); +long __syscall_chmod(long path, long mode); +long __syscall_getpid(void); +long __syscall_pause(void); +long __syscall_access(long path, long amode); +long __syscall_nice(long inc); +long __syscall_sync(void); +long __syscall_rename(long old_path, long new_path); +long __syscall_mkdir(long path, long mode); +long __syscall_rmdir(long path); +long __syscall_dup(long fd); +long __syscall_pipe(long fd); +long __syscall_acct(long filename); +long __syscall_ioctl(long fd, long request, ...); +long __syscall_setpgid(long pid, long gpid); +long __syscall_umask(long mask); +long __syscall_dup2(long oldfd, long newfd); +long __syscall_getppid(void); +long __syscall_getpgrp(void); +long __syscall_setsid(void); +long __syscall_setrlimit(long resource, long limit); +long __syscall_getrusage(long who, long usage); +long __syscall_symlink(long target, long linkpath); +long __syscall_readlink(long path, long buf, long bufsize); +long __syscall_munmap(long addr, long len); +long __syscall_fchmod(long fd, long mode); +long __syscall_getpriority(long which, long who); +long __syscall_setpriority(long which, long who, long prio); +long __syscall_socketcall(long call, long args); +long __syscall_setitimer(long which, long new_value, long old_value); +long __syscall_getitimer(long which, long old_value); +long __syscall_wait4(long pid, long wstatus, long options, long rusage); +long __syscall_setdomainname(long name, long size); +long __syscall_uname(long buf); +long __syscall_mprotect(long addr, long len, long size); +long __syscall_getpgid(long pid); +long __syscall_fchdir(long fd); +long __syscall__newselect(long nfds, long readfds, long writefds, long exceptfds, long timeout); +long __syscall_msync(long addr, long len, long flags); +long __syscall_getsid(long pid); +long __syscall_fdatasync(long fd); +long __syscall_mlock(long addr, long len); +long __syscall_munlock(long addr, long len); +long __syscall_mlockall(long flags); +long __syscall_munlockall(void); +long __syscall_mremap(long old_addr, long old_size, long new_size, long flags, long new_addr); +long __syscall_poll(long fds, long nfds, long timeout); +long __syscall_rt_sigqueueinfo(long tgid, long sig, long uinfo); +long __syscall_getcwd(long buf, long size); +long __syscall_ugetrlimit(long resource, long rlim); +long __syscall_mmap2(long addr, long len, long prot, long flags, long fd, long off); +long __syscall_truncate64(long path, long low, long high); +long __syscall_ftruncate64(long fd, long low, long high); +long __syscall_stat64(long path, long buf); +long __syscall_lstat64(long path, long buf); +long __syscall_fstat64(long fd, long buf); +long __syscall_lchown32(long path, long owner, long group); +long __syscall_getuid32(void); +long __syscall_getgid32(void); +long __syscall_geteuid32(void); +long __syscall_getegid32(void); +long __syscall_setreuid32(long ruid, long euid); +long __syscall_setregid32(long rgid, long egid); +long __syscall_getgroups32(long size, long list); +long __syscall_fchown32(long fd, long owner, long group); +long __syscall_setresuid32(long ruid, long euid, long suid); +long __syscall_getresuid32(long ruid, long euid, long suid); +long __syscall_setresgid32(long rgid, long egid, long sgid); +long __syscall_getresgid32(long rgid, long egid, long sgid); +long __syscall_chown32(long path, long owner, long group); +long __syscall_setuid32(long uid); +long __syscall_setgid32(long uid); +long __syscall_mincore(long addr, long length, long vec); +long __syscall_madvise(long addr, long length, long advice); +long __syscall_getdents64(long fd, long dirp, long count); +long __syscall_fcntl64(long fd, long cmd, ...); +long __syscall_statfs64(long path, long size, long buf); +long __syscall_fstatfs64(long fd, long size, long buf); +long __syscall_fadvise64_64(long fd, long low, long high, long low2, long high2, long advice); +long __syscall_openat(long dirfd, long path, long flags, ...); +long __syscall_mkdirat(long dirfd, long path, long mode); +long __syscall_mknodat(long dirfd, long path, long mode, long dev); +long __syscall_fchownat(long dirfd, long path, long owner, long group, long flags); +long __syscall_fstatat64(long dirfd, long path, long buf, long flags); +long __syscall_unlinkat(long dirfd, long path, long flags); +long __syscall_renameat(long olddirfd, long oldpath, long newdirfd, long newpath); +long __syscall_linkat(long olddirfd, long oldpath, long newdirfd, long newpath, long flags); +long __syscall_symlinkat(long target, long newdirfd, long linkpath); +long __syscall_readlinkat(long dirfd, long path, long bug, long bufsize); +long __syscall_fchmodat(long dirfd, long path, long mode, ...); +long __syscall_faccessat(long dirfd, long path, long amode, long flags); +long __syscall_pselect6(long nfds, long readfds, long writefds, long exceptfds, long timeout, long sigmaks); +long __syscall_utimensat(long dirfd, long path, long times, long flags); +long __syscall_fallocate(long fd, long mode, long off_low, long off_high, long len_low, long len_high); +long __syscall_dup3(long fd, long suggestfd, long flags); +long __syscall_pipe2(long fds, long flags); +long __syscall_recvmmsg(long sockfd, long msgvec, long vlen, long flags, ...); +long __syscall_prlimit64(long pid, long resource, long new_limit, long old_limit); +long __syscall_sendmmsg(long sockfd, long msgvec, long vlen, long flags, ...); +long __syscall_socket(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_socketpair(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_bind(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_connect(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_listen(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_accept4(long sockfd, long addr, long addrlen, long flags, long dummy1, long dummy2); +long __syscall_getsockopt(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_setsockopt(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_getsockname(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_getpeername(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_sendto(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_sendmsg(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_recvfrom(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_recvmsg(long sockfd, long level, long optname, long optval, long optlen, long dummy); +long __syscall_shutdown(long sockfd, long level, long optname, long optval, long optlen, long dummy); #ifdef __cplusplus } diff --git a/include/features.h b/include/features.h index 48c4aa6c..3cc3e579 100644 --- a/include/features.h +++ b/include/features.h @@ -33,7 +33,4 @@ #define _Noreturn #endif -#define weak_alias(old, new) \ - extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) - #endif diff --git a/include/inttypes.h b/include/inttypes.h index 61dcb727..51f4a52a 100644 --- a/include/inttypes.h +++ b/include/inttypes.h @@ -25,6 +25,11 @@ uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); #if UINTPTR_MAX == UINT64_MAX #define __PRI64 "l" #define __PRIPTR "l" +#elif defined(__EMSCRIPTEN__) +// Under emscripten __PTRDIFF_TYPE__ and therefor intptr_t are defined to +// be `long int` even on wasm2. +#define __PRI64 "ll" +#define __PRIPTR "l" #else #define __PRI64 "ll" #define __PRIPTR "" diff --git a/include/pthread.h b/include/pthread.h index 378ae292..3d2e0c45 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -203,18 +203,11 @@ struct __ptcb { struct __ptcb *__next; }; -#ifdef __EMSCRIPTEN__ -// For Emscripten, the cleanup stack is not implemented as a macro, since it's currently in the JS side. -typedef void (*cleanup_handler_routine)(void *arg); -void pthread_cleanup_push(cleanup_handler_routine routine, void *arg); -void pthread_cleanup_pop(int execute); -#else void _pthread_cleanup_push(struct __ptcb *, void (*)(void *), void *); void _pthread_cleanup_pop(struct __ptcb *, int); #define pthread_cleanup_push(f, x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x); #define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0) -#endif #ifdef _GNU_SOURCE struct cpu_set_t; diff --git a/include/setjmp.h b/include/setjmp.h index fac697fc..a9d3d85c 100644 --- a/include/setjmp.h +++ b/include/setjmp.h @@ -22,10 +22,11 @@ typedef jmp_buf sigjmp_buf; /* XXX EMSCRIPTEN: No signals support, alias sigsetjmp and siglongjmp to their non-signals counterparts. */ #if __EMSCRIPTEN__ #define sigsetjmp(buf, x) setjmp((buf)) +#define siglongjmp(buf, val) longjmp(buf, val) #else int sigsetjmp (sigjmp_buf, int); +_Noreturn int siglongjmp (sigjmp_buf, int); #endif -_Noreturn void siglongjmp (sigjmp_buf, int); #endif #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ diff --git a/include/signal.h b/include/signal.h index a16094c5..e206f7b2 100644 --- a/include/signal.h +++ b/include/signal.h @@ -259,7 +259,7 @@ int sigandset(sigset_t *, const sigset_t *, const sigset_t *); #define SIG_ERR ((void (*)(int))-1) #define SIG_DFL ((void (*)(int)) 0) -#define SIG_IGN ((void (*)(int)) 1) +#define SIG_IGN ((void (*)(int))-2) /* XXX EMSCRIPTEN: use -2 since 1 is a valid function address */ typedef int sig_atomic_t; diff --git a/include/unistd.h b/include/unistd.h index 29a644fa..23989653 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -198,6 +198,7 @@ char *get_current_dir_name(void); int syncfs(int); int euidaccess(const char *, int); int eaccess(const char *, int); +pid_t gettid(void); #endif #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) @@ -256,7 +257,11 @@ int eaccess(const char *, int); #define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION #define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION #define _POSIX_THREAD_PRIORITY_SCHEDULING _POSIX_VERSION +#ifdef __EMSCRIPTEN__ +#define _POSIX_THREAD_CPUTIME -1 +#else #define _POSIX_THREAD_CPUTIME _POSIX_VERSION +#endif #define _POSIX_TIMERS _POSIX_VERSION #define _POSIX_TIMEOUTS _POSIX_VERSION #define _POSIX_MONOTONIC_CLOCK _POSIX_VERSION diff --git a/ldso/dlstart.c b/ldso/dlstart.c index 200ab8ff..4dbe1784 100644 --- a/ldso/dlstart.c +++ b/ldso/dlstart.c @@ -1,10 +1,3 @@ -/* - * Copyright 2017 The Emscripten Authors. All rights reserved. - * Emscripten is available under two separate licenses, the MIT license and the - * University of Illinois/NCSA Open Source License. Both these licenses can be - * found in the LICENSE file. - */ - #include #include "dynlink.h" diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 77ec2616..e458f386 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1,10 +1,3 @@ -/* - * Copyright 2017 The Emscripten Authors. All rights reserved. - * Emscripten is available under two separate licenses, the MIT license and the - * University of Illinois/NCSA Open Source License. Both these licenses can be - * found in the LICENSE file. - */ - #define _GNU_SOURCE #include #include diff --git a/src/conf/confstr.c b/src/conf/confstr.c index 6e9c23a0..0cbd9d2b 100644 --- a/src/conf/confstr.c +++ b/src/conf/confstr.c @@ -6,7 +6,26 @@ size_t confstr(int name, char *buf, size_t len) { const char *s = ""; if (!name) { +#ifndef __EMSCRIPTEN__ s = "/bin:/usr/bin"; +#else + // TODO(sbc): Can we just remove these custom values. + // We have tests that check for them but its not clear + // anything else does. + s = "/"; + } else if (name == _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS) { + s = "POSIX_V6_ILP32_OFF32\nPOSIX_V6_ILP32_OFFBIG"; + } else if (name == _CS_GNU_LIBPTHREAD_VERSION) { + s = ""; + } else if (name == _CS_GNU_LIBC_VERSION) { + s = "glibc 2.14"; + } else if (name == _CS_POSIX_V6_ILP32_OFF32_CFLAGS || + name == _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS || + name == _CS_POSIX_V6_ILP32_OFF32_LDFLAGS) { + s = "-m32"; + } else if (name == _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS) { + s = "-m32 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"; +#endif } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>31U) { errno = EINVAL; return 0; diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index c17d1fce..f9dc80b8 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -7,6 +7,11 @@ #include "syscall.h" #include "libc.h" +#ifdef __EMSCRIPTEN__ +#include "emscripten/heap.h" +#include "emscripten/threading.h" +#endif + #define JT(x) (-256|(x)) #define VER JT(1) #define JT_ARG_MAX JT(2) @@ -23,22 +28,22 @@ long sysconf(int name) { - static const int values[] = { // XXX EMSCRIPTEN int instead of short - [_SC_ARG_MAX] = 2097152, // XXX EMSCRIPTEN replace JT_ARG_MAX, - [_SC_CHILD_MAX] = 47839, // XXX EMSCRIPTEN replace RLIM(NPROC), + static const short values[] = { + [_SC_ARG_MAX] = JT_ARG_MAX, + [_SC_CHILD_MAX] = 1024, // XXX EMSCRIPTEN replace RLIM(NPROC), [_SC_CLK_TCK] = 100, - [_SC_NGROUPS_MAX] = 65536, // XXX EMSCRIPTEN replace 32, + [_SC_NGROUPS_MAX] = 32, [_SC_OPEN_MAX] = 1024, // XXX EMSCRIPTEN replace RLIM(NOFILE), - [_SC_STREAM_MAX] = 16, // XXX EMSCRIPTEN replace -1 + [_SC_STREAM_MAX] = -1, [_SC_TZNAME_MAX] = TZNAME_MAX, [_SC_JOB_CONTROL] = 1, [_SC_SAVED_IDS] = 1, - [_SC_REALTIME_SIGNALS] = 200809, // XXX EMSCRIPTEN replace 1, - [_SC_PRIORITY_SCHEDULING] = 200809, // XXX EMSCRIPTEN replace -1, + [_SC_REALTIME_SIGNALS] = 1, + [_SC_PRIORITY_SCHEDULING] = -1, [_SC_TIMERS] = VER, [_SC_ASYNCHRONOUS_IO] = VER, - [_SC_PRIORITIZED_IO] = VER, // XXX EMSCRIPTEN replace -1 - [_SC_SYNCHRONIZED_IO] = 200809, // XXX EMSCRIPTEN replace -1, + [_SC_PRIORITIZED_IO] = -1, + [_SC_SYNCHRONIZED_IO] = -1, [_SC_FSYNC] = VER, [_SC_MAPPED_FILES] = VER, [_SC_MEMLOCK] = VER, @@ -49,42 +54,42 @@ long sysconf(int name) [_SC_SHARED_MEMORY_OBJECTS] = VER, [_SC_AIO_LISTIO_MAX] = -1, [_SC_AIO_MAX] = -1, - [_SC_AIO_PRIO_DELTA_MAX] = 20, // XXX EMSCRIPTEN replace JT_ZERO, /* ?? */ - [_SC_DELAYTIMER_MAX] = 2147483647, // XXX EMSCRIPTEN replace _POSIX_DELAYTIMER_MAX, + [_SC_AIO_PRIO_DELTA_MAX] = JT_ZERO, /* ?? */ + [_SC_DELAYTIMER_MAX] = _POSIX_DELAYTIMER_MAX, [_SC_MQ_OPEN_MAX] = -1, [_SC_MQ_PRIO_MAX] = JT_MQ_PRIO_MAX, [_SC_VERSION] = VER, [_SC_PAGE_SIZE] = JT_PAGE_SIZE, - [_SC_RTSIG_MAX] = 32, // XXX EMSCRIPTEN replace _NSIG - 1 - 31 - 3, - [_SC_SEM_NSEMS_MAX] = -1, // XXX EMSCRIPTEN replace SEM_NSEMS_MAX, + [_SC_RTSIG_MAX] = _NSIG - 1 - 31 - 3, + [_SC_SEM_NSEMS_MAX] = SEM_NSEMS_MAX, [_SC_SEM_VALUE_MAX] = JT_SEM_VALUE_MAX, - [_SC_SIGQUEUE_MAX] = 47839, // XXX EMSCRIPTEN replace -1, + [_SC_SIGQUEUE_MAX] = -1, [_SC_TIMER_MAX] = -1, [_SC_BC_BASE_MAX] = _POSIX2_BC_BASE_MAX, [_SC_BC_DIM_MAX] = _POSIX2_BC_DIM_MAX, [_SC_BC_SCALE_MAX] = _POSIX2_BC_SCALE_MAX, [_SC_BC_STRING_MAX] = _POSIX2_BC_STRING_MAX, - [_SC_COLL_WEIGHTS_MAX] = 255, // XXX EMSCRIPTEN replace COLL_WEIGHTS_MAX, - [_SC_EXPR_NEST_MAX] = 32, // XXX EMSCRIPTEN replace -1, - [_SC_LINE_MAX] = 2048, // XXX EMSCRIPTEN replace -1, - [_SC_RE_DUP_MAX] = 32767, // XXX EMSCRIPTEN replace RE_DUP_MAX, + [_SC_COLL_WEIGHTS_MAX] = COLL_WEIGHTS_MAX, + [_SC_EXPR_NEST_MAX] = -1, + [_SC_LINE_MAX] = -1, + [_SC_RE_DUP_MAX] = RE_DUP_MAX, [_SC_2_VERSION] = VER, [_SC_2_C_BIND] = VER, - [_SC_2_C_DEV] = 200809, // XXX EMSCRIPTEN replace -1, + [_SC_2_C_DEV] = -1, [_SC_2_FORT_DEV] = -1, [_SC_2_FORT_RUN] = -1, - [_SC_2_SW_DEV] = 200809, // XXX EMSCRIPTEN replace -1, - [_SC_2_LOCALEDEF] = 200809, // XXX EMSCRIPTEN replace -1, + [_SC_2_SW_DEV] = -1, + [_SC_2_LOCALEDEF] = -1, [_SC_IOV_MAX] = IOV_MAX, [_SC_THREADS] = VER, [_SC_THREAD_SAFE_FUNCTIONS] = VER, - [_SC_GETGR_R_SIZE_MAX] = 1024, // XXX EMSCRIPTEN replace -1, - [_SC_GETPW_R_SIZE_MAX] = 1024, // XXX EMSCRIPTEN replace -1, + [_SC_GETGR_R_SIZE_MAX] = -1, + [_SC_GETPW_R_SIZE_MAX] = -1, [_SC_LOGIN_NAME_MAX] = 256, [_SC_TTY_NAME_MAX] = TTY_NAME_MAX, [_SC_THREAD_DESTRUCTOR_ITERATIONS] = PTHREAD_DESTRUCTOR_ITERATIONS, - [_SC_THREAD_KEYS_MAX] = 1024, // XXX EMSCRIPTEN replace PTHREAD_KEYS_MAX, - [_SC_THREAD_STACK_MIN] = 16384, // XXX EMSCRIPTEN replace PTHREAD_STACK_MIN, + [_SC_THREAD_KEYS_MAX] = PTHREAD_KEYS_MAX, + [_SC_THREAD_STACK_MIN] = PTHREAD_STACK_MIN, [_SC_THREAD_THREADS_MAX] = -1, [_SC_THREAD_ATTR_STACKADDR] = VER, [_SC_THREAD_ATTR_STACKSIZE] = VER, @@ -96,27 +101,27 @@ long sysconf(int name) [_SC_NPROCESSORS_ONLN] = JT_NPROCESSORS_ONLN, [_SC_PHYS_PAGES] = JT_PHYS_PAGES, [_SC_AVPHYS_PAGES] = JT_AVPHYS_PAGES, - [_SC_ATEXIT_MAX] = 2147483647, // XXX EMSCRIPTEN replace -1, + [_SC_ATEXIT_MAX] = -1, [_SC_PASS_MAX] = -1, [_SC_XOPEN_VERSION] = _XOPEN_VERSION, [_SC_XOPEN_XCU_VERSION] = _XOPEN_VERSION, [_SC_XOPEN_UNIX] = 1, - [_SC_XOPEN_CRYPT] = 1, // XXX EMSCRIPTEN replace -1, + [_SC_XOPEN_CRYPT] = -1, [_SC_XOPEN_ENH_I18N] = 1, [_SC_XOPEN_SHM] = 1, - [_SC_2_CHAR_TERM] = 200809, // XXX EMSCRIPTEN replace -1, + [_SC_2_CHAR_TERM] = -1, [_SC_2_UPE] = -1, [_SC_XOPEN_XPG2] = -1, [_SC_XOPEN_XPG3] = -1, [_SC_XOPEN_XPG4] = -1, [_SC_NZERO] = NZERO, - [_SC_XBS5_ILP32_OFF32] = 1, // XXX EMSCRIPTEN replace -1, + [_SC_XBS5_ILP32_OFF32] = -1, [_SC_XBS5_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : JT_ZERO, - [_SC_XBS5_LP64_OFF64] = -1, // XXX EMSCRIPTEN replace sizeof(long)==8 ? 1 : JT_ZERO, + [_SC_XBS5_LP64_OFF64] = sizeof(long)==8 ? 1 : JT_ZERO, [_SC_XBS5_LPBIG_OFFBIG] = -1, - [_SC_XOPEN_LEGACY] = 1, // XXX EMSCRIPTEN replace -1, - [_SC_XOPEN_REALTIME] = 1, // XXX EMSCRIPTEN replace -1, - [_SC_XOPEN_REALTIME_THREADS] = 1, // XXX EMSCRIPTEN replace -1, + [_SC_XOPEN_LEGACY] = -1, + [_SC_XOPEN_REALTIME] = -1, + [_SC_XOPEN_REALTIME_THREADS] = -1, [_SC_ADVISORY_INFO] = VER, [_SC_BARRIERS] = VER, [_SC_CLOCK_SELECTION] = VER, @@ -137,14 +142,14 @@ long sysconf(int name) [_SC_2_PBS_LOCATE] = -1, [_SC_2_PBS_MESSAGE] = -1, [_SC_2_PBS_TRACK] = -1, - [_SC_SYMLOOP_MAX] = -1, // XXX EMSCRIPTEN replace SYMLOOP_MAX, + [_SC_SYMLOOP_MAX] = SYMLOOP_MAX, [_SC_STREAMS] = JT_ZERO, [_SC_2_PBS_CHECKPOINT] = -1, - [_SC_V6_ILP32_OFF32] = 1, // XXX EMSCRIPTEN replace -1, + [_SC_V6_ILP32_OFF32] = -1, [_SC_V6_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : JT_ZERO, - [_SC_V6_LP64_OFF64] = -1, // XXX EMSCRIPTEN replace sizeof(long)==8 ? 1 : JT_ZERO, + [_SC_V6_LP64_OFF64] = sizeof(long)==8 ? 1 : JT_ZERO, [_SC_V6_LPBIG_OFFBIG] = -1, - [_SC_HOST_NAME_MAX] = 64, // XXX EMSCRIPTEN replace HOST_NAME_MAX, + [_SC_HOST_NAME_MAX] = HOST_NAME_MAX, [_SC_TRACE] = -1, [_SC_TRACE_EVENT_FILTER] = -1, [_SC_TRACE_INHERIT] = -1, @@ -161,7 +166,7 @@ long sysconf(int name) [_SC_TRACE_NAME_MAX] = -1, [_SC_TRACE_SYS_MAX] = -1, [_SC_TRACE_USER_EVENT_MAX] = -1, - [_SC_XOPEN_STREAMS] = -1, // XXX EMSCRIPTEN replace JT_ZERO, + [_SC_XOPEN_STREAMS] = JT_ZERO, [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1, [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1, }; @@ -191,8 +196,7 @@ long sysconf(int name) case JT_NPROCESSORS_CONF & 255: case JT_NPROCESSORS_ONLN & 255: ; #ifdef __EMSCRIPTEN__ - errno = ENOSYS; - return -1; + return emscripten_num_logical_cores(); #else unsigned char set[128] = {1}; int i, cnt; @@ -204,8 +208,7 @@ long sysconf(int name) case JT_PHYS_PAGES & 255: case JT_AVPHYS_PAGES & 255: ; #ifdef __EMSCRIPTEN__ - errno = ENOSYS; - return -1; + return emscripten_get_heap_max() / PAGE_SIZE; #else unsigned long long mem; int __lsysinfo(struct sysinfo *); diff --git a/src/env/__environ.c b/src/env/__environ.c index 9b708fad..1a22ffc0 100644 --- a/src/env/__environ.c +++ b/src/env/__environ.c @@ -1,16 +1,19 @@ #include "libc.h" -#ifdef __EMSCRIPTEN__ -#include -#include -#endif - char **__environ = 0; weak_alias(__environ, ___environ); weak_alias(__environ, _environ); weak_alias(__environ, environ); #ifdef __EMSCRIPTEN__ +#include +#include +// Included for emscripten_builtin_free / emscripten_builtin_malloc +// TODO(sbc): Should these be in their own header to avoid emmalloc here? +#include + +// We use emscripten_builtin_malloc here because this memory is never freed and +// and we don't want LSan to consider this a leak. __attribute__((constructor(100))) // construct this before user code void __emscripten_environ_constructor(void) { size_t environ_count; @@ -21,11 +24,11 @@ void __emscripten_environ_constructor(void) { return; } - __environ = malloc(sizeof(char *) * (environ_count + 1)); + __environ = emscripten_builtin_malloc(sizeof(char *) * (environ_count + 1)); if (__environ == 0) { return; } - char *environ_buf = malloc(sizeof(char) * environ_buf_size); + char *environ_buf = emscripten_builtin_malloc(sizeof(char) * environ_buf_size); if (environ_buf == 0) { __environ = 0; return; diff --git a/src/exit/_Exit.c b/src/exit/_Exit.c index 7a6115c7..9d06aac1 100644 --- a/src/exit/_Exit.c +++ b/src/exit/_Exit.c @@ -3,6 +3,10 @@ _Noreturn void _Exit(int ec) { +#ifdef __EMSCRIPTEN__ + __wasi_proc_exit(ec); +#else __syscall(SYS_exit_group, ec); for (;;) __syscall(SYS_exit, ec); +#endif } diff --git a/src/fcntl/fcntl.c b/src/fcntl/fcntl.c index 2b7c3df2..5f7a1571 100644 --- a/src/fcntl/fcntl.c +++ b/src/fcntl/fcntl.c @@ -5,13 +5,21 @@ #include "syscall.h" #include "libc.h" +#ifdef __EMSCRIPTEN__ +__attribute__((no_sanitize("address"))) +#endif int fcntl(int fd, int cmd, ...) { unsigned long arg; - va_list ap; - va_start(ap, cmd); - arg = va_arg(ap, unsigned long); - va_end(ap); + // XXX Emscripten: According to the va_arg man page it is undefined behaviour to + // read arguments that are not passed. This can lead to a false positive + // in SAFE_HEAP, so avoid it. + if (cmd != F_GETFL && cmd != F_GETFD && cmd != F_GETOWN) { + va_list ap; + va_start(ap, cmd); + arg = va_arg(ap, unsigned long); + va_end(ap); + } if (cmd == F_SETFL) arg |= O_LARGEFILE; if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, (void *)arg); if (cmd == F_GETOWN) { @@ -25,8 +33,7 @@ int fcntl(int fd, int cmd, ...) int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg); if (ret != -EINVAL) { #ifndef __EMSCRIPTEN__ // CLOEXEC makes no sense for a single process - if (ret >= 0) - __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); + if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); #endif return __syscall_ret(ret); } diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 5717627a..736dfd52 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -1,6 +1,31 @@ #ifndef _INTERNAL_RELOC_H #define _INTERNAL_RELOC_H +#ifdef __EMSCRIPTEN__ +// Declare `struct dso` in this header so that it is visible to gen_struct_info. + +#pragma once + +#include + +struct dso { + struct dso *next, *prev; + + // For async mode + em_dlopen_callback onsuccess; + em_arg_callback_func onerror; + void* user_data; + + // Flags used to open the library. We need to cache these so that + // (in the future) other threads can mirror the open library state. + int flags; + + // Flexible array; must be final element of struct + char name[]; +}; + +#else + #include #include #include @@ -95,4 +120,6 @@ struct fdpic_dummy_loadmap { typedef void (*stage2_func)(unsigned char *, size_t *); typedef _Noreturn void (*stage3_func)(size_t *); +#endif // __EMSCRIPTEN__ + #endif diff --git a/src/internal/libc.h b/src/internal/libc.h index 5e145183..ad3ebdea 100644 --- a/src/internal/libc.h +++ b/src/internal/libc.h @@ -4,6 +4,7 @@ #include #include #include +#include struct __locale_map; @@ -55,7 +56,12 @@ void __unlockfile(FILE *) ATTR_LIBC_VISIBILITY; #define UNLOCK(x) __unlock(x) void __synccall(void (*)(void *), void *); +#ifdef __EMSCRIPTEN__ +int __setxid_emscripten(); +#define __setxid(a, b, c, d) __setxid_emscripten() +#else int __setxid(int, int, int, int); +#endif extern char **__environ; diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 4bf78350..5d673f4c 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -15,14 +15,29 @@ #define pthread __pthread +#ifdef __EMSCRIPTEN__ +#define EM_THREAD_NAME_MAX 32 + +typedef struct thread_profiler_block { + // One of THREAD_STATUS_* + int threadStatus; + // Wallclock time denoting when the current thread state was entered in. + double currentStatusStartTime; + // Accumulated duration times denoting how much time has been spent in each + // state, in msecs. + double timeSpentInStatus[EM_THREAD_STATUS_NUMFIELDS]; + // A human-readable name for this thread. + char name[EM_THREAD_NAME_MAX]; +} thread_profiler_block; +#endif + struct pthread { // XXX Emscripten: Need some custom thread control structures. #ifdef __EMSCRIPTEN__ // Note: The specific order of these fields is important, since these are accessed // by direct pointer arithmetic in worker.js. - int threadStatus; // 0: thread not exited, 1: exited. - int threadExitCode; // Thread exit code. - void *profilerBlock; // If --threadprofiler is enabled, this pointer is allocated to contain internal information about the thread state for profiling purposes. + _Atomic int threadStatus; // 0: thread not exited, 1: exited. + thread_profiler_block * _Atomic profilerBlock; // If --threadprofiler is enabled, this pointer is allocated to contain internal information about the thread state for profiling purposes. #endif struct pthread *self; @@ -97,7 +112,7 @@ struct __timer { // XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, so use an extra field // _rw_wr_owner to record which thread owns the write lock in order to avoid hangs. // Points to the pthread that currently has the write lock. -#define _rw_wr_owner __u.__vi[3] +#define _rw_wr_owner __u.__p[3] #endif #define _b_lock __u.__vi[0] #define _b_waiters __u.__vi[1] @@ -164,15 +179,14 @@ void __block_all_sigs(void *); void __block_app_sigs(void *); void __restore_sigs(void *); +#ifdef __EMSCRIPTEN__ +// Keep in sync with DEFAULT_PTHREAD_STACK_SIZE in settings.js +#define DEFAULT_STACK_SIZE (2*1024*1024) +#else #define DEFAULT_STACK_SIZE 81920 +#endif #define DEFAULT_GUARD_SIZE PAGE_SIZE #define __ATTRP_C11_THREAD ((void*)(uintptr_t)-1) -#ifdef __EMSCRIPTEN__ -void __emscripten_init_pthread(pthread_t thread); -#if !__EMSCRIPTEN_PTHREADS__ -pthread_t __emscripten_pthread_stub(void); -#endif -#endif #endif diff --git a/src/internal/syscall.h b/src/internal/syscall.h index b60fce0a..3ee67e9e 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -21,7 +21,7 @@ typedef long syscall_arg_t; extern "C" { #endif __attribute__((visibility("hidden"))) -long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), +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); #ifdef __cplusplus @@ -29,25 +29,14 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #endif #ifndef __EMSCRIPTEN__ -#ifdef SYSCALL_NO_INLINE -#define __syscall0(n) (__syscall)(n) -#define __syscall1(n,a) (__syscall)(n,__scc(a)) -#define __syscall2(n,a,b) (__syscall)(n,__scc(a),__scc(b)) -#define __syscall3(n,a,b,c) (__syscall)(n,__scc(a),__scc(b),__scc(c)) -#define __syscall4(n,a,b,c,d) (__syscall)(n,__scc(a),__scc(b),__scc(c),__scc(d)) -#define __syscall5(n,a,b,c,d,e) (__syscall)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) -#define __syscall6(n,a,b,c,d,e,f) (__syscall)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) -#else #define __syscall1(n,a) __syscall1(n,__scc(a)) #define __syscall2(n,a,b) __syscall2(n,__scc(a),__scc(b)) #define __syscall3(n,a,b,c) __syscall3(n,__scc(a),__scc(b),__scc(c)) #define __syscall4(n,a,b,c,d) __syscall4(n,__scc(a),__scc(b),__scc(c),__scc(d)) #define __syscall5(n,a,b,c,d,e) __syscall5(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) #define __syscall6(n,a,b,c,d,e,f) __syscall6(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) -#endif -#define __syscall7(n,a,b,c,d,e,f,g) (__syscall)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) #else // __EMSCRIPTEN__ -#define __syscall_emscripten(n, ...) __syscall##n(__VA_ARGS__) +#define __syscall_emscripten(n, ...) n(__VA_ARGS__) #define __syscall_emscripten0(n) __syscall_emscripten(n) #define __syscall_emscripten1(n,a) __syscall_emscripten(n,__scc(a)) #define __syscall_emscripten2(n,a,b) __syscall_emscripten(n,__scc(a),__scc(b)) @@ -55,7 +44,6 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #define __syscall_emscripten4(n,a,b,c,d) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c),__scc(d)) #define __syscall_emscripten5(n,a,b,c,d,e) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) #define __syscall_emscripten6(n,a,b,c,d,e,f) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) -#define __syscall_emscripten7(n,a,b,c,d,e,f,g) __syscall_emscripten(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) #endif // __EMSCRIPTEN__ #define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n @@ -87,7 +75,6 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) #else // __EMSCRIPTEN__ #define __syscall_cp(...) __syscall(__VA_ARGS__) -#define SYSCALL_USE_SOCKETCALL #endif // __EMSCRIPTEN__ #define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) @@ -251,6 +238,12 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #define __SC_recvmmsg 19 #define __SC_sendmmsg 20 +/* This is valid only because all socket syscalls are made via + * socketcall, which always fills unused argument slots with zeros. */ +#ifndef SYS_accept +#define SYS_accept SYS_accept4 +#endif + #ifndef __EMSCRIPTEN__ #ifdef SYS_open #define __sys_open2(x,pn,fl) __syscall2(SYS_open, pn, (fl)|O_LARGEFILE) @@ -264,10 +257,10 @@ long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), #define __sys_open_cp3(x,pn,fl,mo) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) #endif #else // __EMSCRIPTEN__ -#define __sys_open2(x,pn,fl) __SYSCALL_CONCAT(__syscall, SYS_open)(__scc(pn), __scc((fl)|O_LARGEFILE)) -#define __sys_open3(x,pn,fl,mo) __SYSCALL_CONCAT(__syscall, SYS_open)(__scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) -#define __sys_open_cp2(x,pn,fl) __SYSCALL_CONCAT(__syscall, SYS_open)(__scc(pn), __scc((fl)|O_LARGEFILE)) -#define __sys_open_cp3(x,pn,fl,mo) __SYSCALL_CONCAT(__syscall, SYS_open)(__scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) +#define __sys_open2(x,pn,fl) __syscall_open(__scc(pn), __scc((fl)|O_LARGEFILE)) +#define __sys_open3(x,pn,fl,mo) __syscall_open(__scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) +#define __sys_open_cp2(x,pn,fl) __syscall_open(__scc(pn), __scc((fl)|O_LARGEFILE)) +#define __sys_open_cp3(x,pn,fl,mo) __syscall_open(__scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) #endif #define __sys_open(...) __SYSCALL_DISP(__sys_open,,__VA_ARGS__) #define sys_open(...) __syscall_ret(__sys_open(__VA_ARGS__)) diff --git a/src/legacy/getpagesize.c b/src/legacy/getpagesize.c index 3d3240bc..0fc29ffc 100644 --- a/src/legacy/getpagesize.c +++ b/src/legacy/getpagesize.c @@ -4,11 +4,5 @@ int getpagesize(void) { -#if __EMSCRIPTEN__ - // A value used historically in emscripten, and which so far we don't have a - // strong reason to change. - return 16384; -#else return PAGE_SIZE; -#endif } diff --git a/src/linux/gettid.c b/src/linux/gettid.c new file mode 100644 index 00000000..70767137 --- /dev/null +++ b/src/linux/gettid.c @@ -0,0 +1,8 @@ +#define _GNU_SOURCE +#include +#include "pthread_impl.h" + +pid_t gettid(void) +{ + return __pthread_self()->tid; +} diff --git a/src/locale/newlocale.c b/src/locale/newlocale.c index bbc31208..f50bbe91 100644 --- a/src/locale/newlocale.c +++ b/src/locale/newlocale.c @@ -41,6 +41,8 @@ locale_t __newlocale(int mask, const char *name, locale_t loc) if (j==1 && tmp.cat[LC_CTYPE]==&__c_dot_utf8) return UTF8_LOCALE; + if ((loc = malloc(sizeof *loc))) *loc = tmp; + return loc; } diff --git a/src/network/recvmmsg.c b/src/network/recvmmsg.c index 58b1b2f6..d8a4df5d 100644 --- a/src/network/recvmmsg.c +++ b/src/network/recvmmsg.c @@ -5,7 +5,7 @@ int recvmmsg(int fd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags, struct timespec *timeout) { -#if LONG_MAX > INT_MAX +#if LONG_MAX > INT_MAX && !defined(__EMSCRIPTEN__) struct mmsghdr *mh = msgvec; unsigned int i; for (i = vlen; i; i--, mh++) diff --git a/src/network/recvmsg.c b/src/network/recvmsg.c index 4f526659..80564b6d 100644 --- a/src/network/recvmsg.c +++ b/src/network/recvmsg.c @@ -6,7 +6,7 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) { ssize_t r; -#if LONG_MAX > INT_MAX +#if LONG_MAX > INT_MAX && !defined(__EMSCRIPTEN__) struct msghdr h, *orig = msg; if (msg) { h = *msg; @@ -15,7 +15,7 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) } #endif r = socketcall_cp(recvmsg, fd, msg, flags, 0, 0, 0); -#if LONG_MAX > INT_MAX +#if LONG_MAX > INT_MAX && !defined(__EMSCRIPTEN__) if (orig) *orig = h; #endif return r; diff --git a/src/network/sendmsg.c b/src/network/sendmsg.c index 5f080007..afd12c69 100644 --- a/src/network/sendmsg.c +++ b/src/network/sendmsg.c @@ -7,7 +7,7 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) { -#if LONG_MAX > INT_MAX +#if LONG_MAX > INT_MAX && !defined(__EMSCRIPTEN__) struct msghdr h; struct cmsghdr chbuf[1024/sizeof(struct cmsghdr)+1], *c; if (msg) { diff --git a/src/stat/fstat.c b/src/stat/fstat.c index 46c53511..ca4d4999 100644 --- a/src/stat/fstat.c +++ b/src/stat/fstat.c @@ -13,8 +13,7 @@ int fstat(int fd, struct stat *st) { int ret = __syscall(SYS_fstat, fd, st); #if __EMSCRIPTEN__ - if (ret != -EBADF || !__wasi_fd_is_valid(fd)) - return __syscall_ret(ret); + return __syscall_ret(ret); #else if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) return __syscall_ret(ret); diff --git a/src/stdlib/strtol.c b/src/stdlib/strtol.c index 730bf2d7..f4e53c79 100644 --- a/src/stdlib/strtol.c +++ b/src/stdlib/strtol.c @@ -6,6 +6,89 @@ #include #include "libc.h" +#ifdef __EMSCRIPTEN__ +#include + +// Loosely based on __intscan but simplified, and optimized for size +// - Doesn't use FILE or getc/ungetc, just operates directly on memory +// - Avoids lookup table +// - Avoids special cases loops for certain bases +// - Skips an early exit with EINVAL when char 0 is greater than base. Its not +// clear this was correct, and glibc seems not do this either. +static unsigned long long strtox(const char *s, char **p, int base, unsigned long long lim) { + int neg=0; + unsigned long long y=0; + const char* orig = s; + + if (base > 36) { + errno = EINVAL; + return 0; + } + + while (*s && isspace(*s)) { s++; }; + + // Handle sign + if (*s=='+' || *s=='-') { + neg = -(*s=='-'); + s++; + } + + int found_digit = 0; + + // Handle hex/octal prefix 0x/00 + if ((base == 0 || base == 16) && *s=='0') { + found_digit = 1; + s++; + if ((*s|32)=='x') { + s++; + base = 16; + } else if (base == 0) { + base = 8; + } + } else if (base == 0) { + base = 10; + } + + int val; + int overflow = 0; + for (y=0; ; s++) { + if ('0' <= *s && *s <= '9') val = *s -'0'; + else if ('a' <= *s && *s <= 'z') val = 10 + *s -'a'; + else if ('A' <= *s && *s <= 'Z') val = 10 + *s -'A'; + else break; + if (val>=base) break; + if (y > ULLONG_MAX/base || (base*y>ULLONG_MAX-val)) { + overflow = 1; + continue; + } + found_digit = 1; + y = y*base + val; + } + if (p) { + if (found_digit) { + *p = (char*)s; + } else { + *p = (char*)orig; + } + } + if (overflow) { + // We exit'd the above loop due to overflow + errno = ERANGE; + y = lim; + if (lim&1) neg = 0; + } + if (y>=lim) { + if (!(lim&1) && !neg) { + errno = ERANGE; + return lim-1; + } else if (y>lim) { + errno = ERANGE; + return lim; + } + } + return (y^neg)-neg; +} +#else static unsigned long long strtox(const char *s, char **p, int base, unsigned long long lim) { /* FIXME: use a helper function or macro to setup the FILE */ @@ -25,6 +108,7 @@ static unsigned long long strtox(const char *s, char **p, int base, unsigned lon } return y; } +#endif unsigned long long strtoull(const char *restrict s, char **restrict p, int base) { diff --git a/src/string/memchr.c b/src/string/memchr.c index 65f0d789..bad4e75c 100644 --- a/src/string/memchr.c +++ b/src/string/memchr.c @@ -12,7 +12,8 @@ void *memchr(const void *src, int c, size_t n) { const unsigned char *s = src; c = (unsigned char)c; -#ifdef __GNUC__ +/* XXX EMSCRIPTEN: add __has_feature check */ +#if defined(__GNUC__) && !__has_feature(address_sanitizer) for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--); if (n && *s != c) { typedef size_t __attribute__((__may_alias__)) word; diff --git a/src/string/memcmp.c b/src/string/memcmp.c index bdbce9f0..c93cf8cc 100644 --- a/src/string/memcmp.c +++ b/src/string/memcmp.c @@ -1,8 +1,32 @@ +#if __EMSCRIPTEN__ +#include +#endif #include int memcmp(const void *vl, const void *vr, size_t n) { const unsigned char *l=vl, *r=vr; + +// XXX EMSCRIPTEN: add an optimized version. +#if !defined(EMSCRIPTEN_OPTIMIZE_FOR_OZ) && !__has_feature(address_sanitizer) + // If we have enough bytes, and everything is aligned, loop on words instead + // of single bytes. + if (n >= 4 && !((((uintptr_t)l) & 3) | (((uintptr_t)r) & 3))) { + while (n >= 4) { + if (*((uint32_t *)l) != *((uint32_t *)r)) { + // Go to the single-byte loop to find the specific byte. + break; + } + l += 4; + r += 4; + n -= 4; + } + } +#endif + +#if defined(EMSCRIPTEN_OPTIMIZE_FOR_OZ) +#pragma clang loop unroll(disable) +#endif for (; n && *l == *r; n--, l++, r++); return n ? *l-*r : 0; } diff --git a/src/string/stpcpy.c b/src/string/stpcpy.c index 4db46a9e..b3685bf5 100644 --- a/src/string/stpcpy.c +++ b/src/string/stpcpy.c @@ -1,6 +1,7 @@ #include #include #include +#include "libc.h" #define ALIGN (sizeof(size_t)) #define ONES ((size_t)-1/UCHAR_MAX) @@ -9,7 +10,8 @@ char *__stpcpy(char *restrict d, const char *restrict s) { -#ifdef __GNUC__ +/* XXX EMSCRIPTEN: add __has_feature check */ +#if defined(__GNUC__) && !__has_feature(address_sanitizer) typedef size_t __attribute__((__may_alias__)) word; word *wd; const word *ws; diff --git a/src/string/stpncpy.c b/src/string/stpncpy.c index c699cfe5..2e3f67ef 100644 --- a/src/string/stpncpy.c +++ b/src/string/stpncpy.c @@ -1,6 +1,7 @@ #include #include #include +#include "libc.h" #define ALIGN (sizeof(size_t)-1) #define ONES ((size_t)-1/UCHAR_MAX) @@ -9,7 +10,8 @@ char *__stpncpy(char *restrict d, const char *restrict s, size_t n) { -#ifdef __GNUC__ +/* XXX EMSCRIPTEN: add __has_feature check */ +#if defined(__GNUC__) && !__has_feature(address_sanitizer) typedef size_t __attribute__((__may_alias__)) word; word *wd; const word *ws; diff --git a/src/string/strchrnul.c b/src/string/strchrnul.c index 39e2635b..0ead0dff 100644 --- a/src/string/strchrnul.c +++ b/src/string/strchrnul.c @@ -1,6 +1,7 @@ #include #include #include +#include "libc.h" #define ALIGN (sizeof(size_t)) #define ONES ((size_t)-1/UCHAR_MAX) @@ -12,7 +13,8 @@ char *__strchrnul(const char *s, int c) c = (unsigned char)c; if (!c) return (char *)s + strlen(s); -#ifdef __GNUC__ +/* XXX EMSCRIPTEN: add __has_feature check */ +#if defined(__GNUC__) && !__has_feature(address_sanitizer) typedef size_t __attribute__((__may_alias__)) word; const word *w; for (; (uintptr_t)s % ALIGN; s++) diff --git a/src/string/strlen.c b/src/string/strlen.c index 309990f0..aab07195 100644 --- a/src/string/strlen.c +++ b/src/string/strlen.c @@ -10,7 +10,8 @@ size_t strlen(const char *s) { const char *a = s; -#ifdef __GNUC__ +/* XXX EMSCRIPTEN: add __has_feature check */ +#if defined(__GNUC__) && !__has_feature(address_sanitizer) typedef size_t __attribute__((__may_alias__)) word; const word *w; for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a; diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index 71abe8e7..433f1d00 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -42,7 +42,12 @@ int __timedwait_cp(volatile int *addr, int val, #ifdef __EMSCRIPTEN__ double msecsToSleep = top ? (top->tv_sec * 1000 + top->tv_nsec / 1000000.0) : INFINITY; int is_main_thread = emscripten_is_main_browser_thread(); - if (is_main_thread || pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { + // cp suffix in the function name means "cancellation point", so this wait can be cancelled + // by the users unless current threads cancelability is set to PTHREAD_CANCEL_DISABLE + // which may be either done by the user of __timedwait() function. + if (is_main_thread || + pthread_self()->canceldisable != PTHREAD_CANCEL_DISABLE || + pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { double sleepUntilTime = emscripten_get_now() + msecsToSleep; do { if (_pthread_isduecanceled(pthread_self())) { diff --git a/src/thread/__wait.c b/src/thread/__wait.c index 265451da..816f4c4a 100644 --- a/src/thread/__wait.c +++ b/src/thread/__wait.c @@ -1,10 +1,13 @@ #ifdef __EMSCRIPTEN__ #include +#include #endif #include "pthread_impl.h" +#ifdef __EMSCRIPTEN__ int _pthread_isduecanceled(struct pthread *pthread_ptr); +#endif void __wait(volatile int *addr, volatile int *waiters, int val, int priv) { @@ -18,7 +21,7 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv) #ifdef __EMSCRIPTEN__ int is_main_thread = emscripten_is_main_runtime_thread(); while (*addr==val) { - if (pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { + if (is_main_thread || pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { // Must wait in slices in case this thread is cancelled in between. int e; do { diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c index 46b85661..8e212f00 100644 --- a/src/thread/pthread_barrier_wait.c +++ b/src/thread/pthread_barrier_wait.c @@ -87,14 +87,29 @@ int pthread_barrier_wait(pthread_barrier_t *b) while (spins-- && !inst->finished) a_spin(); a_inc(&inst->finished); - while (inst->finished == 1) { #ifdef __EMSCRIPTEN__ - emscripten_futex_wait(&inst->finished, 1, INFINITY); + int is_main_thread = emscripten_is_main_browser_thread(); + while (inst->finished == 1) { + if (is_main_thread) { + int e; + do { + // Main thread waits in _very_ small slices so that it stays responsive to assist proxied + // pthread calls. + e = emscripten_futex_wait(&inst->finished, 1, 1); + // Assist other threads by executing proxied operations that are effectively singlethreaded. + emscripten_main_thread_process_queued_calls(); + } while(e == -ETIMEDOUT); + } else { + // Can wait in one go. + emscripten_futex_wait(&inst->finished, 1, INFINITY); + } + } #else + while (inst->finished == 1) { __syscall(SYS_futex,&inst->finished,FUTEX_WAIT|128,1,0) != -ENOSYS || __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0); -#endif } +#endif return PTHREAD_BARRIER_SERIAL_THREAD; } diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c index ed77f74d..26379950 100644 --- a/src/thread/pthread_detach.c +++ b/src/thread/pthread_detach.c @@ -5,6 +5,14 @@ int __pthread_join(pthread_t, void **); static int __pthread_detach(pthread_t t) { + // XXX EMSCRIPTEN: Add check for invalid (already joined) thread. Again + // for the benefit of the conformance tests. + if (t->self != t) + return ESRCH; + // XXX EMSCRIPTEN: Even though the man page says this is undefined behaviour + // we have several tests in the posixtest suite that depend on this. + if (t->detached) + return EINVAL; /* Cannot detach a thread that's already exiting */ if (a_swap(t->exitlock, 1)) return __pthread_join(t, 0); @@ -15,3 +23,5 @@ static int __pthread_detach(pthread_t t) weak_alias(__pthread_detach, pthread_detach); weak_alias(__pthread_detach, thrd_detach); +// XXX EMSCRIPTEN: add extra alias for asan. +weak_alias(__pthread_detach, emscripten_builtin_pthread_detach); diff --git a/src/thread/pthread_getattr_np.c b/src/thread/pthread_getattr_np.c index 10ea5127..d213096a 100644 --- a/src/thread/pthread_getattr_np.c +++ b/src/thread/pthread_getattr_np.c @@ -7,6 +7,10 @@ int pthread_getattr_np(pthread_t t, pthread_attr_t *a) { *a = (pthread_attr_t){0}; a->_a_detach = !!t->detached; +#ifdef __EMSCRIPTEN__ + a->_a_stackaddr = (uintptr_t)t->stack; + a->_a_stacksize = t->stack_size - DEFAULT_STACK_SIZE; +#else if (t->stack) { a->_a_stackaddr = (uintptr_t)t->stack; a->_a_stacksize = t->stack_size - DEFAULT_STACK_SIZE; @@ -19,5 +23,6 @@ int pthread_getattr_np(pthread_t t, pthread_attr_t *a) l += PAGE_SIZE; a->_a_stacksize = l - DEFAULT_STACK_SIZE; } +#endif return 0; } diff --git a/src/thread/pthread_getspecific.c b/src/thread/pthread_getspecific.c index d9342a56..f3772630 100644 --- a/src/thread/pthread_getspecific.c +++ b/src/thread/pthread_getspecific.c @@ -4,6 +4,10 @@ static void *__pthread_getspecific(pthread_key_t k) { struct pthread *self = __pthread_self(); + // XXX EMSCRIPTEN: self->tsd can be NULL in the case of the + // main thread where pthread_key_create is not called. + // See __pthread_key_create for where it get assigned. + if (!self->tsd) return NULL; return self->tsd[k]; } diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c index e77deb1a..d6e2a50b 100644 --- a/src/thread/pthread_key_create.c +++ b/src/thread/pthread_key_create.c @@ -39,11 +39,7 @@ int __pthread_key_delete(pthread_key_t k) return 0; } -#ifdef __EMSCRIPTEN__ -void EMSCRIPTEN_KEEPALIVE __pthread_tsd_run_dtors() -#else void __pthread_tsd_run_dtors() -#endif { pthread_t self = __pthread_self(); int i, j, not_finished = self->tsd_used; diff --git a/src/thread/pthread_rwlock_timedwrlock.c b/src/thread/pthread_rwlock_timedwrlock.c index e1d6162f..15a8acc1 100644 --- a/src/thread/pthread_rwlock_timedwrlock.c +++ b/src/thread/pthread_rwlock_timedwrlock.c @@ -5,13 +5,13 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct times #ifdef __EMSCRIPTEN__ /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. /// If attempting to lock the write lock that we already own, error out. - if (rw->_rw_wr_owner == (int)pthread_self()) return EDEADLK; + if (rw->_rw_wr_owner == (void *)pthread_self()) return EDEADLK; #endif int r, t; - + r = pthread_rwlock_trywrlock(rw); if (r != EBUSY) return r; - + int spins = 100; while (spins-- && rw->_rw_lock && !rw->_rw_waiters) a_spin(); @@ -27,7 +27,7 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct times #ifdef __EMSCRIPTEN__ /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. /// Mark this thread as the owner of this write lock. - rw->_rw_wr_owner = (int)pthread_self(); + rw->_rw_wr_owner = (void *)pthread_self(); #endif return r; } diff --git a/src/thread/pthread_rwlock_trywrlock.c b/src/thread/pthread_rwlock_trywrlock.c index fdd08d39..cf0f2c64 100644 --- a/src/thread/pthread_rwlock_trywrlock.c +++ b/src/thread/pthread_rwlock_trywrlock.c @@ -6,7 +6,7 @@ int pthread_rwlock_trywrlock(pthread_rwlock_t *rw) #ifdef __EMSCRIPTEN__ /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. /// Mark this thread to own the write lock, to ignore multiple attempts to lock. - rw->_rw_wr_owner = (int)pthread_self(); + rw->_rw_wr_owner = (void *)pthread_self(); #endif return 0; } diff --git a/src/thread/pthread_rwlock_unlock.c b/src/thread/pthread_rwlock_unlock.c index 61d5e386..15b363dc 100644 --- a/src/thread/pthread_rwlock_unlock.c +++ b/src/thread/pthread_rwlock_unlock.c @@ -7,7 +7,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rw) #ifdef __EMSCRIPTEN__ /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. /// Mark this thread to not own the write lock anymore. - if (rw->_rw_wr_owner == (int)pthread_self()) rw->_rw_wr_owner = 0; + if (rw->_rw_wr_owner == (void *)pthread_self()) rw->_rw_wr_owner = 0; #endif do { diff --git a/src/thread/thrd_create.c b/src/thread/thrd_create.c index 891d227b..ca4efb66 100644 --- a/src/thread/thrd_create.c +++ b/src/thread/thrd_create.c @@ -1,12 +1,14 @@ #include "pthread_impl.h" #include -// XXX Emscripten implements pthread_create directly rather than __pthread_create #ifdef __EMSCRIPTEN__ +// Fix for lsan. Since lsan wraps calls to the public `pthread_create` function +// if we call the internal __pthread_create function here to don't the wrapping +// See pthread_create wrapper in compiler-rt/lib/lsan/lsan_interceptors.cpp. #define __pthread_create pthread_create -#endif - +#else int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict); +#endif int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { diff --git a/src/thread/thrd_exit.c b/src/thread/thrd_exit.c index 270d3704..b66bd996 100644 --- a/src/thread/thrd_exit.c +++ b/src/thread/thrd_exit.c @@ -1,11 +1,6 @@ #include "pthread_impl.h" #include -// XXX Emscripten implements pthread_exit directly rather than __pthread_exit -#ifdef __EMSCRIPTEN__ -#define __pthread_exit pthread_exit -#endif - _Noreturn void __pthread_exit(void *); _Noreturn void thrd_exit(int result) diff --git a/src/thread/thrd_join.c b/src/thread/thrd_join.c index 0149c89f..ac667893 100644 --- a/src/thread/thrd_join.c +++ b/src/thread/thrd_join.c @@ -1,11 +1,6 @@ #include #include -// XXX Emscripten implements implements pthread_join directly rather than __pthread_join -#ifdef __EMSCRIPTEN__ -#define __pthread_join pthread_join -#endif - int __pthread_join(thrd_t, void**); int thrd_join(thrd_t t, int *res) diff --git a/src/time/asctime.c b/src/time/asctime.c index 57d15fe0..3102eb87 100644 --- a/src/time/asctime.c +++ b/src/time/asctime.c @@ -1,9 +1,9 @@ #include -char *__asctime_r(const struct tm *, char *); +char *__asctime(const struct tm *, char *); char *asctime(const struct tm *tm) { static char buf[26]; - return __asctime_r(tm, buf); + return __asctime(tm, buf); } diff --git a/src/unistd/dup2.c b/src/unistd/dup2.c index 88d281e4..b345cf50 100644 --- a/src/unistd/dup2.c +++ b/src/unistd/dup2.c @@ -13,10 +13,10 @@ int dup2(int old, int new) while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); #else if (old==new) { -#if __EMSCRIPTEN__ - r = __syscall(SYS_fcntl, old, F_GETFD); +#ifdef __EMSCRIPTEN__ + r = __wasi_fd_is_valid(old) ? 0 : -1; #else - r = __wasi_fd_is_valid(old); + r = __syscall(SYS_fcntl, old, F_GETFD); #endif if (r >= 0) return old; } else { diff --git a/src/unistd/setxid.c b/src/unistd/setxid.c index dc1377f7..3d1786c4 100644 --- a/src/unistd/setxid.c +++ b/src/unistd/setxid.c @@ -4,6 +4,12 @@ #include "libc.h" #include "pthread_impl.h" +#ifdef __EMSCRIPTEN__ +int __setxid_emscripten() { + errno = EPERM; // we don't allow dynamic syscalls, and don't need to support these anyhow + return -1; +} +#else struct ctx { int id, eid, sid; int nr, err; @@ -13,10 +19,6 @@ static void do_setxid(void *p) { struct ctx *c = p; if (c->err>0) return; -#ifdef __EMSCRIPTEN__ - c->err = EPERM; // we don't allow dynamic syscalls, and don't need to support these anyhow - return; -#else int ret = -__syscall(c->nr, c->id, c->eid, c->sid); if (ret && !c->err) { /* If one thread fails to set ids after another has already @@ -27,7 +29,6 @@ static void do_setxid(void *p) __syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL); } c->err = ret; -#endif } int __setxid(int nr, int id, int eid, int sid) @@ -42,3 +43,4 @@ int __setxid(int nr, int id, int eid, int sid) } return 0; } +#endif diff --git a/src/unistd/usleep.c b/src/unistd/usleep.c index e850a30b..6c966526 100644 --- a/src/unistd/usleep.c +++ b/src/unistd/usleep.c @@ -1,20 +1,12 @@ #define _GNU_SOURCE #include #include -#ifdef __EMSCRTIPEN__ -#include -#endif int usleep(unsigned useconds) { -#ifdef __EMSCRTIPEN__ - emscripten_thread_sleep(usec / 1e3); - return 0; -#else struct timespec tv = { .tv_sec = useconds/1000000, .tv_nsec = (useconds%1000000)*1000 }; return nanosleep(&tv, &tv); -#endif } From ec947a95043c107b07427ee3f6a04a2a8d427cdd Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 4 Nov 2021 15:00:18 -0700 Subject: [PATCH 055/297] Update to emscripten 2.0.34 --- arch/emscripten/bits/syscall.h | 11 ----------- arch/emscripten/syscall_arch.h | 2 -- src/internal/dynlink.h | 13 +++++++++++-- src/unistd/dup2.c | 2 +- src/unistd/faccessat.c | 6 ++++++ 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/arch/emscripten/bits/syscall.h b/arch/emscripten/bits/syscall.h index db2ae6b5..37a442fe 100644 --- a/arch/emscripten/bits/syscall.h +++ b/arch/emscripten/bits/syscall.h @@ -1,6 +1,3 @@ -#define SYS_exit __syscall_exit -#define SYS_read __syscall_read -#define SYS_write __syscall_write #define SYS_open __syscall_open #define SYS_link __syscall_link #define SYS_unlink __syscall_unlink @@ -21,7 +18,6 @@ #define SYS_ioctl __syscall_ioctl #define SYS_setpgid __syscall_setpgid #define SYS_umask __syscall_umask -#define SYS_dup2 __syscall_dup2 #define SYS_getppid __syscall_getppid #define SYS_setsid __syscall_setsid #define SYS_setrlimit __syscall_setrlimit @@ -50,9 +46,6 @@ #define SYS_munlockall __syscall_munlockall #define SYS_mremap __syscall_mremap #define SYS_poll __syscall_poll -#define SYS_rt_sigqueueinfo __syscall_rt_sigqueueinfo -#define SYS_pread64 __syscall_pread64 -#define SYS_pwrite64 __syscall_pwrite64 #define SYS_getcwd __syscall_getcwd #define SYS_ugetrlimit __syscall_ugetrlimit #define SYS_mmap2 __syscall_mmap2 @@ -73,10 +66,8 @@ #define SYS_chown32 __syscall_chown32 #define SYS_mincore __syscall_mincore #define SYS_madvise __syscall_madvise -#define SYS_madvise1 __syscall_madvise1 #define SYS_getdents64 __syscall_getdents64 #define SYS_fcntl64 __syscall_fcntl64 -#define SYS_exit_group __syscall_exit_group #define SYS_statfs64 __syscall_statfs64 #define SYS_fstatfs64 __syscall_fstatfs64 #define SYS_fadvise64_64 __syscall_fadvise64_64 @@ -97,8 +88,6 @@ #define SYS_fallocate __syscall_fallocate #define SYS_dup3 __syscall_dup3 #define SYS_pipe2 __syscall_pipe2 -#define SYS_preadv __syscall_preadv -#define SYS_pwritev __syscall_pwritev #define SYS_recvmmsg __syscall_recvmmsg #define SYS_prlimit64 __syscall_prlimit64 #define SYS_sendmmsg __syscall_sendmmsg diff --git a/arch/emscripten/syscall_arch.h b/arch/emscripten/syscall_arch.h index 69a77e9f..d43a2118 100644 --- a/arch/emscripten/syscall_arch.h +++ b/arch/emscripten/syscall_arch.h @@ -31,7 +31,6 @@ long __syscall_acct(long filename); long __syscall_ioctl(long fd, long request, ...); long __syscall_setpgid(long pid, long gpid); long __syscall_umask(long mask); -long __syscall_dup2(long oldfd, long newfd); long __syscall_getppid(void); long __syscall_getpgrp(void); long __syscall_setsid(void); @@ -62,7 +61,6 @@ long __syscall_mlockall(long flags); long __syscall_munlockall(void); long __syscall_mremap(long old_addr, long old_size, long new_size, long flags, long new_addr); long __syscall_poll(long fds, long nfds, long timeout); -long __syscall_rt_sigqueueinfo(long tgid, long sig, long uinfo); long __syscall_getcwd(long buf, long size); long __syscall_ugetrlimit(long resource, long rlim); long __syscall_mmap2(long addr, long len, long prot, long flags, long fd, long off); diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 736dfd52..5f60bda7 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -16,10 +16,19 @@ struct dso { em_arg_callback_func onerror; void* user_data; - // Flags used to open the library. We need to cache these so that - // (in the future) other threads can mirror the open library state. + // Flags used to open the library. We need to cache these so that other + // threads can mirror the open library state. int flags; + // Location in memory/table of static data/static function addresses + // The first thread to load a given module alloces the memory and table + // address space and then sets this field to non-zero. + uint8_t mem_allocated; + void* mem_addr; + size_t mem_size; + void* table_addr; + size_t table_size; + // Flexible array; must be final element of struct char name[]; }; diff --git a/src/unistd/dup2.c b/src/unistd/dup2.c index b345cf50..793cfba1 100644 --- a/src/unistd/dup2.c +++ b/src/unistd/dup2.c @@ -14,7 +14,7 @@ int dup2(int old, int new) #else if (old==new) { #ifdef __EMSCRIPTEN__ - r = __wasi_fd_is_valid(old) ? 0 : -1; + r = __wasi_fd_is_valid(old) ? 0 : -EBADF; #else r = __syscall(SYS_fcntl, old, F_GETFD); #endif diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c index 33478959..3c310ad4 100644 --- a/src/unistd/faccessat.c +++ b/src/unistd/faccessat.c @@ -5,6 +5,7 @@ #include "syscall.h" #include "pthread_impl.h" +#ifndef __EMSCRIPTEN__ struct ctx { int fd; const char *filename; @@ -30,9 +31,13 @@ static int checker(void *p) for (i=0; i < sizeof errors/sizeof *errors - 1 && ret!=errors[i]; i++); return i; } +#endif int faccessat(int fd, const char *filename, int amode, int flag) { +#ifdef __EMSCRIPTEN__ + return syscall(SYS_faccessat, fd, filename, amode, flag); +#else if (!flag || (flag==AT_EACCESS && getuid()==geteuid() && getgid()==getegid())) return syscall(SYS_faccessat, fd, filename, amode, flag); @@ -60,4 +65,5 @@ int faccessat(int fd, const char *filename, int amode, int flag) __restore_sigs(&set); return __syscall_ret(ret); +#endif } From 8274aaaaa1948c50c661aa32e21b3db27a5c0eab Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 29 Nov 2021 17:41:43 -0500 Subject: [PATCH 056/297] fix hwcap access in powerpc-sf setjmp/longjmp commit 7be59733d71ada3a32a98622507399253f1d5e48 introduced the hwcap-based branches to support the SPE FPU, but wrongly coded them as bitwise tests on the computed address of __hwcap, not a value loaded from that address. replace the add with indexed load to fix it. --- src/setjmp/powerpc/longjmp.S | 2 +- src/setjmp/powerpc/setjmp.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/setjmp/powerpc/longjmp.S b/src/setjmp/powerpc/longjmp.S index 34aecb4c..611389fe 100644 --- a/src/setjmp/powerpc/longjmp.S +++ b/src/setjmp/powerpc/longjmp.S @@ -44,7 +44,7 @@ longjmp: .long __hwcap-. 1: mflr 4 lwz 5, 0(4) - add 4, 4, 5 + lwzx 4, 4, 5 andis. 4, 4, 0x80 beq 1f .long 0x11c35b01 /* evldd 14,88(3) */ diff --git a/src/setjmp/powerpc/setjmp.S b/src/setjmp/powerpc/setjmp.S index 413e6a81..f1fcce33 100644 --- a/src/setjmp/powerpc/setjmp.S +++ b/src/setjmp/powerpc/setjmp.S @@ -44,7 +44,7 @@ setjmp: .long __hwcap-. 1: mflr 4 lwz 5, 0(4) - add 4, 4, 5 + lwzx 4, 4, 5 andis. 4, 4, 0x80 beq 1f .long 0x11c35b21 /* evstdd 14,88(3) */ From 98e688a9da5e7b2925dda17a2d6820dddf1fb287 Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Sun, 15 Aug 2021 17:51:57 +0200 Subject: [PATCH 057/297] define NULL as nullptr when used in C++11 or later This should be safer for casting and more compatible with existing code bases that wrongly assume it must be defined as a pointer. --- include/locale.h | 4 +++- include/stddef.h | 4 +++- include/stdio.h | 4 +++- include/stdlib.h | 4 +++- include/string.h | 4 +++- include/time.h | 4 +++- include/unistd.h | 4 +++- include/wchar.h | 4 +++- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/include/locale.h b/include/locale.h index ce384381..11106fea 100644 --- a/include/locale.h +++ b/include/locale.h @@ -7,7 +7,9 @@ extern "C" { #include -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/stddef.h b/include/stddef.h index bd753853..f25b8639 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -1,7 +1,9 @@ #ifndef _STDDEF_H #define _STDDEF_H -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/stdio.h b/include/stdio.h index 3604198c..d1ed01f0 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -25,7 +25,9 @@ extern "C" { #include -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/stdlib.h b/include/stdlib.h index 7af86e3b..b507ca33 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -7,7 +7,9 @@ extern "C" { #include -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/string.h b/include/string.h index 795a2abc..43ad0942 100644 --- a/include/string.h +++ b/include/string.h @@ -7,7 +7,9 @@ extern "C" { #include -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/time.h b/include/time.h index 5494df18..3d948372 100644 --- a/include/time.h +++ b/include/time.h @@ -7,7 +7,9 @@ extern "C" { #include -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/unistd.h b/include/unistd.h index 13064026..ee2dbe8a 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -15,7 +15,9 @@ extern "C" { #define SEEK_CUR 1 #define SEEK_END 2 -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/wchar.h b/include/wchar.h index 88eb55b1..ed5d774d 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -38,7 +38,9 @@ extern "C" { #define WCHAR_MIN (-1-0x7fffffff+L'\0') #endif -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) From 8d404733e1314ef633aa09a90865e94fe711b4ca Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 9 Dec 2021 15:35:13 -0500 Subject: [PATCH 058/297] fix mismatched signatures for strtod_l family strtod_l, strtof_l, and strtold_l originally existed only as glibc-ABI-compat symbols. as noted in the commit which added them, 17a60f9d327c6f8b5707a06f9497d846e75c01f2, making them aliases for the non-_l functions was a hack and not appropriate if they ever became public API. unfortunately, commit 35eb1a1a9b97577e113240cd65bf9fc44b8df030 did make them public without undoing the hack. fix that now by moving the the _l functions to their own file as wrappers that just throw away the locale_t argument. --- src/locale/strtod_l.c | 22 ++++++++++++++++++++++ src/stdlib/strtod.c | 7 ------- 2 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 src/locale/strtod_l.c diff --git a/src/locale/strtod_l.c b/src/locale/strtod_l.c new file mode 100644 index 00000000..574ba148 --- /dev/null +++ b/src/locale/strtod_l.c @@ -0,0 +1,22 @@ +#define _GNU_SOURCE +#include +#include + +float strtof_l(const char *restrict s, char **restrict p, locale_t l) +{ + return strtof(s, p); +} + +double strtod_l(const char *restrict s, char **restrict p, locale_t l) +{ + return strtod(s, p); +} + +long double strtold_l(const char *restrict s, char **restrict p, locale_t l) +{ + return strtold(s, p); +} + +weak_alias(strtof_l, __strtof_l); +weak_alias(strtod_l, __strtod_l); +weak_alias(strtold_l, __strtold_l); diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c index a5d0118a..39b9daad 100644 --- a/src/stdlib/strtod.c +++ b/src/stdlib/strtod.c @@ -28,10 +28,3 @@ long double strtold(const char *restrict s, char **restrict p) { return strtox(s, p, 2); } - -weak_alias(strtof, strtof_l); -weak_alias(strtod, strtod_l); -weak_alias(strtold, strtold_l); -weak_alias(strtof, __strtof_l); -weak_alias(strtod, __strtod_l); -weak_alias(strtold, __strtold_l); From 775bde6b5c04ecc689ecbb4a25ceaf2ed6ab60c8 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 27 Dec 2021 20:08:31 -0500 Subject: [PATCH 059/297] fix wcwidth of hangul combining (vowel/final) letters these characters combine onto a base character (initial) and therefore need to have width 0. the original binary-search implementation of wcwidth handled them correctly, but a regression was introduced in commit 1b0ce9af6d2aa7b92edaf3e9c631cb635bae22bd by generating the new tables from unicode without noticing that the classification logic in use (unicode character category Mn/Me/Cf) was insufficient to catch these characters. --- src/ctype/nonspacing.h | 118 +++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/src/ctype/nonspacing.h b/src/ctype/nonspacing.h index 5d05a3d1..7746f3b6 100644 --- a/src/ctype/nonspacing.h +++ b/src/ctype/nonspacing.h @@ -1,23 +1,23 @@ -16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,16,16,32,16,16,16,33,34,35, -36,37,38,39,16,16,40,16,16,16,16,16,16,16,16,16,16,16,41,42,16,16,43,16,16,16, +16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,16,33,16,16,16,34,35,36, +37,38,39,40,16,16,41,16,16,16,16,16,16,16,16,16,16,16,42,43,16,16,44,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,16,16,16,44,16,45,46,47,48,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,16,16,16,45,16,46,47,48,49,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,50,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,51,16,16,52, +53,16,54,55,56,16,16,16,16,16,16,57,16,16,58,16,59,60,61,62,63,64,65,66,67,68, +69,70,16,71,72,73,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,74,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,49,16,16,50, -51,16,52,53,54,16,16,16,16,16,16,55,16,16,56,16,57,58,59,60,61,62,63,64,65,66, -67,68,16,69,70,71,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,72,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,75,76,16,16,16,77,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,73,74,16,16,16,75,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,76,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,77,78,16,16,16,16,16,16,16,79,16,16,16,16,16,80,81,82,16,16,16,16,16,83, -84,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,78,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,79,80,16,16,16,16,16,16,16,81,16,16,16,16,16,82,83,84,16,16,16,16,16,85, +86,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, @@ -35,55 +35,57 @@ 242,7,128,127,0,0,0,0,0,0,0,0,0,0,0,0,242,31,0,63,0,0,0,0,0,0,0,0,0,3,0,0,160, 2,0,0,0,0,0,0,254,127,223,224,255,254,255,255,255,31,64,0,0,0,0,0,0,0,0,0,0,0, 0,224,253,102,0,0,0,195,1,0,30,0,100,32,0,32,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0, -0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254,15,32,0,0,0,0,0,120,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,1,4,14,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,9,0,0,0,0,0,0,64,127, -229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0,15,0,0,0,0,0,208,23,4,0,0, -0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0,0,0,0,0,240,207,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255, +0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,28,0,0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254, +15,32,0,0,0,0,0,120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,135,1,4,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +128,9,0,0,0,0,0,0,64,127,229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0, +15,0,0,0,0,0,208,23,4,0,0,0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0, +0,0,0,0,240,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255, 251,0,248,0,0,0,124,0,0,0,0,0,0,223,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255, 255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0, 0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,128,247,63,0,0,0,192,0,0,0,0,0,0,0,0,0,0,3,0,68,8,0,0,96,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,255,255,3,128,0,0,0,0,192,63,0,0,128,255,3,0, -0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0,0,0,0,0,0,0,126,102,0,8,16,0,0,0,0, -0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,33,0,0,0,0,0,64, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255,255,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,110,240,0,0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0, -0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,192,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255, -127,0,0,0,0,0,0,128,3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0, -0,0,0,0,0,0,8,0,3,0,0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192, -31,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0, -0,0,0,0,0,248,133,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,60,176,1,0,0,48,0,0,0, -0,0,0,0,0,0,0,248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0, -0,224,188,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -128,255,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0, -126,14,0,0,0,0,0,252,127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0, -0,0,0,0,0,0,0,252,255,255,252,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,180,191,0, -0,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,24, -0,0,0,0,0,0,0,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,127,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0, -0,128,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,15, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,255,255,255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248, -254,255,0,0,0,0,0,0,0,0,0, -0,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0, +0,0,0,0,0,0,126,102,0,8,16,0,0,0,0,0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,33,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,0,0,0, +64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255, +255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,240,0, +0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,240,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,255,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255,127,0,0,0,0,0,0,128, +3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0,0,0,0,0,0,0,8,0,3,0, +0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192,31,31,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0,0,0,0,0,0,248,133,13,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,176,1,0,0,48,0,0,0,0,0,0,0,0,0,0, +248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0,0,224,188,15,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,255,6,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0,126,14,0,0,0,0,0,252, +127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0,0,0,0,0,0,0,0,252,255, +255,252,109,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,126,180,191,0,0,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,255, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,128,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,15,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, +255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248,254,255,0,0,0, +0,0,0,0,0,0,0,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, From c4d4028dde90562f631edf559fbc42d8ec1b29de Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 21 Oct 2021 16:09:30 +0000 Subject: [PATCH 060/297] fix failure to use add-cfi scripts on asm when building out-of-tree use $srcdir in configure test for add-cfi script. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index e1aefed7..ca5cbc0b 100755 --- a/configure +++ b/configure @@ -409,7 +409,7 @@ test "$debug" = yes && CFLAGS_AUTO=-g # printf "checking whether we should preprocess assembly to add debugging information... " if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" && - test -f "tools/add-cfi.$ARCH.awk" && + test -f "$srcdir/tools/add-cfi.$ARCH.awk" && printf ".file 1 \"srcfile.s\"\n.line 1\n.cfi_startproc\n.cfi_endproc" | $CC -g -x assembler -c -o /dev/null 2>/dev/null - then ADD_CFI=yes From cbacd638e32a02edbe66c48ae3d1361bc06a492a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira?= Date: Fri, 17 Dec 2021 04:59:43 -0300 Subject: [PATCH 061/297] add SEEK_DATA and SEEK_HOLE to unistd.h these are linux specific constants. glibc exposes them behind _GNU_SOURCE, but, since SEEK_* is reserved for the implementation, we can simply define them. furthermore, since they can't be used with fseek() and other functions that deal with FILE, we don't add them to stdio.h. --- include/unistd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/unistd.h b/include/unistd.h index ee2dbe8a..212263a7 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -14,6 +14,8 @@ extern "C" { #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 +#define SEEK_DATA 3 +#define SEEK_HOLE 4 #if __cplusplus >= 201103L #define NULL nullptr From 52f0deb96975401d9f13334dc37f907630224af7 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 9 Jan 2022 00:33:56 -0500 Subject: [PATCH 062/297] make fseek detect and produce an error for invalid whence arguments this is a POSIX requirement. we previously relied on the underlying fd (or other backend) seek operation to produce the error, but since linux lseek now supports other seek modes (SEEK_DATA and SEEK_HOLE) which do not interact well with stdio buffering, this is insufficient. instead, explicitly check whence before performing any operations. --- src/stdio/fseek.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c index 439308f7..c07f7e95 100644 --- a/src/stdio/fseek.c +++ b/src/stdio/fseek.c @@ -1,7 +1,14 @@ #include "stdio_impl.h" +#include int __fseeko_unlocked(FILE *f, off_t off, int whence) { + /* Fail immediately for invalid whence argument. */ + if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END) { + errno = EINVAL; + return -1; + } + /* Adjust relative offset for unread data in buffer, if any. */ if (whence == SEEK_CUR && f->rend) off -= f->rend - f->rpos; From 75b3412f3dbda8f1fc6818b8b0cf1d0737c2163c Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 18 Jan 2022 17:31:46 -0500 Subject: [PATCH 063/297] fix potentially wrong-sign zero in cproj functions at infinity these are specified to use the sign of the imaginary part of the input as the sign of zero in the result, but wrongly copied the sign of the real part. --- src/complex/cproj.c | 2 +- src/complex/cprojf.c | 2 +- src/complex/cprojl.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/complex/cproj.c b/src/complex/cproj.c index 9ae1e17c..d2b8f5a9 100644 --- a/src/complex/cproj.c +++ b/src/complex/cproj.c @@ -3,6 +3,6 @@ double complex cproj(double complex z) { if (isinf(creal(z)) || isinf(cimag(z))) - return CMPLX(INFINITY, copysign(0.0, creal(z))); + return CMPLX(INFINITY, copysign(0.0, cimag(z))); return z; } diff --git a/src/complex/cprojf.c b/src/complex/cprojf.c index 03fab339..15a874bb 100644 --- a/src/complex/cprojf.c +++ b/src/complex/cprojf.c @@ -3,6 +3,6 @@ float complex cprojf(float complex z) { if (isinf(crealf(z)) || isinf(cimagf(z))) - return CMPLXF(INFINITY, copysignf(0.0, crealf(z))); + return CMPLXF(INFINITY, copysignf(0.0, cimagf(z))); return z; } diff --git a/src/complex/cprojl.c b/src/complex/cprojl.c index 38a494c5..531ffa1c 100644 --- a/src/complex/cprojl.c +++ b/src/complex/cprojl.c @@ -9,7 +9,7 @@ long double complex cprojl(long double complex z) long double complex cprojl(long double complex z) { if (isinf(creall(z)) || isinf(cimagl(z))) - return CMPLXL(INFINITY, copysignl(0.0, creall(z))); + return CMPLXL(INFINITY, copysignl(0.0, cimagl(z))); return z; } #endif From 3b7b4155570b4b9054465785be2992c92cb7d7b1 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 9 Feb 2022 17:48:43 -0500 Subject: [PATCH 064/297] fix out-of-bound read processing time zone data with distant-past dates this bug goes back to commit 1cc81f5cb0df2b66a795ff0c26d7bbc4d16e13c6 where zoneinfo file support was first added. in scan_trans, which searches for the appropriate local time/dst rule in effect at a given time, times prior to the second transition time caused the -1 slot of the index to be read to determine the previous rule in effect. this memory was always valid (part of another zoneinfo table in the mapped file) but the byte value read was then used to index another table, possibly going outside the bounds of the mmap. most of the time, the result was limited to misinterpretation of the rule in effect at that time (pre-1900s), but it could produce a crash if adjacent memory was not readable. the root cause of the problem, however, was that the logic for this code path was all wrong. as documented in the comment, times before the first transition should be treated as using the lowest-numbered non-dst rule, or rule 0 if no non-dst rules exist. if the argument is in units of local time, however, the rule prior to the first transition is needed to determine if it falls before or after it, and that's where the -1 index was wrongly used. instead, use the documented logic to find out what rule would be in effect before the first transition, and apply it as the offset if the argument was given in local time. the new code has not been heavily tested, but no longer performs potentially out-of-bounds accesses, and successfully handles the 1883 transition from local mean time to central standard time in the test case the error was reported for. --- src/time/__tz.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/time/__tz.c b/src/time/__tz.c index 3e2fcdcb..c34b3eb7 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -293,22 +293,20 @@ static size_t scan_trans(long long t, int local, size_t *alt) n = (index-trans)>>scale; if (a == n-1) return -1; if (a == 0) { - x = zi_read32(trans + (a< Date: Wed, 16 Feb 2022 23:06:17 +0000 Subject: [PATCH 065/297] add missing strerror text for key management --- src/errno/__strerror.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h index 2d992da5..14925907 100644 --- a/src/errno/__strerror.h +++ b/src/errno/__strerror.h @@ -102,3 +102,7 @@ E(EDQUOT, "Quota exceeded") E(ENOMEDIUM, "No medium found") E(EMEDIUMTYPE, "Wrong medium type") E(EMULTIHOP, "Multihop attempted") +E(ENOKEY, "Required key not available") +E(EKEYEXPIRED, "Key has expired") +E(EKEYREVOKED, "Key has been revoked") +E(EKEYREJECTED, "Key was rejected by service") From f8bdc3048216f41eaaf655524fa286cfb1184a70 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 20 Feb 2022 20:11:14 -0500 Subject: [PATCH 066/297] fix spurious failures by fgetws when buffer ends with partial character commit a90d9da1d1b14d81c4f93e1a6d1a686c3312e4ba made fgetws look for changes to errno by fgetwc to detect encoding errors, since ISO C did not allow the implementation to set the stream's error flag in this case, and the fgetwc interface did not admit any other way to detect the error. however, the possibility of fgetwc setting errno to EILSEQ in the success path was overlooked, and in fact this can happen if the buffer ends with a partial character, causing mbtowc to be called with only part of the character available. since that change was made, the C standard was amended to specify that fgetwc set the stream error flag on encoding errors, and commit 511d70738bce11a67219d0132ce725c323d00e4e made it do so. thus, there is no longer any need for fgetws to poke at errno to handle encoding errors. this commit reverts commit a90d9da1d1b14d81c4f93e1a6d1a686c3312e4ba and thereby fixes the problem. --- src/stdio/fgetws.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/stdio/fgetws.c b/src/stdio/fgetws.c index b08b3049..195cb435 100644 --- a/src/stdio/fgetws.c +++ b/src/stdio/fgetws.c @@ -1,6 +1,5 @@ #include "stdio_impl.h" #include -#include wint_t __fgetwc_unlocked(FILE *); @@ -12,10 +11,6 @@ wchar_t *fgetws(wchar_t *restrict s, int n, FILE *restrict f) FLOCK(f); - /* Setup a dummy errno so we can detect EILSEQ. This is - * the only way to catch encoding errors in the form of a - * partial character just before EOF. */ - errno = EAGAIN; for (; n; n--) { wint_t c = __fgetwc_unlocked(f); if (c == WEOF) break; @@ -23,7 +18,7 @@ wchar_t *fgetws(wchar_t *restrict s, int n, FILE *restrict f) if (c == '\n') break; } *p = 0; - if (ferror(f) || errno==EILSEQ) p = s; + if (ferror(f)) p = s; FUNLOCK(f); From 7c0c7a75ec8ecf3eedefc40bb4dae5aaa76d7108 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 4 Feb 2022 21:04:45 +0100 Subject: [PATCH 067/297] math: avoid runtime conversions of floating-point constants gcc-12 with -frounding-mode will do inexact constant conversions at runtime according to the runtime rounding mode. in the math library we want constants to be rounding mode independent so this patch fixes cases where new runtime conversions happen with gcc-12. fortunately this only affects two minor cases, the fix uses global initializers where rounding mode does not apply. after the patch the same amount of conversions happen with gcc-12 as with gcc-11. --- src/complex/cacosf.c | 4 +++- src/complex/catanf.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/complex/cacosf.c b/src/complex/cacosf.c index 2e048540..ed8acf0f 100644 --- a/src/complex/cacosf.c +++ b/src/complex/cacosf.c @@ -2,8 +2,10 @@ // FIXME +static const float float_pi_2 = M_PI_2; + float complex cacosf(float complex z) { z = casinf(z); - return CMPLXF((float)M_PI_2 - crealf(z), -cimagf(z)); + return CMPLXF(float_pi_2 - crealf(z), -cimagf(z)); } diff --git a/src/complex/catanf.c b/src/complex/catanf.c index ef3907a5..1d569f2d 100644 --- a/src/complex/catanf.c +++ b/src/complex/catanf.c @@ -61,13 +61,15 @@ static const double DP1 = 3.140625; static const double DP2 = 9.67502593994140625E-4; static const double DP3 = 1.509957990978376432E-7; +static const float float_pi = M_PI; + static float _redupif(float xx) { float x, t; long i; x = xx; - t = x/(float)M_PI; + t = x/float_pi; if (t >= 0.0f) t += 0.5f; else From 74a28a8af21977ebbc2945beb879f1b9b6ff13ba Mon Sep 17 00:00:00 2001 From: jvoisin Date: Mon, 13 Dec 2021 21:05:19 +0100 Subject: [PATCH 068/297] protect stack canary from leak via read-as-string by zeroing second byte This reduces entropy of the canary from 64-bit to 56-bit in exchange for mitigating non-terminated C string overflows by setting the second byte of the canary to nul, so that off-by-one write overflow with a nul byte can still be detected. Idea from GrapheneOS bionic commit 7024d880b51f03a796ff8832f1298f2f1531fd7b --- src/env/__stack_chk_fail.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/env/__stack_chk_fail.c b/src/env/__stack_chk_fail.c index bf5a280a..e5352602 100644 --- a/src/env/__stack_chk_fail.c +++ b/src/env/__stack_chk_fail.c @@ -9,6 +9,15 @@ void __init_ssp(void *entropy) if (entropy) memcpy(&__stack_chk_guard, entropy, sizeof(uintptr_t)); else __stack_chk_guard = (uintptr_t)&__stack_chk_guard * 1103515245; +#if UINTPTR_MAX >= 0xffffffffffffffff + /* Sacrifice 8 bits of entropy on 64bit to prevent leaking/ + * overwriting the canary via string-manipulation functions. + * The NULL byte is on the second byte so that off-by-ones can + * still be detected. Endianness is taken care of + * automatically. */ + ((char *)&__stack_chk_guard)[1] = 0; +#endif + __pthread_self()->canary = __stack_chk_guard; } From 3aba2150d0efc80df30d7fc6c22d6041e14d445e Mon Sep 17 00:00:00 2001 From: Alexey Kodanev Date: Tue, 29 Jun 2021 16:31:30 +0300 Subject: [PATCH 069/297] nice: return EPERM instead of EACCES To comply with POSIX, change errno from EACCES to EPERM when the caller did not have the required privilege. --- src/unistd/nice.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/unistd/nice.c b/src/unistd/nice.c index 6c25c8c3..1c2295ff 100644 --- a/src/unistd/nice.c +++ b/src/unistd/nice.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "syscall.h" @@ -12,5 +13,11 @@ int nice(int inc) prio += getpriority(PRIO_PROCESS, 0); if (prio > NZERO-1) prio = NZERO-1; if (prio < -NZERO) prio = -NZERO; - return setpriority(PRIO_PROCESS, 0, prio) ? -1 : prio; + if (setpriority(PRIO_PROCESS, 0, prio)) { + if (errno == EACCES) + errno = EPERM; + return -1; + } else { + return prio; + } } From b21f3ded780cc8fd8e510c99aeaf4a453d8c8a22 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 7 Mar 2021 19:21:34 +0000 Subject: [PATCH 070/297] bits/syscall.h: add epoll_pwait2 from linux v5.11 see linux commit b0a0c2615f6f199a656ed8549d7dce625d77aa77 epoll: wire up syscall epoll_pwait2 linux commit 58169a52ebc9a733aeb5bea857bc5daa71a301bb epoll: add syscall epoll_pwait2 epoll_wait with struct timespec timeout instead of int. no time32 variant. --- arch/aarch64/bits/syscall.h.in | 1 + arch/arm/bits/syscall.h.in | 1 + arch/i386/bits/syscall.h.in | 1 + arch/m68k/bits/syscall.h.in | 1 + arch/microblaze/bits/syscall.h.in | 1 + arch/mips/bits/syscall.h.in | 1 + arch/mips64/bits/syscall.h.in | 1 + arch/mipsn32/bits/syscall.h.in | 1 + arch/or1k/bits/syscall.h.in | 1 + arch/powerpc/bits/syscall.h.in | 1 + arch/powerpc64/bits/syscall.h.in | 1 + arch/riscv64/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/sh/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 16 files changed, 16 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index 1ad467c0..e955da4d 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -294,4 +294,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index cf9e3411..2a55d4db 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -394,6 +394,7 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index 5d1c4d7a..f900db2e 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -431,4 +431,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index 6794b1a0..e064b445 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -411,3 +411,4 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index 7f71df3b..86fe8271 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -432,4 +432,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index d54845b2..83c9655d 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -413,4 +413,5 @@ #define __NR_pidfd_getfd 4438 #define __NR_faccessat2 4439 #define __NR_process_madvise 4440 +#define __NR_epoll_pwait2 4441 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index 920b4358..1be9f3e1 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -343,4 +343,5 @@ #define __NR_pidfd_getfd 5438 #define __NR_faccessat2 5439 #define __NR_process_madvise 5440 +#define __NR_epoll_pwait2 5441 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index e6dad688..1bd7aeb2 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -367,4 +367,5 @@ #define __NR_pidfd_getfd 6438 #define __NR_faccessat2 6439 #define __NR_process_madvise 6440 +#define __NR_epoll_pwait2 6441 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index 463ee901..499aa832 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -316,4 +316,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index db4d0ca4..7f7d5a11 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -420,4 +420,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index a128890b..b5793172 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -392,4 +392,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index 39c0d650..df6bf5c2 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -294,6 +294,7 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index 9c8d984e..16ec02ee 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -357,4 +357,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index 17dd7e07..4fc1f9e8 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -404,4 +404,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index 5361442e..14c7231f 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -303,6 +303,7 @@ #define __NR_pidfd_getfd (0x40000000 + 438) #define __NR_faccessat2 (0x40000000 + 439) #define __NR_process_madvise (0x40000000 + 440) +#define __NR_epoll_pwait2 (0x40000000 + 441) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index e943883d..f611884e 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -350,4 +350,5 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 From f35b99b38721c0e76152069254b642dd345da784 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 7 Mar 2021 20:50:17 +0000 Subject: [PATCH 071/297] sys/prctl.h: add PR_SET_SYSCALL_USER_DISPATCH from linux v5.11 see linux commit 1446e1df9eb183fdf81c3f0715402f1d7595d4cb kernel: Implement selective syscall userspace redirection linux commit 36a6c843fd0d8e02506681577e96dabd203dd8e8 entry: Use different define for selector variable in SUD redirect syscalls to a userspace handler via SIGSYS, except for a specific range of code. can be toggled via a memory write to a selector variable. mainly for wine. --- include/sys/prctl.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/sys/prctl.h b/include/sys/prctl.h index 4ba73f42..3f0254c7 100644 --- a/include/sys/prctl.h +++ b/include/sys/prctl.h @@ -168,6 +168,12 @@ struct prctl_mm_map { #define PR_SET_IO_FLUSHER 57 #define PR_GET_IO_FLUSHER 58 +#define PR_SET_SYSCALL_USER_DISPATCH 59 +#define PR_SYS_DISPATCH_OFF 0 +#define PR_SYS_DISPATCH_ON 1 +#define SYSCALL_DISPATCH_FILTER_ALLOW 0 +#define SYSCALL_DISPATCH_FILTER_BLOCK 1 + int prctl (int, ...); #ifdef __cplusplus From c5ecaca743e4d6c1be7e3fd91dee62e560acb7e2 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 7 Mar 2021 21:19:36 +0000 Subject: [PATCH 072/297] sys/socket.h: add new SO_ socket options from linux v5.11 see linux commit 7fd3253a7de6a317a0683f83739479fb880bffc8 net: Introduce preferred busy-polling linux commit 7c951cafc0cb2e575f1d58677b95ac387ac0a5bd net: Add SO_BUSY_POLL_BUDGET socket option --- include/sys/socket.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sys/socket.h b/include/sys/socket.h index 38f5bb17..6dc1e40a 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -289,6 +289,8 @@ struct linger { #define SCM_TXTIME SO_TXTIME #define SO_BINDTOIFINDEX 62 #define SO_DETACH_REUSEPORT_BPF 68 +#define SO_PREFER_BUSY_POLL 69 +#define SO_BUSY_POLL_BUDGET 70 #ifndef SOL_SOCKET #define SOL_SOCKET 1 From b54f481fbcc5637226fc3d2e0404b7f95b3e2f14 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 7 Mar 2021 21:33:25 +0000 Subject: [PATCH 073/297] netinet/if_ether.h: add ETH_P_CFM from linux v5.11 see linux commit fbaedb4129838252570410c65abb2036b5505cbd bridge: uapi: cfm: Added EtherType used by the CFM protocol. --- include/netinet/if_ether.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/netinet/if_ether.h b/include/netinet/if_ether.h index 55a2ff1b..3479f511 100644 --- a/include/netinet/if_ether.h +++ b/include/netinet/if_ether.h @@ -66,6 +66,7 @@ #define ETH_P_1588 0x88F7 #define ETH_P_NCSI 0x88F8 #define ETH_P_PRP 0x88FB +#define ETH_P_CFM 0x8902 #define ETH_P_FCOE 0x8906 #define ETH_P_TDLS 0x890D #define ETH_P_FIP 0x8914 From 30c8a1456ab7a005360f5315ba96f8073593ab51 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 7 Mar 2021 21:39:24 +0000 Subject: [PATCH 074/297] netinet/tcp.h: add tcp zerocopy related changes from linux v5.11 see linux commit 18fb76ed53865c1b5d5f0157b1b825704590beb5 net-zerocopy: Copy straggler unaligned data for TCP Rx. zerocopy. linux commit 94ab9eb9b234ddf23af04a4bc7e8db68e67b8778 net-zerocopy: Defer vm zap unless actually needed. --- include/netinet/tcp.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h index b7b997f5..30f20239 100644 --- a/include/netinet/tcp.h +++ b/include/netinet/tcp.h @@ -281,12 +281,17 @@ struct tcp_repair_window { uint32_t rcv_wup; }; +#define TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT 0x1 + struct tcp_zerocopy_receive { uint64_t address; uint32_t length; uint32_t recv_skip_hint; uint32_t inq; int32_t err; + uint64_t copybuf_address; + int32_t copybuf_len; + uint32_t flags; }; #endif From 3dcbd896907d9d474da811b7c6b769342abaf651 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 7 Mar 2021 22:15:11 +0000 Subject: [PATCH 075/297] signal.h: add si_code values for SIGSYS unlike other si_code defines, SYS_ is not in the posix reserved namespace which is likely the reason why SYS_SECCOMP was previously missing (was new in linux v3.5). --- include/signal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/signal.h b/include/signal.h index f270a594..4dd46142 100644 --- a/include/signal.h +++ b/include/signal.h @@ -261,6 +261,8 @@ void (*sigset(int, void (*)(int)))(int); #if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) #define NSIG _NSIG typedef void (*sig_t)(int); + +#define SYS_SECCOMP 1 #endif #ifdef _GNU_SOURCE From 993cccce13ba3ae0432cb06eacd2e7f55a090952 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 7 Mar 2021 22:20:54 +0000 Subject: [PATCH 076/297] signal.h: add SYS_USER_DISPATCH si_code value from linux v5.11 see linux commit 1d7637d89cfce54a4f4a41c2325288c2f47470e8 signal: Expose SYS_USER_DISPATCH si_code type --- include/signal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/signal.h b/include/signal.h index 4dd46142..af940ccb 100644 --- a/include/signal.h +++ b/include/signal.h @@ -263,6 +263,7 @@ void (*sigset(int, void (*)(int)))(int); typedef void (*sig_t)(int); #define SYS_SECCOMP 1 +#define SYS_USER_DISPATCH 2 #endif #ifdef _GNU_SOURCE From e99c4258275507c576d7d5bebdba1a8aadf120c4 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Wed, 17 Mar 2021 19:19:27 +0000 Subject: [PATCH 077/297] signal.h: add new sa_flags from linux v5.11 see linux commit a54f0dfda754c5cecc89a14dab68a3edc1e497b5 signal: define the SA_UNSUPPORTED bit in sa_flags linux commit 6ac05e832a9e96f9b1c42a8917cdd317d7b6c8fa signal: define the SA_EXPOSE_TAGBITS bit in sa_flags Note: SA_ is in the posix reserved namespace so these linux specific flags can be exposed when compiling for posix. --- include/signal.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/signal.h b/include/signal.h index af940ccb..c347f861 100644 --- a/include/signal.h +++ b/include/signal.h @@ -178,6 +178,9 @@ struct sigaction { #define sa_handler __sa_handler.sa_handler #define sa_sigaction __sa_handler.sa_sigaction +#define SA_UNSUPPORTED 0x00000400 +#define SA_EXPOSE_TAGBITS 0x00000800 + struct sigevent { union sigval sigev_value; int sigev_signo; From f7d3db5bfc4c3b2315dd8c3137f0f332e1c6896a Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Tue, 25 May 2021 20:53:18 +0000 Subject: [PATCH 078/297] bits/syscall.h: add mount_setattr from linux v5.12 new syscall to change the properties of a mount or a mount tree using file descriptors which the new mount api is based on, see linux commit 2a1867219c7b27f928e2545782b86daaf9ad50bd fs: add mount_setattr() --- arch/aarch64/bits/syscall.h.in | 1 + arch/arm/bits/syscall.h.in | 1 + arch/i386/bits/syscall.h.in | 1 + arch/m68k/bits/syscall.h.in | 1 + arch/microblaze/bits/syscall.h.in | 1 + arch/mips/bits/syscall.h.in | 1 + arch/mips64/bits/syscall.h.in | 1 + arch/mipsn32/bits/syscall.h.in | 1 + arch/or1k/bits/syscall.h.in | 1 + arch/powerpc/bits/syscall.h.in | 1 + arch/powerpc64/bits/syscall.h.in | 1 + arch/riscv64/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/sh/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 16 files changed, 16 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index e955da4d..037da214 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -295,4 +295,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index 2a55d4db..8919137f 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -395,6 +395,7 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index f900db2e..4c04ea89 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -432,4 +432,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index e064b445..136775b4 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -412,3 +412,4 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index 86fe8271..10f27aba 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -433,4 +433,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index 83c9655d..1d0deed3 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -414,4 +414,5 @@ #define __NR_faccessat2 4439 #define __NR_process_madvise 4440 #define __NR_epoll_pwait2 4441 +#define __NR_mount_setattr 4442 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index 1be9f3e1..b1b83f5f 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -344,4 +344,5 @@ #define __NR_faccessat2 5439 #define __NR_process_madvise 5440 #define __NR_epoll_pwait2 5441 +#define __NR_mount_setattr 5442 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index 1bd7aeb2..bfaa080e 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -368,4 +368,5 @@ #define __NR_faccessat2 6439 #define __NR_process_madvise 6440 #define __NR_epoll_pwait2 6441 +#define __NR_mount_setattr 6442 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index 499aa832..3c60eda9 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -317,4 +317,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index 7f7d5a11..33e26e4b 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -421,4 +421,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index b5793172..38bb23cb 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -393,4 +393,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index df6bf5c2..a9cbfb50 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -295,6 +295,7 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index 16ec02ee..88de5148 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -358,4 +358,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index 4fc1f9e8..1a900264 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -405,4 +405,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index 14c7231f..d90cb157 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -304,6 +304,7 @@ #define __NR_faccessat2 (0x40000000 + 439) #define __NR_process_madvise (0x40000000 + 440) #define __NR_epoll_pwait2 (0x40000000 + 441) +#define __NR_mount_setattr (0x40000000 + 442) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index f611884e..634e29fd 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -351,4 +351,5 @@ #define __NR_faccessat2 439 #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 From 9ffd145479c53b5eb0940dc6c3d09c060d7f3273 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Tue, 25 May 2021 21:16:43 +0000 Subject: [PATCH 079/297] s390x: add ptrace requests from linux v5.12 PTRACE_OLDSETOPTIONS is old, but it was missing, PTRACE_SYSEMU and PTRACE_SYSEMU_SINGLESTEP are new, see linux commit 56e62a73702836017564eaacd5212e4d0fa1c01d s390: convert to generic entry --- arch/s390x/bits/ptrace.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390x/bits/ptrace.h b/arch/s390x/bits/ptrace.h index d50e3262..a06cb077 100644 --- a/arch/s390x/bits/ptrace.h +++ b/arch/s390x/bits/ptrace.h @@ -1,4 +1,7 @@ #define PTRACE_SINGLEBLOCK 12 +#define PTRACE_OLDSETOPTIONS 21 +#define PTRACE_SYSEMU 31 +#define PTRACE_SYSEMU_SINGLESTEP 32 #define PTRACE_PEEKUSR_AREA 0x5000 #define PTRACE_POKEUSR_AREA 0x5001 #define PTRACE_GET_LAST_BREAK 0x5006 From bc89c311120111de330c99335d3139ff55fae1fe Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Wed, 26 May 2021 16:04:38 +0000 Subject: [PATCH 080/297] netinet/tcp.h: add TCP_NLA_* values up to linux v5.12 TCP_NLA_EDT was new in v5.9, see linux commit 48040793fa6003d211f021c6ad273477bcd90d91 tcp: add earliest departure time to SCM_TIMESTAMPING_OPT_STATS TCP_NLA_TTL is new in v5.12, see linux commit e7ed11ee945438b737e2ae2370e35591e16ec371 tcp: add TTL to SCM_TIMESTAMPING_OPT_STATS --- include/netinet/tcp.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h index 30f20239..08ed7cc2 100644 --- a/include/netinet/tcp.h +++ b/include/netinet/tcp.h @@ -80,6 +80,8 @@ enum { TCP_NLA_SRTT, TCP_NLA_TIMEOUT_REHASH, TCP_NLA_BYTES_NOTSENT, + TCP_NLA_EDT, + TCP_NLA_TTL, }; #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) From 1ee8109ea01c4ac79e7932a533fead96309f80f3 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Wed, 26 May 2021 16:01:38 +0000 Subject: [PATCH 081/297] netinet/tcp.h: add tcp_zerocopy_receive fields from linux v5.12 see linux commit 7eeba1706eba6def15f6cb2fc7b3c3b9a2651edc tcp: Add receive timestamp support for receive zerocopy. linux commit 3c5a2fd042d0bfac71a2dfb99515723d318df47b tcp: Sanitize CMSG flags and reserved args in tcp_zerocopy_receive. --- include/netinet/tcp.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h index 08ed7cc2..fad1d844 100644 --- a/include/netinet/tcp.h +++ b/include/netinet/tcp.h @@ -294,6 +294,10 @@ struct tcp_zerocopy_receive { uint64_t copybuf_address; int32_t copybuf_len; uint32_t flags; + uint64_t msg_control; + uint64_t msg_controllen; + uint32_t msg_flags; + uint32_t reserved; }; #endif From ee05b11b67d59a6c5bb4b9d661bcc20bbd0bbe7a Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 4 Jul 2021 16:34:15 +0000 Subject: [PATCH 082/297] bits/syscall.h: add landlock syscalls from linux v5.13 see linux commit a49f4f81cb48925e8d7cbd9e59068f516e984144 arch: Wire up Landlock syscalls linuxcommit 17ae69aba89dbfa2139b7f8024b757ab3cc42f59 Merge tag 'landlock_v34' of ... jmorris/linux-security Landlock provides for unprivileged application sandboxing. The goal of Landlock is to enable to restrict ambient rights (e.g. global filesystem access) for a set of processes. Landlock is inspired by seccomp-bpf but instead of filtering syscalls and their raw arguments, a Landlock rule can restrict the use of kernel objects like file hierarchies, according to the kernel semantic. --- arch/aarch64/bits/syscall.h.in | 3 +++ arch/arm/bits/syscall.h.in | 3 +++ arch/i386/bits/syscall.h.in | 3 +++ arch/m68k/bits/syscall.h.in | 3 +++ arch/microblaze/bits/syscall.h.in | 3 +++ arch/mips/bits/syscall.h.in | 3 +++ arch/mips64/bits/syscall.h.in | 3 +++ arch/mipsn32/bits/syscall.h.in | 3 +++ arch/or1k/bits/syscall.h.in | 3 +++ arch/powerpc/bits/syscall.h.in | 3 +++ arch/powerpc64/bits/syscall.h.in | 3 +++ arch/riscv64/bits/syscall.h.in | 3 +++ arch/s390x/bits/syscall.h.in | 3 +++ arch/sh/bits/syscall.h.in | 3 +++ arch/x32/bits/syscall.h.in | 3 +++ arch/x86_64/bits/syscall.h.in | 3 +++ 16 files changed, 48 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index 037da214..5f420e61 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -296,4 +296,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index 8919137f..048fdea7 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -396,6 +396,9 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index 4c04ea89..46ffe1d9 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -433,4 +433,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index 136775b4..a0c63323 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -413,3 +413,6 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index 10f27aba..931d7919 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -434,4 +434,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index 1d0deed3..63e3503a 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -415,4 +415,7 @@ #define __NR_process_madvise 4440 #define __NR_epoll_pwait2 4441 #define __NR_mount_setattr 4442 +#define __NR_landlock_create_ruleset 4444 +#define __NR_landlock_add_rule 4445 +#define __NR_landlock_restrict_self 4446 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index b1b83f5f..b89965d1 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -345,4 +345,7 @@ #define __NR_process_madvise 5440 #define __NR_epoll_pwait2 5441 #define __NR_mount_setattr 5442 +#define __NR_landlock_create_ruleset 5444 +#define __NR_landlock_add_rule 5445 +#define __NR_landlock_restrict_self 5446 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index bfaa080e..bb2d04a8 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -369,4 +369,7 @@ #define __NR_process_madvise 6440 #define __NR_epoll_pwait2 6441 #define __NR_mount_setattr 6442 +#define __NR_landlock_create_ruleset 6444 +#define __NR_landlock_add_rule 6445 +#define __NR_landlock_restrict_self 6446 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index 3c60eda9..2b5f2052 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -318,4 +318,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index 33e26e4b..b1605a58 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -422,4 +422,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index 38bb23cb..b3a8fba0 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -394,4 +394,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index a9cbfb50..b534afe8 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -296,6 +296,9 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index 88de5148..dfc38479 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -359,4 +359,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index 1a900264..ff14f54d 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -406,4 +406,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index d90cb157..5d22fa17 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -305,6 +305,9 @@ #define __NR_process_madvise (0x40000000 + 440) #define __NR_epoll_pwait2 (0x40000000 + 441) #define __NR_mount_setattr (0x40000000 + 442) +#define __NR_landlock_create_ruleset (0x40000000 + 444) +#define __NR_landlock_add_rule (0x40000000 + 445) +#define __NR_landlock_restrict_self (0x40000000 + 446) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index 634e29fd..c3882de7 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -352,4 +352,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 From dda21f10a7d800812cdc63602556c2d217de1d3c Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 4 Jul 2021 20:33:25 +0000 Subject: [PATCH 083/297] netinet/in.h: add INADDR_DUMMY from linux v5.13 see linux commit 321827477360934dc040e9d3c626bf1de6c3ab3c icmp: don't send out ICMP messages with a source address of 0.0.0.0 "RFC7600 reserves a dummy address to be used as a source for ICMP messages (192.0.0.8/32), so let's teach the kernel to substitute that address as a last resort if the regular source address selection procedure fails." --- include/netinet/in.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/netinet/in.h b/include/netinet/in.h index f9594339..fb628b61 100644 --- a/include/netinet/in.h +++ b/include/netinet/in.h @@ -48,6 +48,7 @@ struct ipv6_mreq { #define INADDR_BROADCAST ((in_addr_t) 0xffffffff) #define INADDR_NONE ((in_addr_t) 0xffffffff) #define INADDR_LOOPBACK ((in_addr_t) 0x7f000001) +#define INADDR_DUMMY ((in_addr_t) 0xc0000008) #define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) #define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) From a8300f5d2a4b0774a1646454bdf6c629d2c49ace Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Wed, 7 Jul 2021 17:40:46 +0000 Subject: [PATCH 084/297] elf.h: add NT_ARM_PAC_ENABLED_KEYS from linux v5.13 see linux commit 201698626fbca1cf1a3b686ba14cf2a056500716 arm64: Introduce prctl(PR_PAC_{SET,GET}_ENABLED_KEYS) --- include/elf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/elf.h b/include/elf.h index 5170f3e2..86e2f0bb 100644 --- a/include/elf.h +++ b/include/elf.h @@ -687,6 +687,7 @@ typedef struct { #define NT_ARM_PACA_KEYS 0x407 #define NT_ARM_PACG_KEYS 0x408 #define NT_ARM_TAGGED_ADDR_CTRL 0x409 +#define NT_ARM_PAC_ENABLED_KEYS 0x40a #define NT_METAG_CBUF 0x500 #define NT_METAG_RPIPE 0x501 #define NT_METAG_TLS 0x502 From aa3bab6ce48d4e210ba3a86fed62e589df789ff4 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Wed, 7 Jul 2021 17:43:30 +0000 Subject: [PATCH 085/297] sys/prctl.h: add PR_PAC_{SET,GET}_ENABLED_KEYS from linux v5.13 see linux commit 201698626fbca1cf1a3b686ba14cf2a056500716 arm64: Introduce prctl(PR_PAC_{SET,GET}_ENABLED_KEYS) --- include/sys/prctl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/sys/prctl.h b/include/sys/prctl.h index 3f0254c7..087a75c9 100644 --- a/include/sys/prctl.h +++ b/include/sys/prctl.h @@ -174,6 +174,9 @@ struct prctl_mm_map { #define SYSCALL_DISPATCH_FILTER_ALLOW 0 #define SYSCALL_DISPATCH_FILTER_BLOCK 1 +#define PR_PAC_SET_ENABLED_KEYS 60 +#define PR_PAC_GET_ENABLED_KEYS 61 + int prctl (int, ...); #ifdef __cplusplus From bdb5454065f74b0f6b5ddd8ee39f83d6303c97bb Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Wed, 7 Jul 2021 17:46:31 +0000 Subject: [PATCH 086/297] sys/ptrace.h: add PTRACE_GET_RSEQ_CONFIGURATION from linux v5.13 see linux commit 90f093fa8ea48e5d991332cee160b761423d55c1 rseq, ptrace: Add PTRACE_GET_RSEQ_CONFIGURATION request the struct type got __ prefix to follow existing practice. --- include/sys/ptrace.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/sys/ptrace.h b/include/sys/ptrace.h index 5d62a985..c72e3c06 100644 --- a/include/sys/ptrace.h +++ b/include/sys/ptrace.h @@ -42,6 +42,7 @@ extern "C" { #define PTRACE_SECCOMP_GET_FILTER 0x420c #define PTRACE_SECCOMP_GET_METADATA 0x420d #define PTRACE_GET_SYSCALL_INFO 0x420e +#define PTRACE_GET_RSEQ_CONFIGURATION 0x420f #define PT_READ_I PTRACE_PEEKTEXT #define PT_READ_D PTRACE_PEEKDATA @@ -130,6 +131,14 @@ struct __ptrace_syscall_info { }; }; +struct __ptrace_rseq_configuration { + uint64_t rseq_abi_pointer; + uint32_t rseq_abi_size; + uint32_t signature; + uint32_t flags; + uint32_t pad; +}; + long ptrace(int, ...); #ifdef __cplusplus From 760f5d7efed4d4761875334f8c4e6398be308cc9 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 8 Mar 2022 17:21:49 -0500 Subject: [PATCH 087/297] fix __WORDSIZE on x32 sys/user.h sys/reg.h already had it right as 32, to which it was explicitly changed when commit 664cd341921007cea52c8891f27ce35927dca378 derived x32 from x86_64. but the copy exposed in sys/user.h was missed. --- arch/x32/bits/user.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x32/bits/user.h b/arch/x32/bits/user.h index 4073cc06..eac82a14 100644 --- a/arch/x32/bits/user.h +++ b/arch/x32/bits/user.h @@ -1,5 +1,5 @@ #undef __WORDSIZE -#define __WORDSIZE 64 +#define __WORDSIZE 32 typedef struct user_fpregs_struct { uint16_t cwd, swd, ftw, fop; From 6d8a515796270eb6cec8a278cb353a078a10f09a Mon Sep 17 00:00:00 2001 From: Isaiah Poston Date: Sat, 12 Mar 2022 18:21:56 -0600 Subject: [PATCH 088/297] fix invalid free of duplocale object when malloc has been replaced newlocale and freelocale use __libc_malloc and __libc_free, but duplocale used malloc. If malloc was replaced, this resulted in invalid free using the wrong allocator when passing the result of duplocale to freelocale. Instead, use libc-internal malloc for duplocale. This bug was introduced by commit 1e4204d522670a1d8b8ab85f1cfefa960547e8af. --- src/locale/duplocale.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/locale/duplocale.c b/src/locale/duplocale.c index 030b64cb..5ce33ae6 100644 --- a/src/locale/duplocale.c +++ b/src/locale/duplocale.c @@ -3,6 +3,11 @@ #include "locale_impl.h" #include "libc.h" +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef + locale_t __duplocale(locale_t old) { locale_t new = malloc(sizeof *new); From 01b14242cccb03c411d3eb1437c99da663c95507 Mon Sep 17 00:00:00 2001 From: psykose Date: Wed, 2 Mar 2022 21:16:54 +0100 Subject: [PATCH 089/297] accept null pointer as message argument to gettext functions the change to support passing null was rejected in the past on the grounds that GNU gettext documented it as undefined, on an assumption that only glibc accepted it and that the standalone GNU gettext did not. but it turned out that both explicitly accept it. in light of this, since some software assumes null can be passed safely, allow it. --- src/locale/dcngettext.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/locale/dcngettext.c b/src/locale/dcngettext.c index d1e6c6d1..0b53286d 100644 --- a/src/locale/dcngettext.c +++ b/src/locale/dcngettext.c @@ -132,6 +132,9 @@ char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2, struct binding *q; int old_errno = errno; + /* match gnu gettext behaviour */ + if (!msgid1) goto notrans; + if ((unsigned)category >= LC_ALL) goto notrans; if (!domainname) domainname = __gettextdomain(); From 7a43f6fea9081bdd53d8a11cef9e9fab0348c53d Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 7 Apr 2022 13:12:40 -0400 Subject: [PATCH 090/297] release 1.2.3 --- VERSION | 2 +- WHATSNEW | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 23aa8390..0495c4a8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.2 +1.2.3 diff --git a/WHATSNEW b/WHATSNEW index e1d01982..f9bb2482 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -2287,3 +2287,43 @@ arch-specific bugs fixed: - i386 __set_thread_area fallback for pre-2.6 kernels didn't work - missing O_LARGEFILE macro value on x86_64, x32, mips64 - unpredictable s390x breakage from failure to preserve call-saved registers + + + +1.2.3 release notes + +new features: +- qsort_r function (POSIX-future) +- pthread_getname_np extension function +- hard float on SPE FPU for powerpc-sf +- SEEK_DATA and SEEK_HOLE exposed in unistd.h (Linux extensions) + +compatibility: +- free now preserves errno (POSIX-future requirement) +- setjmp is declared explicitly with returns_twice for non-GCC compilers +- macro version of isascii is no longer defined for C++ +- dynamic linker now tolerates zero-length LOAD segments +- epoll_[p]wait is now a cancellation point +- pwd/grp functions no longer fail on systems without AF_UNIX support +- POSIX TZ parsing is stricter to allow more names to fallback to files +- NULL is now defined as nullptr when used in C++11 or later +- gettext now accepts null pointer as argument + +bugs fixed: +- old regression in wcwidth of Hangul combining (vowel/final) letters +- duplocale used wrong malloc when malloc was replaced (1.2.2 regression) +- fmaf rounded wrong on archs without FE_TOWARDZERO (all softfloat archs) +- popen didn't honor requirement not to leak other popen pipe fds to child +- aligned_alloc and variants crashed on allocation failure +- dl_iterate_phdr reported incorrect module TLS pointers +- mishandling of some inputs in acoshf and expm1f and functions using them +- potentially wrong-sign zero in cproj functions at infinity +- multiple bugs in legacy function cuserid +- minor posix_spawn file actions API conformance issues +- pthread_setname_np fd leak +- out-of-bound read in zoneinfo handling with distant-past times +- out-of-tree builds lacked generated debug cfi for x86 asm + +arch-specific bugs fixed: +- powerpc (32-bit) struct shmid_ds layout was wrong for some fields +- time64 struct layout was wrong in sound ioctl fallback (32-bit archs) From 8cf87b3027009c0acac591d9ae80262dc25daccf Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Wed, 21 Nov 2018 17:29:21 +0100 Subject: [PATCH 091/297] fix incorrect parameter name in internal netlink.h RTA_OK macro the wrong name works only by accident. --- src/network/netlink.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/netlink.h b/src/network/netlink.h index 38acb178..873fabe2 100644 --- a/src/network/netlink.h +++ b/src/network/netlink.h @@ -86,7 +86,7 @@ struct ifaddrmsg { #define RTA_DATALEN(rta) ((rta)->rta_len-sizeof(struct rtattr)) #define RTA_DATAEND(rta) ((char*)(rta)+(rta)->rta_len) #define RTA_NEXT(rta) (struct rtattr*)((char*)(rta)+NETLINK_ALIGN((rta)->rta_len)) -#define RTA_OK(nlh,end) ((char*)(end)-(char*)(rta) >= sizeof(struct rtattr)) +#define RTA_OK(rta,end) ((char*)(end)-(char*)(rta) >= sizeof(struct rtattr)) #define NLMSG_RTA(nlh,len) ((void*)((char*)(nlh)+sizeof(struct nlmsghdr)+NETLINK_ALIGN(len))) #define NLMSG_RTAOK(rta,nlh) RTA_OK(rta,NLMSG_DATAEND(nlh)) From 55b727d7ad6c3c8ac147622c441e2995e553e91d Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 20 Apr 2022 09:06:54 -0400 Subject: [PATCH 092/297] add missing POSIX confstr keys for pthread CFLAGS/LDFLAGS _CS_POSIX_V7_THREADS_CFLAGS and _CS_POSIX_V7_THREADS_LDFLAGS have been missing for a long time, which is a conformance defect. we were waiting on glibc to add them or at least agree on the numeric values they will have so as to keep the numbering aligned. it looks like they will be added to glibc with these numbers, and in any case, this list does not have any significant churn that would result in the numbers getting taken. --- include/unistd.h | 2 ++ src/conf/confstr.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/unistd.h b/include/unistd.h index 212263a7..80be3b26 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -467,6 +467,8 @@ pid_t gettid(void); #define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS 1147 #define _CS_V6_ENV 1148 #define _CS_V7_ENV 1149 +#define _CS_POSIX_V7_THREADS_CFLAGS 1150 +#define _CS_POSIX_V7_THREADS_LDFLAGS 1151 #ifdef __cplusplus } diff --git a/src/conf/confstr.c b/src/conf/confstr.c index 02cb1aa2..3d417284 100644 --- a/src/conf/confstr.c +++ b/src/conf/confstr.c @@ -7,7 +7,7 @@ size_t confstr(int name, char *buf, size_t len) const char *s = ""; if (!name) { s = "/bin:/usr/bin"; - } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>33U) { + } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>35U) { errno = EINVAL; return 0; } From 03f71251e6987b18d005e5a9e07d20906ae4b143 Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 03:17:45 -0400 Subject: [PATCH 093/297] remove ARMSUBARCH relic from configure commit 0f814a4e57e80d2512934820b878211e9d71c93e removed its use. --- configure | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configure b/configure index ca5cbc0b..6f5453f5 100755 --- a/configure +++ b/configure @@ -723,11 +723,6 @@ fi test "$SUBARCH" \ && printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH" -case "$ARCH$SUBARCH" in -arm) ASMSUBARCH=el ;; -*) ASMSUBARCH=$SUBARCH ;; -esac - # # Some archs (powerpc) have different possible long double formats # that the compiler can be configured for. The logic for whether this From 8910efd0e474fab85bf00657a6eeae4d69a87f63 Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 03:27:03 -0400 Subject: [PATCH 094/297] don't remap internal-use syscall macros to nonexistent time32 syscalls riscv32 and future architectures lack the _time32 variants entirely, so don't try to use their numbers. instead, reflect that they're not present. --- src/internal/syscall.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/internal/syscall.h b/src/internal/syscall.h index d5f294d4..4f41e1dc 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -201,43 +201,43 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l #define SYS_sendfile SYS_sendfile64 #endif -#ifndef SYS_timer_settime +#ifdef SYS_timer_settime32 #define SYS_timer_settime SYS_timer_settime32 #endif -#ifndef SYS_timer_gettime +#ifdef SYS_timer_gettime32 #define SYS_timer_gettime SYS_timer_gettime32 #endif -#ifndef SYS_timerfd_settime +#ifdef SYS_timerfd_settime32 #define SYS_timerfd_settime SYS_timerfd_settime32 #endif -#ifndef SYS_timerfd_gettime +#ifdef SYS_timerfd_gettime32 #define SYS_timerfd_gettime SYS_timerfd_gettime32 #endif -#ifndef SYS_clock_settime +#ifdef SYS_clock_settime32 #define SYS_clock_settime SYS_clock_settime32 #endif -#ifndef SYS_clock_gettime +#ifdef SYS_clock_gettime32 #define SYS_clock_gettime SYS_clock_gettime32 #endif -#ifndef SYS_clock_getres +#ifdef SYS_clock_getres_time32 #define SYS_clock_getres SYS_clock_getres_time32 #endif -#ifndef SYS_clock_nanosleep +#ifdef SYS_clock_nanosleep_time32 #define SYS_clock_nanosleep SYS_clock_nanosleep_time32 #endif -#ifndef SYS_gettimeofday +#ifdef SYS_gettimeofday_time32 #define SYS_gettimeofday SYS_gettimeofday_time32 #endif -#ifndef SYS_settimeofday +#ifdef SYS_settimeofday_time32 #define SYS_settimeofday SYS_settimeofday_time32 #endif From 41149ea8c7a6f28a1c60478fe7f6b9552aa39e3b Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 03:31:05 -0400 Subject: [PATCH 095/297] only use getrlimit/setrlimit syscalls if they exist riscv32 and future architectures only provide prlimit64. --- src/misc/getrlimit.c | 6 +++++- src/misc/setrlimit.c | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/misc/getrlimit.c b/src/misc/getrlimit.c index 2ab2f0f4..bf676307 100644 --- a/src/misc/getrlimit.c +++ b/src/misc/getrlimit.c @@ -6,12 +6,13 @@ int getrlimit(int resource, struct rlimit *rlim) { - unsigned long k_rlim[2]; int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim); if (!ret) { FIX(rlim->rlim_cur); FIX(rlim->rlim_max); } +#ifdef SYS_getrlimit + unsigned long k_rlim[2]; if (!ret || errno != ENOSYS) return ret; if (syscall(SYS_getrlimit, resource, k_rlim) < 0) @@ -21,6 +22,9 @@ int getrlimit(int resource, struct rlimit *rlim) FIX(rlim->rlim_cur); FIX(rlim->rlim_max); return 0; +#else + return ret; +#endif } weak_alias(getrlimit, getrlimit64); diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c index 8340aee0..5b713cf3 100644 --- a/src/misc/setrlimit.c +++ b/src/misc/setrlimit.c @@ -12,12 +12,14 @@ struct ctx { int err; }; +#ifdef SYS_setrlimit static void do_setrlimit(void *p) { struct ctx *c = p; if (c->err>0) return; c->err = -__syscall(SYS_setrlimit, c->res, c->lim); } +#endif int setrlimit(int resource, const struct rlimit *rlim) { @@ -29,6 +31,7 @@ int setrlimit(int resource, const struct rlimit *rlim) rlim = &tmp; } int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0); +#ifdef SYS_setrlimit if (ret != -ENOSYS) return __syscall_ret(ret); struct ctx c = { @@ -42,6 +45,9 @@ int setrlimit(int resource, const struct rlimit *rlim) return -1; } return 0; +#else + return __syscall_ret(ret); +#endif } weak_alias(setrlimit, setrlimit64); From 12a757b3219408c5f96fd5b9daa5c551944337ee Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 03:33:10 -0400 Subject: [PATCH 096/297] only fallback to gettimeofday/settimeofday syscalls if they exist riscv32 and future architectures only provide the clock_ functions. --- src/time/clock_gettime.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index 3e1d0975..c7e66a51 100644 --- a/src/time/clock_gettime.c +++ b/src/time/clock_gettime.c @@ -80,10 +80,12 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) return __syscall_ret(r); long ts32[2]; r = __syscall(SYS_clock_gettime, clk, ts32); +#ifdef SYS_gettimeofday if (r==-ENOSYS && clk==CLOCK_REALTIME) { r = __syscall(SYS_gettimeofday, ts32, 0); ts32[1] *= 1000; } +#endif if (!r) { ts->tv_sec = ts32[0]; ts->tv_nsec = ts32[1]; @@ -92,6 +94,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) return __syscall_ret(r); #else r = __syscall(SYS_clock_gettime, clk, ts); +#ifdef SYS_gettimeofday if (r == -ENOSYS) { if (clk == CLOCK_REALTIME) { __syscall(SYS_gettimeofday, ts, 0); @@ -100,6 +103,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) } r = -EINVAL; } +#endif return __syscall_ret(r); #endif } From 9a9374955517bf731f11fd2c4a071b3cc1120526 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 27 Apr 2022 09:10:02 -0400 Subject: [PATCH 097/297] drop use of stat operation in temporary file name generation this change serves two purposes: 1. it eliminates one of the few remaining uses of the kernel stat structure which will not be present in future archs, avoiding the need for growing ifdef logic here. 2. it potentially makes the operations less expensive when the candidate exists as a non-symlink by avoiding the need to read the inode (assuming the directory tables suffice to distinguish symlinks). this uses the idiom I discovered while rewriting realpath for commit 29ff7599a448232f2527841c2362643d246cee36 of being able to use the readlink operation as an inexpensive probe for file existence that doesn't following symlinks. --- src/stdio/tempnam.c | 8 +++----- src/stdio/tmpnam.c | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/stdio/tempnam.c b/src/stdio/tempnam.c index 565df6b6..0c65b1f0 100644 --- a/src/stdio/tempnam.c +++ b/src/stdio/tempnam.c @@ -6,7 +6,6 @@ #include #include #include "syscall.h" -#include "kstat.h" #define MAXTRIES 100 @@ -37,11 +36,10 @@ char *tempnam(const char *dir, const char *pfx) for (try=0; try #include #include "syscall.h" -#include "kstat.h" #define MAXTRIES 100 @@ -17,11 +16,10 @@ char *tmpnam(char *buf) int r; for (try=0; try Date: Thu, 28 Apr 2022 02:02:38 -0400 Subject: [PATCH 098/297] drop direct use of stat syscalls in fchmodat instead, use the fstatat/stat functions, so that the logic for which syscalls are present and usable is all in fstatat. this results in a slight increase in cost for old kernels on 32-bit archs: now statx will be attempted first rather than just using the legacy time32 syscalls, despite us not caring about timestamps. however, it's not even clear that the legacy syscalls *should* succeed if the timestamps are out of range; arguably they should fail with EOVERFLOW. as such, paying a small cost here on old kernels seems well-motivated. with this change, fchmodat itself is no longer blocking ports to new archs that lack the legacy syscalls. --- src/stat/fchmodat.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c index 4ee00b0a..bc581050 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -2,7 +2,6 @@ #include #include #include "syscall.h" -#include "kstat.h" int fchmodat(int fd, const char *path, mode_t mode, int flag) { @@ -11,12 +10,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) if (flag != AT_SYMLINK_NOFOLLOW) return __syscall_ret(-EINVAL); - struct kstat st; + struct stat st; int ret, fd2; char proc[15+3*sizeof(int)]; - if ((ret = __syscall(SYS_fstatat, fd, path, &st, flag))) - return __syscall_ret(ret); + if (fstatat(fd, path, &st, flag)) + return -1; if (S_ISLNK(st.st_mode)) return __syscall_ret(-EOPNOTSUPP); @@ -27,12 +26,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) } __procfdname(proc, fd2); - ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0); + ret = stat(proc, &st); if (!ret) { - if (S_ISLNK(st.st_mode)) ret = -EOPNOTSUPP; - else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode); + if (S_ISLNK(st.st_mode)) ret = __syscall_ret(-EOPNOTSUPP); + else ret = syscall(SYS_fchmodat, AT_FDCWD, proc, mode); } __syscall(SYS_close, fd2); - return __syscall_ret(ret); + return ret; } From c9ba0769a749e4e08fd8a8815b8ced96fba4927b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 28 Apr 2022 02:14:34 -0400 Subject: [PATCH 099/297] provide an internal namespace-safe __fstatat this makes it so we can drop direct stat syscall use in interfaces that can't use the POSIX namespace. --- src/include/sys/stat.h | 8 ++++++++ src/stat/fstatat.c | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/include/sys/stat.h diff --git a/src/include/sys/stat.h b/src/include/sys/stat.h new file mode 100644 index 00000000..822888b2 --- /dev/null +++ b/src/include/sys/stat.h @@ -0,0 +1,8 @@ +#ifndef SYS_STAT_H +#define SYS_STAT_H + +#include "../../../include/sys/stat.h" + +hidden int __fstatat(int, const char *restrict, struct stat *restrict, int); + +#endif diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index de165b5c..cf11a294 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -131,7 +131,7 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric return 0; } -int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) +int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) { int ret; if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) { @@ -142,6 +142,8 @@ int fstatat(int fd, const char *restrict path, struct stat *restrict st, int fla return __syscall_ret(ret); } +weak_alias(__fstatat, fstatat); + #if !_REDIR_TIME64 weak_alias(fstatat, fstatat64); #endif From 2b754a542492f5878608a1130e00021ae02a0e34 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 28 Apr 2022 02:18:42 -0400 Subject: [PATCH 100/297] drop direct use of stat syscalls in internal __map_file this function is used to implement some baseline ISO C interfaces, so it cannot call any of the stat functions by their public names. use the namespace-safe __fstatat instead. --- src/time/__map_file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/time/__map_file.c b/src/time/__map_file.c index d3cefa82..8ef36138 100644 --- a/src/time/__map_file.c +++ b/src/time/__map_file.c @@ -1,16 +1,16 @@ +#define _BSD_SOURCE #include #include #include #include "syscall.h" -#include "kstat.h" const char unsigned *__map_file(const char *pathname, size_t *size) { - struct kstat st; + struct stat st; const unsigned char *map = MAP_FAILED; int fd = sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return 0; - if (!syscall(SYS_fstat, fd, &st)) { + if (!__fstatat(fd, "", &st, AT_EMPTY_PATH)) { map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); *size = st.st_size; } From fb10dc288d74442ea85c26b0ac3810f05377cba9 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 28 Apr 2022 02:24:44 -0400 Subject: [PATCH 101/297] only use fstatat and others legacy stat syscalls if they exist riscv32 and future architectures only provide statx. --- src/stat/fstatat.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index cf11a294..74c51cf5 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -6,7 +6,6 @@ #include #include #include "syscall.h" -#include "kstat.h" struct statx { uint32_t stx_mask; @@ -69,6 +68,10 @@ static int fstatat_statx(int fd, const char *restrict path, struct stat *restric return 0; } +#ifdef SYS_fstatat + +#include "kstat.h" + static int fstatat_kstat(int fd, const char *restrict path, struct stat *restrict st, int flag) { int ret; @@ -130,15 +133,20 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric return 0; } +#endif int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) { int ret; +#ifdef SYS_fstatat if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) { ret = fstatat_statx(fd, path, st, flag); if (ret!=-ENOSYS) return __syscall_ret(ret); } ret = fstatat_kstat(fd, path, st, flag); +#else + ret = fstatat_statx(fd, path, st, flag); +#endif return __syscall_ret(ret); } From 05a55868ff0f42cfc8701c7977322aa4c8e1aca3 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 4 May 2022 10:51:00 -0400 Subject: [PATCH 102/297] provide an internal namespace-safe __fstat this avoids the need for implementation-internal callers to depend on the nonstandard AT_EMPTY_PATH extension to use __fstatat and isolates knowledge of that extension to the implementation of __fstat. --- src/include/sys/stat.h | 1 + src/stat/fstat.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/include/sys/stat.h b/src/include/sys/stat.h index 822888b2..59339bee 100644 --- a/src/include/sys/stat.h +++ b/src/include/sys/stat.h @@ -3,6 +3,7 @@ #include "../../../include/sys/stat.h" +hidden int __fstat(int, struct stat *); hidden int __fstatat(int, const char *restrict, struct stat *restrict, int); #endif diff --git a/src/stat/fstat.c b/src/stat/fstat.c index 9bbb46de..27db0ccb 100644 --- a/src/stat/fstat.c +++ b/src/stat/fstat.c @@ -4,12 +4,14 @@ #include #include "syscall.h" -int fstat(int fd, struct stat *st) +int __fstat(int fd, struct stat *st) { if (fd<0) return __syscall_ret(-EBADF); - return fstatat(fd, "", st, AT_EMPTY_PATH); + return __fstatat(fd, "", st, AT_EMPTY_PATH); } +weak_alias(__fstat, fstat); + #if !_REDIR_TIME64 weak_alias(fstat, fstat64); #endif From 6e9d2370c7559af80b32a91f20898f41597e093b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 4 May 2022 10:53:01 -0400 Subject: [PATCH 103/297] use __fstat instead of __fstatat with AT_EMPTY_PATH in __map_file this isolates knowledge of the nonstandard AT_EMPTY_PATH extension to one place and returns __map_file to its prior simplicity. --- src/time/__map_file.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/time/__map_file.c b/src/time/__map_file.c index 8ef36138..c2b29fe8 100644 --- a/src/time/__map_file.c +++ b/src/time/__map_file.c @@ -1,4 +1,3 @@ -#define _BSD_SOURCE #include #include #include @@ -10,7 +9,7 @@ const char unsigned *__map_file(const char *pathname, size_t *size) const unsigned char *map = MAP_FAILED; int fd = sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return 0; - if (!__fstatat(fd, "", &st, AT_EMPTY_PATH)) { + if (!__fstat(fd, &st)) { map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); *size = st.st_size; } From dcb31f6b450fdeed4dc364e15cd190e8562ea227 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 6 May 2022 19:34:48 -0400 Subject: [PATCH 104/297] fix constraint violation in qsort wrapper around qsort_r function pointer types do not implicitly convert to void *. a cast is required here. --- src/stdlib/qsort_nr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdlib/qsort_nr.c b/src/stdlib/qsort_nr.c index efe7ccec..8ffe71d0 100644 --- a/src/stdlib/qsort_nr.c +++ b/src/stdlib/qsort_nr.c @@ -10,5 +10,5 @@ static int wrapper_cmp(const void *v1, const void *v2, void *cmp) void qsort(void *base, size_t nel, size_t width, cmpfun cmp) { - __qsort_r(base, nel, width, wrapper_cmp, cmp); + __qsort_r(base, nel, width, wrapper_cmp, (void *)cmp); } From 751bee0ee727e8d8b003c87cff77ac76f1dbecd6 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Wed, 15 Sep 2021 22:11:55 +0000 Subject: [PATCH 105/297] mntent: fix parsing lines with optional fields According to fstab(5), the last two fields are optional, but this wasn't accepted. After this change, only the first field is required, which matches glibc's behaviour. Using sscanf as before, it would have been impossible to differentiate between 0 fields and 4 fields, because sscanf would have returned 0 in both cases due to the use of assignment suppression and %n for the string fields (which is important to avoid copying any strings). So instead, before calling sscanf, initialize every string to the empty string, and then we can check which strings are empty afterwards to know how many fields were matched. --- src/misc/mntent.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/misc/mntent.c b/src/misc/mntent.c index eabb8200..962b8767 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -21,7 +21,8 @@ int endmntent(FILE *f) struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen) { - int cnt, n[8], use_internal = (linebuf == SENTINEL); + int n[8], use_internal = (linebuf == SENTINEL); + size_t len, i; mnt->mnt_freq = 0; mnt->mnt_passno = 0; @@ -39,10 +40,13 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle errno = ERANGE; return 0; } - cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", + + len = strlen(linebuf); + for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len; + sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", n, n+1, n+2, n+3, n+4, n+5, n+6, n+7, &mnt->mnt_freq, &mnt->mnt_passno); - } while (cnt < 2 || linebuf[n[0]] == '#'); + } while (linebuf[n[0]] == '#' || n[1]==len); linebuf[n[1]] = 0; linebuf[n[3]] = 0; From 8974ef2124118e4ed8cad7ee0534b36e5c584c4e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 15 May 2022 19:22:05 -0400 Subject: [PATCH 106/297] mntent: fix potential mishandling of extremely long lines commit 05973dc3bbc1aca9b3c8347de6879ed72147ab3b made it so that lines longer than INT_MAX can in theory be read, but did not use a suitable type for the positions determined by sscanf. we could change to using size_t, but since the signature for getmntent_r does not admit lines longer than INT_MAX, it does not make sense to support them in the legacy thread-unsafe form either -- the principle here is that there should not be an incentive to use the unsafe function to get added functionality. --- src/misc/mntent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/misc/mntent.c b/src/misc/mntent.c index 962b8767..d404fbe3 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -2,6 +2,7 @@ #include #include #include +#include static char *internal_buf; static size_t internal_bufsize; @@ -42,6 +43,7 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle } len = strlen(linebuf); + if (len > INT_MAX) continue; for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len; sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", n, n+1, n+2, n+3, n+4, n+5, n+6, n+7, From 6c858d6fd4df8b5498ef2cae66c8f3c3eff1587b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 3 Jun 2022 11:03:00 -0400 Subject: [PATCH 107/297] ensure distinct query id for parallel A and AAAA queries in resolver assuming a reasonable realtime clock, res_mkquery is highly unlikely to generate the same query id twice in a row, but it's possible with a very low-resolution system clock or under extreme delay of forward progress. when it happens, res_msend fails to wait for both answers, and instead stops listening after getting two answers to the same query (A or AAAA). to avoid this, increment one byte of the second query's id if it matches the first query's. don't bother checking if the second byte is also equal, since it doesn't matter; we just need to ensure that at least one byte is distinct. --- src/network/lookup_name.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index aa558c19..b5232ce8 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -155,6 +155,9 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static if (qlens[nq] == -1) return EAI_NONAME; qbuf[nq][3] = 0; /* don't need AD flag */ + /* Ensure query IDs are distinct. */ + if (nq && qbuf[nq][0] == qbuf[0][0]) + qbuf[nq][0]++; nq++; } } From 4100279825c17807bdabf1c128ba4e49a1dea406 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 3 Jun 2022 18:54:41 -0400 Subject: [PATCH 108/297] remove random filename obfuscation that leaks ASLR information the __randname function is used by various temp file creation interfaces as a backend to produce a name to attempt using. it does not have to produce results that are safe against guessing, and only aims to avoid unintentional collisions. mixing the address of an object on the stack in a reversible manner leaked ASLR information, potentially allowing an attacker who can observe the temp files created and their creation timestamps to narrow down the possible ASLR state of the process that created them. there is no actual value in mixing these addresses in; it was just obfuscation. so don't do it. instead, mix the tid, just to avoid collisions if multiple processes/threads stampede to create temp files at the same moment. even without this measure, they should not collide unless the clock source is very low resolution, but it's a cheap improvement. if/when we have a guaranteed-available userspace csprng, it could be used here instead. even though there is no need for cryptographic entropy here, it would avoid having to reason about clock resolution and such to determine whether the behavior is nice. --- src/temp/__randname.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/temp/__randname.c b/src/temp/__randname.c index 2bce37a0..1425badc 100644 --- a/src/temp/__randname.c +++ b/src/temp/__randname.c @@ -1,5 +1,6 @@ #include #include +#include "pthread_impl.h" /* This assumes that a check for the template size has already been made */ @@ -10,7 +11,7 @@ char *__randname(char *template) unsigned long r; __clock_gettime(CLOCK_REALTIME, &ts); - r = ts.tv_nsec*65537 ^ (uintptr_t)&ts / 16 + (uintptr_t)template; + r = ts.tv_nsec + __pthread_self()->tid * 65537UL; for (i=0; i<6; i++, r>>=5) template[i] = 'A'+(r&15)+(r&16)*2; From a23a3da29bcca8d179d1e4de7d059639716a5c1e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 23 Jun 2022 11:53:28 -0400 Subject: [PATCH 109/297] avoid limited space of random temp file names if clock resolution is low this is not an issue that was actually hit, but I noticed it during previous changes to __randname: if the resolution of tv_nsec is too low, the space of temp file names obtainable by a thread could plausibly be exhausted. mixing in tv_sec avoids this. --- src/temp/__randname.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/temp/__randname.c b/src/temp/__randname.c index 1425badc..e9b970f1 100644 --- a/src/temp/__randname.c +++ b/src/temp/__randname.c @@ -11,7 +11,7 @@ char *__randname(char *template) unsigned long r; __clock_gettime(CLOCK_REALTIME, &ts); - r = ts.tv_nsec + __pthread_self()->tid * 65537UL; + r = ts.tv_sec + ts.tv_nsec + __pthread_self()->tid * 65537UL; for (i=0; i<6; i++, r>>=5) template[i] = 'A'+(r&15)+(r&16)*2; From 63c67053a3e42e9dff788de432f82ff07d4d772a Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Thu, 30 Jun 2022 13:52:43 -0400 Subject: [PATCH 110/297] in early stage ldso before __dls2b, call mprotect with __syscall if LTO is enabled, gcc hoists the call to ___errno_location outside the loop even though the access to errno is gated behind head != &ldso because ___errno_location is marked __attribute__((const)). this causes the program to crash because TLS is not yet initialized when called from __dls2. this is also possible if LTO is not enabled; even though gcc 11 doesn't do it, it is still wrong to use errno here. since the start and end are already aligned, we can simply call __syscall instead of using global errno. Fixes: e13a2b8953ef ("implement PT_GNU_RELRO support") --- ldso/dynlink.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 5b9c8be4..14fdd29e 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1356,12 +1356,14 @@ static void reloc_all(struct dso *p) do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2); do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3); - if (head != &ldso && p->relro_start != p->relro_end && - mprotect(laddr(p, p->relro_start), p->relro_end-p->relro_start, PROT_READ) - && errno != ENOSYS) { - error("Error relocating %s: RELRO protection failed: %m", - p->name); - if (runtime) longjmp(*rtld_fail, 1); + if (head != &ldso && p->relro_start != p->relro_end) { + long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start), + p->relro_end-p->relro_start, PROT_READ); + if (ret != 0 && ret != -ENOSYS) { + error("Error relocating %s: RELRO protection failed: %m", + p->name); + if (runtime) longjmp(*rtld_fail, 1); + } } p->relocated = 1; From d16d7b10997e6f1c224c3de01b43868f0ce2cc3d Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 19 Jul 2022 19:00:53 -0400 Subject: [PATCH 111/297] early stage ldso: remove symbolic references via error handling function while the error handling function should not be reached in stage 2 (assuming ldso itself was linked correctly), this was not statically determinate from the compiler's perspective, and in theory a compiler performing LTO could lift the TLS references (errno and other things) out of the printf-family functions called in a stage where TLS is not yet initialized. instead, perform the call via a static-storage, internal-linkage function pointer which will be set to a no-op function until the stage where the real error handling function should be reachable. inspired by commit 63c67053a3e42e9dff788de432f82ff07d4d772a. --- ldso/dynlink.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 14fdd29e..cc677952 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -29,7 +29,9 @@ #define realloc __libc_realloc #define free __libc_free -static void error(const char *, ...); +static void error_impl(const char *, ...); +static void error_noop(const char *, ...); +static void (*error)(const char *, ...) = error_noop; #define MAXP2(a,b) (-(-(a)&-(b))) #define ALIGN(x,y) ((x)+(y)-1 & -(y)) @@ -1758,6 +1760,9 @@ void __dls3(size_t *sp, size_t *auxv) env_preload = getenv("LD_PRELOAD"); } + /* Activate error handler function */ + error = error_impl; + /* If the main program was already loaded by the kernel, * AT_PHDR will point to some location other than the dynamic * linker's program headers. */ @@ -2347,7 +2352,7 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void return ret; } -static void error(const char *fmt, ...) +static void error_impl(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -2361,3 +2366,7 @@ static void error(const char *fmt, ...) __dl_vseterr(fmt, ap); va_end(ap); } + +static void error_noop(const char *fmt, ...) +{ +} From 7d568410b455390362e2bcfb7c50fcf9c8833d9b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 1 Aug 2022 12:54:23 -0400 Subject: [PATCH 112/297] fix mishandling of errno in getaddrinfo AI_ADDRCONFIG logic this code attempts to use the value of errno from failure of socket or connect to infer availability of the requested address family (v4 or v6). however, in the case where connect failed, there is an intervening call to close between connect and the use of errno. close is not required to preserve errno on success, and in fact the __aio_close code, which is called whenever aio is linked and thus always called in dynamic-linked programs, unconditionally clobbers errno. as a result, getaddrinfo fails with EAI_SYSTEM and errno=ENOENT rather than correctly determining that the address family was unavailable. this fix is based on report/patch by Jussi Nieminen, but simplified slightly to avoid breaking the case where socket, not connect, failed. --- src/network/getaddrinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c index efaab306..9df045f6 100644 --- a/src/network/getaddrinfo.c +++ b/src/network/getaddrinfo.c @@ -66,9 +66,11 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &cs); int r = connect(s, ta[i], tl[i]); + int saved_errno = errno; pthread_setcancelstate(cs, 0); close(s); if (!r) continue; + errno = saved_errno; } switch (errno) { case EADDRNOTAVAIL: From 4f48da008d1fb3ccab2ad76523c104aa3fa8d8b6 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sat, 16 Jul 2022 15:55:51 +0200 Subject: [PATCH 113/297] aarch64: add vfork The generic vfork implementation uses clone(SIGCHLD) which has fork semantics. Implement vfork as clone(SIGCHLD|CLONE_VM|CLONE_VFORK, 0) instead which has vfork semantics. (stack == 0 means sp is unchanged in the child.) Some users rely on vfork semantics when memory overcommit is disabled or when the vfork child runs code that synchronizes with the parent process (non-conforming). --- src/process/aarch64/vfork.s | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/process/aarch64/vfork.s diff --git a/src/process/aarch64/vfork.s b/src/process/aarch64/vfork.s new file mode 100644 index 00000000..429bec8c --- /dev/null +++ b/src/process/aarch64/vfork.s @@ -0,0 +1,9 @@ +.global vfork +.type vfork,%function +vfork: + mov x8, 220 // SYS_clone + mov x0, 0x4111 // SIGCHLD | CLONE_VM | CLONE_VFORK + mov x1, 0 + svc 0 + .hidden __syscall_ret + b __syscall_ret From baaf257f05b96816c24951e7b6721d72922949e5 Mon Sep 17 00:00:00 2001 From: Eugene Yudin Date: Mon, 1 Aug 2022 13:53:22 -0400 Subject: [PATCH 114/297] fix ESRCH error handling for clock_getcpuclockid the syscall used to probe availability of the clock fails with EINVAL when the requested pid does not exist, but clock_getcpuclockid is specified to use ESRCH for this purpose. --- src/time/clock_getcpuclockid.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/time/clock_getcpuclockid.c b/src/time/clock_getcpuclockid.c index 8a0e2d4c..bce1e8ab 100644 --- a/src/time/clock_getcpuclockid.c +++ b/src/time/clock_getcpuclockid.c @@ -8,6 +8,7 @@ int clock_getcpuclockid(pid_t pid, clockid_t *clk) struct timespec ts; clockid_t id = (-pid-1)*8U + 2; int ret = __syscall(SYS_clock_getres, id, &ts); + if (ret == -EINVAL) ret = -ESRCH; if (ret) return -ret; *clk = id; return 0; From 46d1c7801bb509e1097e8fadbaf359367fa4ef0b Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 18 May 2022 23:13:23 -0400 Subject: [PATCH 115/297] fix strings.h feature test macro usage due to missing features.h --- include/strings.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/strings.h b/include/strings.h index db0960b4..b7a5ea08 100644 --- a/include/strings.h +++ b/include/strings.h @@ -5,6 +5,7 @@ extern "C" { #endif +#include #define __NEED_size_t #define __NEED_locale_t From 2404d9d643763e6eceafa9a1918925d80a84ad44 Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Fri, 1 Jul 2022 11:09:10 -0400 Subject: [PATCH 116/297] use syscall_arg_t and __scc macro for arguments to __alt_socketcall otherwise, pointer arguments are sign-extended on x32, resulting in EFAULT. --- src/internal/syscall.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 4f41e1dc..4a446157 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -58,7 +58,7 @@ hidden long __syscall_ret(unsigned long), #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, long a, long b, long c, long d, long e, long f) +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); @@ -71,9 +71,9 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l return r; } #define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \ - (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) + __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, \ - (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) + __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f)) /* fixup legacy 16-bit junk */ From d32dadd60efb9d3b255351a3b532f8e4c3dd0db1 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 2 Aug 2022 17:24:47 -0400 Subject: [PATCH 117/297] ldso: support DT_RELR relative relocation format this resolves DT_RELR relocations in non-ldso, dynamic-linked objects. --- include/elf.h | 8 ++++++-- ldso/dynlink.c | 21 ++++++++++++++++++++- src/internal/dynlink.h | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/elf.h b/include/elf.h index 86e2f0bb..9e980a29 100644 --- a/include/elf.h +++ b/include/elf.h @@ -385,7 +385,8 @@ typedef struct { #define SHT_PREINIT_ARRAY 16 #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 -#define SHT_NUM 19 +#define SHT_RELR 19 +#define SHT_NUM 20 #define SHT_LOOS 0x60000000 #define SHT_GNU_ATTRIBUTES 0x6ffffff5 #define SHT_GNU_HASH 0x6ffffff6 @@ -754,7 +755,10 @@ typedef struct { #define DT_PREINIT_ARRAY 32 #define DT_PREINIT_ARRAYSZ 33 #define DT_SYMTAB_SHNDX 34 -#define DT_NUM 35 +#define DT_RELRSZ 35 +#define DT_RELR 36 +#define DT_RELRENT 37 +#define DT_NUM 38 #define DT_LOOS 0x6000000d #define DT_HIOS 0x6ffff000 #define DT_LOPROC 0x70000000 diff --git a/ldso/dynlink.c b/ldso/dynlink.c index cc677952..e92f03cb 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -210,7 +210,8 @@ static void decode_vec(size_t *v, size_t *a, size_t cnt) size_t i; for (i=0; ibase; + size_t *reloc_addr; + for (; relr_size; relr++, relr_size-=sizeof(size_t)) + if ((relr[0]&1) == 0) { + reloc_addr = laddr(dso, relr[0]); + *reloc_addr++ += (size_t)base; + } else { + int i = 0; + for (size_t bitmap=relr[0]; (bitmap>>=1); i++) + if (bitmap&1) + reloc_addr[i] += (size_t)base; + reloc_addr += 8*sizeof(size_t)-1; + } +} + static void redo_lazy_relocs() { struct dso *p = lazy_head, *next; @@ -1357,6 +1375,7 @@ static void reloc_all(struct dso *p) 2+(dyn[DT_PLTREL]==DT_RELA)); do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2); do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3); + do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]); if (head != &ldso && p->relro_start != p->relro_end) { long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start), diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 51c0639f..830354eb 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -93,7 +93,7 @@ struct fdpic_dummy_loadmap { #endif #define AUX_CNT 32 -#define DYN_CNT 32 +#define DYN_CNT 37 typedef void (*stage2_func)(unsigned char *, size_t *); From bf99258564fd5b58974d93201ab61506eb8cb03e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 2 Aug 2022 17:29:01 -0400 Subject: [PATCH 118/297] ldso: process RELR only for non-FDPIC archs the way RELR is applied is not a meaningful operation for FDPIC (there is no single "base" address). it seems unlikely RELR would ever be added for FDPIC, but if it ever is, the behavior and possibly data format will need to be different, so guard against calling the non-FDPIC code. --- ldso/dynlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index e92f03cb..fd09ca69 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1375,7 +1375,8 @@ static void reloc_all(struct dso *p) 2+(dyn[DT_PLTREL]==DT_RELA)); do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2); do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3); - do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]); + if (!DL_FDPIC) + do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]); if (head != &ldso && p->relro_start != p->relro_end) { long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start), From 37e18b7bf307fa4a8c745feebfcba54a0ba74f30 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 17 Aug 2022 18:34:07 -0400 Subject: [PATCH 119/297] freopen: reset stream orientation (byte/wide) and encoding rule this is a requirement of the C language (orientation) and POSIX (encoding rule) that was somehow overlooked. we rely on the fact that the buffer pointers have been reset by fflush, so that any future stdio operations on the stream will go through the same code paths they would on a newly-opened file without an orientation set, thereby setting the orientation as they should. --- src/stdio/freopen.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c index 615d4b47..96bfbb42 100644 --- a/src/stdio/freopen.c +++ b/src/stdio/freopen.c @@ -40,6 +40,8 @@ FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *re fclose(f2); } + f->mode = 0; + f->locale = 0; FUNLOCK(f); return f; From 379b18218d18a049b5423bbb9bb22e066ffc3f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira?= Date: Mon, 15 Aug 2022 15:14:25 -0300 Subject: [PATCH 120/297] ldso: make exit condition clearer in fixup_rpath breaking out of the switch-case when l==-1 means the conditional below will necessarily be true (-1 >= buf_size, a size_t variable) and the function will return 0. it is, however, somewhat unclear that that's what's happening. simply returning there is simpler --- ldso/dynlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index fd09ca69..03f5fd59 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -886,7 +886,7 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size) case ENOENT: case ENOTDIR: case EACCES: - break; + return 0; default: return -1; } From 2e5fff43dd7fc808197744c67cca7908ac19bb4f Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 20 Aug 2022 12:24:49 -0400 Subject: [PATCH 121/297] use alt signal stack when present for implementation-internal signals a request for this behavior has been open for a long time. the motivation is that application code, particularly under some language runtimes designed around very-low-footprint coroutine type constructs, may be operating with extremely small stack sizes unsuitable for receiving signals, using a separate signal stack for any signals it might handle. progress on this was blocked at one point trying to determine whether the implementation is actually entitled to clobber the alt stack, but the phrasing "available to the implementation" in the POSIX spec for sigaltstack seems to make it clear that the application cannot rely on the contents of this memory to be preserved in the absence of signal delivery (on the abstract machine, excluding implementation-internal signals) and that we can therefore use it for delivery of signals that "don't exist" on the abstract machine. no change is made for SIGTIMER since it is always blocked when used, and accepted via sigwaitinfo rather than execution of the signal handler. --- src/linux/membarrier.c | 2 +- src/thread/pthread_cancel.c | 2 +- src/thread/synccall.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linux/membarrier.c b/src/linux/membarrier.c index 343f7360..f64fe7e1 100644 --- a/src/linux/membarrier.c +++ b/src/linux/membarrier.c @@ -35,7 +35,7 @@ int __membarrier(int cmd, int flags) __tl_lock(); sem_init(&barrier_sem, 0, 0); struct sigaction sa = { - .sa_flags = SA_RESTART, + .sa_flags = SA_RESTART | SA_ONSTACK, .sa_handler = bcast_barrier }; memset(&sa.sa_mask, -1, sizeof sa.sa_mask); diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c index 2f9d5e97..2d3a98ea 100644 --- a/src/thread/pthread_cancel.c +++ b/src/thread/pthread_cancel.c @@ -77,7 +77,7 @@ void __testcancel() static void init_cancellation() { struct sigaction sa = { - .sa_flags = SA_SIGINFO | SA_RESTART, + .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK, .sa_sigaction = cancel_handler }; memset(&sa.sa_mask, -1, _NSIG/8); diff --git a/src/thread/synccall.c b/src/thread/synccall.c index d58c851f..a6b177c0 100644 --- a/src/thread/synccall.c +++ b/src/thread/synccall.c @@ -45,7 +45,7 @@ void __synccall(void (*func)(void *), void *ctx) { sigset_t oldmask; int cs, i, r; - struct sigaction sa = { .sa_flags = SA_RESTART, .sa_handler = handler }; + struct sigaction sa = { .sa_flags = SA_RESTART | SA_ONSTACK, .sa_handler = handler }; pthread_t self = __pthread_self(), td; int count = 0; From f34891801d18fc918bb03dd58f3bf194c485ab21 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 23 Aug 2022 14:02:58 -0700 Subject: [PATCH 122/297] Remove old header from arch/emscripten/bits --- arch/emscripten/bits/fcntl.h | 40 ------- arch/emscripten/bits/io.h | 0 arch/emscripten/bits/ipc.h | 14 --- arch/emscripten/bits/mman.h | 62 ---------- arch/emscripten/bits/msg.h | 16 --- arch/emscripten/bits/poll.h | 0 arch/emscripten/bits/resource.h | 2 - arch/emscripten/bits/sem.h | 11 -- arch/emscripten/bits/shm.h | 18 --- arch/emscripten/bits/statfs.h | 7 -- arch/emscripten/bits/syscall.h.in | 129 -------------------- arch/emscripten/bits/termios.h | 160 ------------------------- arch/emscripten/bits/update_syscall.sh | 7 -- 13 files changed, 466 deletions(-) delete mode 100644 arch/emscripten/bits/fcntl.h delete mode 100644 arch/emscripten/bits/io.h delete mode 100644 arch/emscripten/bits/ipc.h delete mode 100644 arch/emscripten/bits/mman.h delete mode 100644 arch/emscripten/bits/msg.h delete mode 100644 arch/emscripten/bits/poll.h delete mode 100644 arch/emscripten/bits/resource.h delete mode 100644 arch/emscripten/bits/sem.h delete mode 100644 arch/emscripten/bits/shm.h delete mode 100644 arch/emscripten/bits/statfs.h delete mode 100644 arch/emscripten/bits/syscall.h.in delete mode 100644 arch/emscripten/bits/termios.h delete mode 100755 arch/emscripten/bits/update_syscall.sh diff --git a/arch/emscripten/bits/fcntl.h b/arch/emscripten/bits/fcntl.h deleted file mode 100644 index 900601b1..00000000 --- a/arch/emscripten/bits/fcntl.h +++ /dev/null @@ -1,40 +0,0 @@ -#define O_CREAT 0100 -#define O_EXCL 0200 -#define O_NOCTTY 0400 -#define O_TRUNC 01000 -#define O_APPEND 02000 -#define O_NONBLOCK 04000 -#define O_DSYNC 010000 -#define O_SYNC 04010000 -#define O_RSYNC 04010000 -#define O_DIRECTORY 0200000 -#define O_NOFOLLOW 0400000 -#define O_CLOEXEC 02000000 - -#define O_ASYNC 020000 -#define O_DIRECT 040000 -#define O_LARGEFILE 0100000 -#define O_NOATIME 01000000 -#define O_PATH 010000000 -#define O_TMPFILE 020000000 -#define O_NDELAY O_NONBLOCK - -#define F_DUPFD 0 -#define F_GETFD 1 -#define F_SETFD 2 -#define F_GETFL 3 -#define F_SETFL 4 - -#define F_SETOWN 8 -#define F_GETOWN 9 -#define F_SETSIG 10 -#define F_GETSIG 11 - -#define F_GETLK 12 -#define F_SETLK 13 -#define F_SETLKW 14 - -#define F_SETOWN_EX 15 -#define F_GETOWN_EX 16 - -#define F_GETOWNER_UIDS 17 diff --git a/arch/emscripten/bits/io.h b/arch/emscripten/bits/io.h deleted file mode 100644 index e69de29b..00000000 diff --git a/arch/emscripten/bits/ipc.h b/arch/emscripten/bits/ipc.h deleted file mode 100644 index b748d3b7..00000000 --- a/arch/emscripten/bits/ipc.h +++ /dev/null @@ -1,14 +0,0 @@ -struct ipc_perm -{ - key_t __ipc_perm_key; - uid_t uid; - gid_t gid; - uid_t cuid; - gid_t cgid; - mode_t mode; - int __ipc_perm_seq; - long __pad1; - long __pad2; -}; - -#define IPC_64 0x100 diff --git a/arch/emscripten/bits/mman.h b/arch/emscripten/bits/mman.h deleted file mode 100644 index add63855..00000000 --- a/arch/emscripten/bits/mman.h +++ /dev/null @@ -1,62 +0,0 @@ -#define MAP_FAILED ((void *) -1) - -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 -#define PROT_GROWSDOWN 0x01000000 -#define PROT_GROWSUP 0x02000000 - -#define MAP_SHARED 0x01 -#define MAP_PRIVATE 0x02 -#define MAP_FIXED 0x10 - -#define MAP_TYPE 0x0f -#define MAP_FILE 0x00 -#define MAP_ANON 0x20 -#define MAP_ANONYMOUS MAP_ANON -#define MAP_32BIT 0x40 -#define MAP_NORESERVE 0x4000 -#define MAP_GROWSDOWN 0x0100 -#define MAP_DENYWRITE 0x0800 -#define MAP_EXECUTABLE 0x1000 -#define MAP_LOCKED 0x2000 -#define MAP_POPULATE 0x8000 -#define MAP_NONBLOCK 0x10000 -#define MAP_STACK 0x20000 -#define MAP_HUGETLB 0x40000 - -#define POSIX_MADV_NORMAL 0 -#define POSIX_MADV_RANDOM 1 -#define POSIX_MADV_SEQUENTIAL 2 -#define POSIX_MADV_WILLNEED 3 -#define POSIX_MADV_DONTNEED 0 - -#define MS_ASYNC 1 -#define MS_INVALIDATE 2 -#define MS_SYNC 4 - -#define MCL_CURRENT 1 -#define MCL_FUTURE 2 - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define MADV_NORMAL 0 -#define MADV_RANDOM 1 -#define MADV_SEQUENTIAL 2 -#define MADV_WILLNEED 3 -#define MADV_DONTNEED 4 -#define MADV_REMOVE 9 -#define MADV_DONTFORK 10 -#define MADV_DOFORK 11 -#define MADV_MERGEABLE 12 -#define MADV_UNMERGEABLE 13 -#define MADV_HUGEPAGE 14 -#define MADV_NOHUGEPAGE 15 -#define MADV_DONTDUMP 16 -#define MADV_DODUMP 17 -#define MADV_HWPOISON 100 -#define MADV_SOFT_OFFLINE 101 - -#define MREMAP_MAYMOVE 1 -#define MREMAP_FIXED 2 -#endif diff --git a/arch/emscripten/bits/msg.h b/arch/emscripten/bits/msg.h deleted file mode 100644 index 3db8576b..00000000 --- a/arch/emscripten/bits/msg.h +++ /dev/null @@ -1,16 +0,0 @@ -struct msqid_ds -{ - struct ipc_perm msg_perm; - time_t msg_stime; - int __unused1; - time_t msg_rtime; - int __unused2; - time_t msg_ctime; - int __unused3; - unsigned long msg_cbytes; - msgqnum_t msg_qnum; - msglen_t msg_qbytes; - pid_t msg_lspid; - pid_t msg_lrpid; - unsigned long __unused[2]; -}; diff --git a/arch/emscripten/bits/poll.h b/arch/emscripten/bits/poll.h deleted file mode 100644 index e69de29b..00000000 diff --git a/arch/emscripten/bits/resource.h b/arch/emscripten/bits/resource.h deleted file mode 100644 index 139597f9..00000000 --- a/arch/emscripten/bits/resource.h +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/arch/emscripten/bits/sem.h b/arch/emscripten/bits/sem.h deleted file mode 100644 index f5ce202b..00000000 --- a/arch/emscripten/bits/sem.h +++ /dev/null @@ -1,11 +0,0 @@ -struct semid_ds { - struct ipc_perm sem_perm; - time_t sem_otime; - time_t __unused1; - time_t sem_ctime; - time_t __unused2; - unsigned short sem_nsems; - char __sem_nsems_pad[sizeof(time_t)-sizeof(short)]; - time_t __unused3; - time_t __unused4; -}; diff --git a/arch/emscripten/bits/shm.h b/arch/emscripten/bits/shm.h deleted file mode 100644 index 8807c4fb..00000000 --- a/arch/emscripten/bits/shm.h +++ /dev/null @@ -1,18 +0,0 @@ -#define SHMLBA 4096 - -struct shmid_ds -{ - struct ipc_perm shm_perm; - size_t shm_segsz; - time_t shm_atime; - int __unused1; - time_t shm_dtime; - int __unused2; - time_t shm_ctime; - int __unused3; - pid_t shm_cpid; - pid_t shm_lpid; - unsigned long shm_nattch; - unsigned long __pad1; - unsigned long __pad2; -}; diff --git a/arch/emscripten/bits/statfs.h b/arch/emscripten/bits/statfs.h deleted file mode 100644 index f103f4e4..00000000 --- a/arch/emscripten/bits/statfs.h +++ /dev/null @@ -1,7 +0,0 @@ -struct statfs { - unsigned long f_type, f_bsize; - fsblkcnt_t f_blocks, f_bfree, f_bavail; - fsfilcnt_t f_files, f_ffree; - fsid_t f_fsid; - unsigned long f_namelen, f_frsize, f_flags, f_spare[4]; -}; diff --git a/arch/emscripten/bits/syscall.h.in b/arch/emscripten/bits/syscall.h.in deleted file mode 100644 index 4bf32ad2..00000000 --- a/arch/emscripten/bits/syscall.h.in +++ /dev/null @@ -1,129 +0,0 @@ -/* - * The .h version of this file is generated from the .h.in. - * See update_syscall.sh. - */ -#define __NR_exit 1 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_chdir 12 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_getpid 20 -#define __NR_pause 29 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_sync 36 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_acct 51 -#define __NR_ioctl 54 -#define __NR_setpgid 57 -#define __NR_umask 60 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_setrlimit 75 -#define __NR_getrusage 77 -#define __NR_symlink 83 -#define __NR_readlink 85 -#define __NR_munmap 91 -#define __NR_fchmod 94 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_setitimer 104 -#define __NR_wait4 114 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_mprotect 125 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR__newselect 142 -#define __NR_msync 144 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_mremap 163 -#define __NR_poll 168 -#define __NR_rt_sigqueueinfo 178 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_getcwd 183 -#define __NR_ugetrlimit 191 -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_lchown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_chown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_mincore 218 -#define __NR_madvise 219 -#define __NR_madvise1 219 -#define __NR_getdents64 220 -#define __NR_fcntl64 221 -#define __NR_exit_group 252 -#define __NR_statfs64 268 -#define __NR_fstatfs64 269 -#define __NR_fadvise64_64 272 -#define __NR_openat 295 -#define __NR_mkdirat 296 -#define __NR_mknodat 297 -#define __NR_fchownat 298 -#define __NR_fstatat64 300 -#define __NR_unlinkat 301 -#define __NR_renameat 302 -#define __NR_linkat 303 -#define __NR_symlinkat 304 -#define __NR_readlinkat 305 -#define __NR_fchmodat 306 -#define __NR_faccessat 307 -#define __NR_pselect6 308 -#define __NR_utimensat 320 -#define __NR_fallocate 324 -#define __NR_dup3 330 -#define __NR_pipe2 331 -#define __NR_preadv 333 -#define __NR_pwritev 334 -#define __NR_recvmmsg 337 -#define __NR_prlimit64 340 -#define __NR_sendmmsg 345 -#define __NR_socket 359 -#define __NR_socketpair 360 -#define __NR_bind 361 -#define __NR_connect 362 -#define __NR_listen 363 -#define __NR_accept4 364 -#define __NR_getsockopt 365 -#define __NR_setsockopt 366 -#define __NR_getsockname 367 -#define __NR_getpeername 368 -#define __NR_sendto 369 -#define __NR_sendmsg 370 -#define __NR_recvfrom 371 -#define __NR_recvmsg 372 -#define __NR_shutdown 373 diff --git a/arch/emscripten/bits/termios.h b/arch/emscripten/bits/termios.h deleted file mode 100644 index 61c888f4..00000000 --- a/arch/emscripten/bits/termios.h +++ /dev/null @@ -1,160 +0,0 @@ -struct termios -{ - tcflag_t c_iflag; - tcflag_t c_oflag; - tcflag_t c_cflag; - tcflag_t c_lflag; - cc_t c_line; - cc_t c_cc[NCCS]; - speed_t __c_ispeed; - speed_t __c_ospeed; -}; - -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 - -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 - -/* ?? */ -#define XTABS 0014000 - -#define B0 0000000 -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 - -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define B460800 0010004 -#define B500000 0010005 -#define B576000 0010006 -#define B921600 0010007 -#define B1000000 0010010 -#define B1152000 0010011 -#define B1500000 0010012 -#define B2000000 0010013 -#define B2500000 0010014 -#define B3000000 0010015 -#define B3500000 0010016 -#define B4000000 0010017 - -#define CBAUD 0010017 - -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 - -#define CRTSCTS 020000000000 - -#define ISIG 0000001 -#define ICANON 0000002 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define IEXTEN 0100000 - -/* Extensions? */ -#define CBAUDEX 0010000 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define EXTPROC 0200000 - -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 diff --git a/arch/emscripten/bits/update_syscall.sh b/arch/emscripten/bits/update_syscall.sh deleted file mode 100755 index 7e4489cb..00000000 --- a/arch/emscripten/bits/update_syscall.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# This scripe updates syscall.h based on the contents of syscall.h.in -# essentially duplicate all the __NR_ marcros with __SYS_ macros. In upstream -# must this is don by the top level Makefile. - -cp syscall.h.in syscall.h -sed -n -e s/__NR_/SYS_/p < syscall.h.in >> syscall.h From d4f987e4ac44e4e5ca2bcf68365b4c2b77bdf2d0 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Wed, 24 Aug 2022 15:26:52 +0100 Subject: [PATCH 123/297] epoll_create: fail with EINVAL if size is non-positive This is a part of the interface contract defined in the Linux man page (official for a Linux-specific interface) and asserted by test cases in the Linux Test Project (LTP). --- src/linux/epoll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/linux/epoll.c b/src/linux/epoll.c index 93baa814..e56e8f4c 100644 --- a/src/linux/epoll.c +++ b/src/linux/epoll.c @@ -5,6 +5,7 @@ int epoll_create(int size) { + if (size<=0) return __syscall_ret(-EINVAL); return epoll_create1(0); } From d8fddb964108e57e670d20c36e6da84796617d78 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 24 Aug 2022 20:48:47 -0400 Subject: [PATCH 124/297] fix fallback when ipv6 is disabled but resolv.conf has v6 nameserves apparently this code path was never tested, as it's not usual to have v6 nameservers listed on a system without v6 networking support. but it was always intended to work. when reverting to binding a v4 address, also revert the family in the sockaddr structure and the socklen for it. otherwise bind will just fail due to mismatched family/sockaddr size. fix dns resolver fallback when v6 nameservers are listed by --- src/network/res_msend.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 3e018009..105bf598 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -68,14 +68,15 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, } /* Get local address and open/bind a socket */ - sa.sin.sin_family = family; fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); /* Handle case where system lacks IPv6 support */ if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) { fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); family = AF_INET; + sl = sizeof sa.sin; } + sa.sin.sin_family = family; if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) { if (fd >= 0) close(fd); pthread_setcancelstate(cs, 0); From 25340a93375fc6d3324ab65c154edbf8d1701801 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 26 Aug 2022 10:20:46 -0400 Subject: [PATCH 125/297] add sysconf keys/values for signal stack size as a result of ISA extensions exploding register file sizes on some archs, using a constant for minimum signal stack size no longer seems viably future-proof. add sysconf keys allowing the kernel to provide a machine-dependent minimum applications can query to ensure they allocate sufficient space for stacks. the key names and indices align with the same functionality in glibc. see commit d5a5045382315e36588ca225889baa36ed0ed38f for previous action on this subject. ultimately, the macros MINSIGSTKSZ and SIGSTKSZ probably need to be deprecated, but that is standards-amendment work outside the scope of a single implementation. --- include/unistd.h | 2 ++ src/conf/sysconf.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/include/unistd.h b/include/unistd.h index 80be3b26..0e8149e4 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -425,6 +425,8 @@ pid_t gettid(void); #define _SC_XOPEN_STREAMS 246 #define _SC_THREAD_ROBUST_PRIO_INHERIT 247 #define _SC_THREAD_ROBUST_PRIO_PROTECT 248 +#define _SC_MINSIGSTKSZ 249 +#define _SC_SIGSTKSZ 250 #define _CS_PATH 0 #define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 1 diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index 3baaed32..33220daf 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -165,6 +165,9 @@ long sysconf(int name) [_SC_XOPEN_STREAMS] = JT_ZERO, [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1, [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1, + + [_SC_MINSIGSTKSZ] = MINSIGSTKSZ, + [_SC_SIGSTKSZ] = SIGSTKSZ, }; if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) { From 996b6154b20184c3b08cce28eb01edb7f47e9413 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 26 Aug 2022 11:34:46 -0400 Subject: [PATCH 126/297] use kernel-provided AT_MINSIGSTKSZ for sysconf(_SC_[MIN]SIGSTKSZ) use the legacy constant values if the kernel does not provide AT_MINSIGSTKSZ (__getauxval will return 0 in this case) and as a safety check if something is wrong and the provided value is less than the legacy constant. sysconf(_SC_SIGSTKSZ) returns SIGSTKSZ adjusted for the difference between the legacy constant MINSIGSTKSZ and the runtime value, so that the working space the application has on top of the minimum remains invariant under changes to the minimum. --- src/conf/sysconf.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index 33220daf..60d3e745 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "syscall.h" #include "libc.h" @@ -19,6 +20,8 @@ #define JT_AVPHYS_PAGES JT(9) #define JT_ZERO JT(10) #define JT_DELAYTIMER_MAX JT(11) +#define JT_MINSIGSTKSZ JT(12) +#define JT_SIGSTKSZ JT(13) #define RLIM(x) (-32768|(RLIMIT_ ## x)) @@ -166,8 +169,8 @@ long sysconf(int name) [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1, [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1, - [_SC_MINSIGSTKSZ] = MINSIGSTKSZ, - [_SC_SIGSTKSZ] = SIGSTKSZ, + [_SC_MINSIGSTKSZ] = JT_MINSIGSTKSZ, + [_SC_SIGSTKSZ] = JT_SIGSTKSZ, }; if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) { @@ -215,6 +218,13 @@ long sysconf(int name) mem *= si.mem_unit; mem /= PAGE_SIZE; return (mem > LONG_MAX) ? LONG_MAX : mem; + case JT_MINSIGSTKSZ & 255: + case JT_SIGSTKSZ & 255: ; + long val = __getauxval(AT_MINSIGSTKSZ); + if (val < MINSIGSTKSZ) val = MINSIGSTKSZ; + if (values[name] == JT_SIGSTKSZ) + val += SIGSTKSZ - MINSIGSTKSZ; + return val; case JT_ZERO & 255: return 0; } From a636fd630f70da01665c5cfaf01b8a657ef6c2fe Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 26 Aug 2022 14:57:52 -0400 Subject: [PATCH 127/297] dns: fail if ipv6 is disabled and resolv.conf has only v6 nameserves if resolv.conf lists no nameservers at all, the default of 127.0.0.1 is used. however, another "no nameservers" case arises where the system has ipv6 support disabled/configured-out and resolv.conf only contains v6 nameservers. this caused the resolver to repeat socket operations that will necessarily fail (sending to one or more wrong-family addresses) while waiting for a timeout. it would be contrary to configured intent to query 127.0.0.1 in this case, but the current behavior is not conducive to diagnosing the configuration problem. instead, fail immediately with EAI_SYSTEM and errno==EAFNOSUPPORT so that the configuration error is reportable. --- src/network/res_msend.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 105bf598..9adaea13 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -72,6 +72,11 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, /* Handle case where system lacks IPv6 support */ if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) { + for (i=0; ins[nns].family == AF_INET6; i++); + if (i==nns) { + pthread_setcancelstate(cs, 0); + return -1; + } fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); family = AF_INET; sl = sizeof sa.sin; From 5c1bbf80a9a940e0d48a19aea1481fcb06b9a74d Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 6 Sep 2022 01:53:54 -0700 Subject: [PATCH 128/297] Update to emscripten 3.1.20 --- arch/emscripten/bits/alltypes.h | 18 +- arch/emscripten/bits/reg.h | 21 +-- arch/emscripten/bits/stdint.h | 12 +- arch/emscripten/bits/syscall.h | 14 +- arch/emscripten/syscall_arch.h | 233 ++++++++++++------------ include/inttypes.h | 10 +- src/env/__environ.c | 4 +- src/exit/atexit.c | 14 +- src/internal/libc.c | 7 +- src/internal/pthread_impl.h | 25 +-- src/internal/syscall.h | 17 +- src/math/sqrtl.c | 4 + src/mman/mmap.c | 1 + src/mman/munmap.c | 1 + src/network/freeaddrinfo.c | 8 + src/sched/sched_yield.c | 11 +- src/stat/fstatat.c | 2 + src/thread/__timedwait.c | 31 ++-- src/thread/__wait.c | 24 +-- src/thread/pthread_barrier_wait.c | 11 +- src/thread/pthread_cancel.c | 6 + src/thread/pthread_cond_timedwait.c | 6 +- src/thread/pthread_detach.c | 4 +- src/thread/pthread_join.c | 38 ++++ src/thread/pthread_key_create.c | 3 + src/thread/pthread_rwlock_timedwrlock.c | 4 +- src/thread/pthread_rwlock_trywrlock.c | 2 +- src/thread/pthread_rwlock_unlock.c | 2 +- src/time/clock_gettime.c | 7 +- src/time/clock_nanosleep.c | 13 +- src/time/localtime_r.c | 9 +- src/unistd/fchown.c | 8 +- 32 files changed, 305 insertions(+), 265 deletions(-) diff --git a/arch/emscripten/bits/alltypes.h b/arch/emscripten/bits/alltypes.h index 2d727fca..1f7a6718 100644 --- a/arch/emscripten/bits/alltypes.h +++ b/arch/emscripten/bits/alltypes.h @@ -41,7 +41,7 @@ typedef __WCHAR_TYPE__ wchar_t; #else #if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t) -typedef long wchar_t; +typedef int wchar_t; #define __DEFINED_wchar_t #endif @@ -78,12 +78,12 @@ typedef long double double_t; #endif #if defined(__NEED_time_t) && !defined(__DEFINED_time_t) -typedef long time_t; +typedef _Int64 time_t; #define __DEFINED_time_t #endif #if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t) -typedef long suseconds_t; +typedef int suseconds_t; /* XXX EMSCRIPTEN: ensure it's always 32-bits even in wasm64 */ #define __DEFINED_suseconds_t #endif @@ -91,9 +91,9 @@ typedef long suseconds_t; #if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t) typedef struct { union { - int __i[9]; - volatile int __vi[9]; - unsigned __s[9]; + int __i[10]; + volatile int __vi[10]; + unsigned __s[10]; } __u; #ifdef __EMSCRIPTEN__ // For canvas transfer implementation in Emscripten, use an extra control field @@ -253,7 +253,7 @@ typedef unsigned int dev_t; #endif #if defined(__NEED_blksize_t) && !defined(__DEFINED_blksize_t) -typedef long blksize_t; +typedef int blksize_t; /* XXX EMSCRIPTEN: ensure it's always 32-bits even in wasm64 */ #define __DEFINED_blksize_t #endif @@ -278,7 +278,7 @@ typedef unsigned wint_t; #endif #if defined(__NEED_wctype_t) && !defined(__DEFINED_wctype_t) -typedef unsigned long wctype_t; +typedef unsigned int wctype_t; /* XXX EMSCRIPTEN: ensure it's always 32-bits even in wasm64 */ #define __DEFINED_wctype_t #endif @@ -294,7 +294,7 @@ typedef int clockid_t; #endif #if defined(__NEED_clock_t) && !defined(__DEFINED_clock_t) -typedef long clock_t; +typedef int clock_t; /* XXX EMSCRIPTEN: ensure it's always 32-bits even in wasm64 */ #define __DEFINED_clock_t #endif diff --git a/arch/emscripten/bits/reg.h b/arch/emscripten/bits/reg.h index 8bc2582d..1c4987c7 100644 --- a/arch/emscripten/bits/reg.h +++ b/arch/emscripten/bits/reg.h @@ -1,19 +1,6 @@ #undef __WORDSIZE +#ifdef __wasm64__ +#define __WORDSIZE 64 +#else #define __WORDSIZE 32 -#define EBX 0 -#define ECX 1 -#define EDX 2 -#define ESI 3 -#define EDI 4 -#define EBP 5 -#define EAX 6 -#define DS 7 -#define ES 8 -#define FS 9 -#define GS 10 -#define ORIG_EAX 11 -#define EIP 12 -#define CS 13 -#define EFL 14 -#define UESP 15 -#define SS 16 +#endif diff --git a/arch/emscripten/bits/stdint.h b/arch/emscripten/bits/stdint.h index 2621b613..832dca5f 100644 --- a/arch/emscripten/bits/stdint.h +++ b/arch/emscripten/bits/stdint.h @@ -23,11 +23,11 @@ typedef uint32_t uint_fast32_t; #else -#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 +#define INTPTR_MIN (-1-__INTPTR_MAX__) +#define INTPTR_MAX __INTPTR_MAX__ +#define UINTPTR_MAX __UINTPTR_MAX__ +#define PTRDIFF_MIN (-1-__PTRDIFF_MAX__) +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#define SIZE_MAX __SIZE_MAX__ #endif diff --git a/arch/emscripten/bits/syscall.h b/arch/emscripten/bits/syscall.h index 37a442fe..f88e03e6 100644 --- a/arch/emscripten/bits/syscall.h +++ b/arch/emscripten/bits/syscall.h @@ -1,16 +1,9 @@ -#define SYS_open __syscall_open #define SYS_link __syscall_link -#define SYS_unlink __syscall_unlink #define SYS_chdir __syscall_chdir -#define SYS_mknod __syscall_mknod #define SYS_chmod __syscall_chmod #define SYS_getpid __syscall_getpid #define SYS_pause __syscall_pause -#define SYS_access __syscall_access -#define SYS_nice __syscall_nice #define SYS_sync __syscall_sync -#define SYS_rename __syscall_rename -#define SYS_mkdir __syscall_mkdir #define SYS_rmdir __syscall_rmdir #define SYS_dup __syscall_dup #define SYS_pipe __syscall_pipe @@ -23,7 +16,6 @@ #define SYS_setrlimit __syscall_setrlimit #define SYS_getrusage __syscall_getrusage #define SYS_symlink __syscall_symlink -#define SYS_readlink __syscall_readlink #define SYS_munmap __syscall_munmap #define SYS_fchmod __syscall_fchmod #define SYS_getpriority __syscall_getpriority @@ -54,7 +46,6 @@ #define SYS_stat64 __syscall_stat64 #define SYS_lstat64 __syscall_lstat64 #define SYS_fstat64 __syscall_fstat64 -#define SYS_lchown32 __syscall_lchown32 #define SYS_getuid32 __syscall_getuid32 #define SYS_getgid32 __syscall_getgid32 #define SYS_geteuid32 __syscall_geteuid32 @@ -63,19 +54,18 @@ #define SYS_fchown32 __syscall_fchown32 #define SYS_getresuid32 __syscall_getresuid32 #define SYS_getresgid32 __syscall_getresgid32 -#define SYS_chown32 __syscall_chown32 #define SYS_mincore __syscall_mincore #define SYS_madvise __syscall_madvise #define SYS_getdents64 __syscall_getdents64 #define SYS_fcntl64 __syscall_fcntl64 #define SYS_statfs64 __syscall_statfs64 #define SYS_fstatfs64 __syscall_fstatfs64 -#define SYS_fadvise64_64 __syscall_fadvise64_64 +#define SYS_fadvise64 __syscall_fadvise64 #define SYS_openat __syscall_openat #define SYS_mkdirat __syscall_mkdirat #define SYS_mknodat __syscall_mknodat #define SYS_fchownat __syscall_fchownat -#define SYS_fstatat64 __syscall_fstatat64 +#define SYS_newfstatat __syscall_newfstatat #define SYS_unlinkat __syscall_unlinkat #define SYS_renameat __syscall_renameat #define SYS_linkat __syscall_linkat diff --git a/arch/emscripten/syscall_arch.h b/arch/emscripten/syscall_arch.h index d43a2118..f398401a 100644 --- a/arch/emscripten/syscall_arch.h +++ b/arch/emscripten/syscall_arch.h @@ -2,131 +2,124 @@ #include #include -#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)) +// Compile as if we can pass uint64 values directly to the +// host. Binaryen will take care of splitting any i64 params +// into a pair of i32 values if needed. +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) #ifdef __cplusplus extern "C" { #endif -long __syscall_open(long path, long flags, ...); // mode is optional -long __syscall_link(long oldpath, long newpath); -long __syscall_unlink(long path); -long __syscall_chdir(long path); -long __syscall_mknod(long path, long mode, long dev); -long __syscall_chmod(long path, long mode); -long __syscall_getpid(void); -long __syscall_pause(void); -long __syscall_access(long path, long amode); -long __syscall_nice(long inc); -long __syscall_sync(void); -long __syscall_rename(long old_path, long new_path); -long __syscall_mkdir(long path, long mode); -long __syscall_rmdir(long path); -long __syscall_dup(long fd); -long __syscall_pipe(long fd); -long __syscall_acct(long filename); -long __syscall_ioctl(long fd, long request, ...); -long __syscall_setpgid(long pid, long gpid); -long __syscall_umask(long mask); -long __syscall_getppid(void); -long __syscall_getpgrp(void); -long __syscall_setsid(void); -long __syscall_setrlimit(long resource, long limit); -long __syscall_getrusage(long who, long usage); -long __syscall_symlink(long target, long linkpath); -long __syscall_readlink(long path, long buf, long bufsize); -long __syscall_munmap(long addr, long len); -long __syscall_fchmod(long fd, long mode); -long __syscall_getpriority(long which, long who); -long __syscall_setpriority(long which, long who, long prio); -long __syscall_socketcall(long call, long args); -long __syscall_setitimer(long which, long new_value, long old_value); -long __syscall_getitimer(long which, long old_value); -long __syscall_wait4(long pid, long wstatus, long options, long rusage); -long __syscall_setdomainname(long name, long size); -long __syscall_uname(long buf); -long __syscall_mprotect(long addr, long len, long size); -long __syscall_getpgid(long pid); -long __syscall_fchdir(long fd); -long __syscall__newselect(long nfds, long readfds, long writefds, long exceptfds, long timeout); -long __syscall_msync(long addr, long len, long flags); -long __syscall_getsid(long pid); -long __syscall_fdatasync(long fd); -long __syscall_mlock(long addr, long len); -long __syscall_munlock(long addr, long len); -long __syscall_mlockall(long flags); -long __syscall_munlockall(void); -long __syscall_mremap(long old_addr, long old_size, long new_size, long flags, long new_addr); -long __syscall_poll(long fds, long nfds, long timeout); -long __syscall_getcwd(long buf, long size); -long __syscall_ugetrlimit(long resource, long rlim); -long __syscall_mmap2(long addr, long len, long prot, long flags, long fd, long off); -long __syscall_truncate64(long path, long low, long high); -long __syscall_ftruncate64(long fd, long low, long high); -long __syscall_stat64(long path, long buf); -long __syscall_lstat64(long path, long buf); -long __syscall_fstat64(long fd, long buf); -long __syscall_lchown32(long path, long owner, long group); -long __syscall_getuid32(void); -long __syscall_getgid32(void); -long __syscall_geteuid32(void); -long __syscall_getegid32(void); -long __syscall_setreuid32(long ruid, long euid); -long __syscall_setregid32(long rgid, long egid); -long __syscall_getgroups32(long size, long list); -long __syscall_fchown32(long fd, long owner, long group); -long __syscall_setresuid32(long ruid, long euid, long suid); -long __syscall_getresuid32(long ruid, long euid, long suid); -long __syscall_setresgid32(long rgid, long egid, long sgid); -long __syscall_getresgid32(long rgid, long egid, long sgid); -long __syscall_chown32(long path, long owner, long group); -long __syscall_setuid32(long uid); -long __syscall_setgid32(long uid); -long __syscall_mincore(long addr, long length, long vec); -long __syscall_madvise(long addr, long length, long advice); -long __syscall_getdents64(long fd, long dirp, long count); -long __syscall_fcntl64(long fd, long cmd, ...); -long __syscall_statfs64(long path, long size, long buf); -long __syscall_fstatfs64(long fd, long size, long buf); -long __syscall_fadvise64_64(long fd, long low, long high, long low2, long high2, long advice); -long __syscall_openat(long dirfd, long path, long flags, ...); -long __syscall_mkdirat(long dirfd, long path, long mode); -long __syscall_mknodat(long dirfd, long path, long mode, long dev); -long __syscall_fchownat(long dirfd, long path, long owner, long group, long flags); -long __syscall_fstatat64(long dirfd, long path, long buf, long flags); -long __syscall_unlinkat(long dirfd, long path, long flags); -long __syscall_renameat(long olddirfd, long oldpath, long newdirfd, long newpath); -long __syscall_linkat(long olddirfd, long oldpath, long newdirfd, long newpath, long flags); -long __syscall_symlinkat(long target, long newdirfd, long linkpath); -long __syscall_readlinkat(long dirfd, long path, long bug, long bufsize); -long __syscall_fchmodat(long dirfd, long path, long mode, ...); -long __syscall_faccessat(long dirfd, long path, long amode, long flags); -long __syscall_pselect6(long nfds, long readfds, long writefds, long exceptfds, long timeout, long sigmaks); -long __syscall_utimensat(long dirfd, long path, long times, long flags); -long __syscall_fallocate(long fd, long mode, long off_low, long off_high, long len_low, long len_high); -long __syscall_dup3(long fd, long suggestfd, long flags); -long __syscall_pipe2(long fds, long flags); -long __syscall_recvmmsg(long sockfd, long msgvec, long vlen, long flags, ...); -long __syscall_prlimit64(long pid, long resource, long new_limit, long old_limit); -long __syscall_sendmmsg(long sockfd, long msgvec, long vlen, long flags, ...); -long __syscall_socket(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_socketpair(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_bind(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_connect(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_listen(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_accept4(long sockfd, long addr, long addrlen, long flags, long dummy1, long dummy2); -long __syscall_getsockopt(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_setsockopt(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_getsockname(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_getpeername(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_sendto(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_sendmsg(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_recvfrom(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_recvmsg(long sockfd, long level, long optname, long optval, long optlen, long dummy); -long __syscall_shutdown(long sockfd, long level, long optname, long optval, long optlen, long dummy); +int __syscall_link(intptr_t oldpath, intptr_t newpath); +int __syscall_chdir(intptr_t path); +int __syscall_mknod(intptr_t path, int mode, int dev); +int __syscall_chmod(intptr_t path, int mode); +int __syscall_getpid(void); +int __syscall_pause(void); +int __syscall_access(intptr_t path, int amode); +int __syscall_sync(void); +int __syscall_rmdir(intptr_t path); +int __syscall_dup(int fd); +int __syscall_pipe(intptr_t fd); +int __syscall_acct(intptr_t filename); +int __syscall_ioctl(int fd, int request, ...); +int __syscall_setpgid(int pid, int gpid); +int __syscall_umask(int mask); +int __syscall_getppid(void); +int __syscall_getpgrp(void); +int __syscall_setsid(void); +int __syscall_setrlimit(int resource, intptr_t limit); +int __syscall_getrusage(int who, intptr_t usage); +int __syscall_symlink(intptr_t target, intptr_t linkpath); +int __syscall_munmap(intptr_t addr, size_t len); +int __syscall_fchmod(int fd, int mode); +int __syscall_getpriority(int which, int who); +int __syscall_setpriority(int which, int who, int prio); +int __syscall_socketcall(int call, intptr_t args); +int __syscall_setitimer(int which, intptr_t new_value, intptr_t old_value); +int __syscall_getitimer(int which, intptr_t old_value); +int __syscall_wait4(int pid, intptr_t wstatus, int options, int rusage); +int __syscall_setdomainname(intptr_t name, size_t size); +int __syscall_uname(intptr_t buf); +int __syscall_mprotect(size_t addr, size_t len, int prot); +int __syscall_getpgid(int pid); +int __syscall_fchdir(int fd); +int __syscall__newselect(int nfds, intptr_t readfds, intptr_t writefds, intptr_t exceptfds, intptr_t timeout); +int __syscall_msync(intptr_t addr, size_t len, int flags); +int __syscall_getsid(int pid); +int __syscall_fdatasync(int fd); +int __syscall_mlock(intptr_t addr, size_t len); +int __syscall_munlock(intptr_t addr, size_t len); +int __syscall_mlockall(int flags); +int __syscall_munlockall(void); +int __syscall_mremap(intptr_t old_addr, size_t old_size, size_t new_size, int flags, intptr_t new_addr); +int __syscall_poll(intptr_t fds, int nfds, int timeout); +int __syscall_getcwd(intptr_t buf, size_t size); +int __syscall_ugetrlimit(int resource, intptr_t rlim); +intptr_t __syscall_mmap2(intptr_t addr, size_t len, int prot, int flags, int fd, size_t off); +int __syscall_truncate64(intptr_t path, uint64_t length); +int __syscall_ftruncate64(int fd, uint64_t length); +int __syscall_stat64(intptr_t path, intptr_t buf); +int __syscall_lstat64(intptr_t path, intptr_t buf); +int __syscall_fstat64(int fd, intptr_t buf); +int __syscall_getuid32(void); +int __syscall_getgid32(void); +int __syscall_geteuid32(void); +int __syscall_getegid32(void); +int __syscall_setreuid32(int ruid, int euid); +int __syscall_setregid32(int rgid, int egid); +int __syscall_getgroups32(int size, intptr_t list); +int __syscall_fchown32(int fd, int owner, int group); +int __syscall_setresuid32(int ruid, int euid, int suid); +int __syscall_getresuid32(intptr_t ruid, intptr_t euid, intptr_t suid); +int __syscall_setresgid32(int rgid, int egid, int sgid); +int __syscall_getresgid32(intptr_t rgid, intptr_t egid, intptr_t sgid); +int __syscall_setuid32(int uid); +int __syscall_setgid32(int uid); +int __syscall_mincore(intptr_t addr, size_t length, intptr_t vec); +int __syscall_madvise(intptr_t addr, size_t length, int advice); +int __syscall_getdents64(int fd, intptr_t dirp, size_t count); +int __syscall_fcntl64(int fd, int cmd, ...); +int __syscall_statfs64(intptr_t path, size_t size, intptr_t buf); +int __syscall_fstatfs64(int fd, size_t size, intptr_t buf); +int __syscall_fadvise64(int fd, uint64_t offset, uint64_t length, int advice); +int __syscall_openat(int dirfd, intptr_t path, int flags, ...); // mode is optional +int __syscall_mkdirat(int dirfd, intptr_t path, int mode); +int __syscall_mknodat(int dirfd, intptr_t path, int mode, int dev); +int __syscall_fchownat(int dirfd, intptr_t path, int owner, int group, int flags); +int __syscall_newfstatat(int dirfd, intptr_t path, intptr_t buf, int flags); +int __syscall_unlinkat(int dirfd, intptr_t path, int flags); +int __syscall_renameat(int olddirfd, intptr_t oldpath, int newdirfd, intptr_t newpath); +int __syscall_linkat(int olddirfd, intptr_t oldpath, int newdirfd, intptr_t newpath, int flags); +int __syscall_symlinkat(intptr_t target, int newdirfd, intptr_t linkpath); +int __syscall_readlinkat(int dirfd, intptr_t path, intptr_t buf, size_t bufsize); +int __syscall_fchmodat(int dirfd, intptr_t path, int mode, ...); +int __syscall_faccessat(int dirfd, intptr_t path, int amode, int flags); +int __syscall_pselect6(int nfds, intptr_t readfds, intptr_t writefds, intptr_t exceptfds, intptr_t timeout, intptr_t sigmaks); +int __syscall_utimensat(int dirfd, intptr_t path, intptr_t times, int flags); +int __syscall_fallocate(int fd, int mode, uint64_t off, uint64_t len); +int __syscall_dup3(int fd, int suggestfd, int flags); +int __syscall_pipe2(intptr_t fds, int flags); +int __syscall_recvmmsg(int sockfd, intptr_t msgvec, size_t vlen, int flags, ...); +int __syscall_prlimit64(int pid, int resource, intptr_t new_limit, intptr_t old_limit); +int __syscall_sendmmsg(int sockfd, intptr_t msgvec, size_t vlen, int flags, ...); +int __syscall_socket(int domain, int type, int protocol, int dummy1, int dummy2, int dummy3); +int __syscall_socketpair(int domain, int type, int protocol, intptr_t fds, int dummy, int dummy2); +int __syscall_bind(int sockfd, intptr_t addr, size_t alen, int dummy, int dymmy2, int dummy3); +int __syscall_connect(int sockfd, intptr_t addr, size_t len, int dummy, int dummy2, int dummy3); +int __syscall_listen(int sockfd, int backlock, int dummy1, int dummy2, int dummy3, int dummy4); +int __syscall_accept4(int sockfd, intptr_t addr, intptr_t addrlen, int flags, int dummy1, int dummy2); +int __syscall_getsockopt(int sockfd, int level, int optname, intptr_t optval, intptr_t optlen, int dummy); +int __syscall_setsockopt(int sockfd, int level, int optname, intptr_t optval, size_t optlen, int dummy); +int __syscall_getsockname(int sockfd, intptr_t addr, intptr_t len, int dummy, int dummy2, int dummy3); +int __syscall_getpeername(int sockfd, intptr_t addr, intptr_t len, int dummy, int dummy2, int dummy3); +int __syscall_sendto(int sockfd, intptr_t msg, size_t len, int flags, intptr_t addr, size_t alen); +int __syscall_sendmsg(int sockfd, intptr_t msg , int flags, intptr_t addr, size_t alen, int dummy); +int __syscall_recvfrom(int sockfd, intptr_t msg, size_t len, int flags, intptr_t addr, intptr_t alen); +int __syscall_recvmsg(int sockfd, intptr_t msg, int flags, int dummy, int dummy2, int dummy3); +int __syscall_shutdown(int sockfd, int how, int dummy, int dummy2, int dummy3, int dummy4); #ifdef __cplusplus } diff --git a/include/inttypes.h b/include/inttypes.h index 51f4a52a..90c35c86 100644 --- a/include/inttypes.h +++ b/include/inttypes.h @@ -22,14 +22,14 @@ uintmax_t strtoumax(const char *__restrict, char **__restrict, int); intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int); uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); -#if UINTPTR_MAX == UINT64_MAX -#define __PRI64 "l" -#define __PRIPTR "l" -#elif defined(__EMSCRIPTEN__) +#if defined(__EMSCRIPTEN__) // Under emscripten __PTRDIFF_TYPE__ and therefor intptr_t are defined to -// be `long int` even on wasm2. +// be `long int` even on wasm32. #define __PRI64 "ll" #define __PRIPTR "l" +#elif UINTPTR_MAX == UINT64_MAX +#define __PRI64 "l" +#define __PRIPTR "l" #else #define __PRI64 "ll" #define __PRIPTR "" diff --git a/src/env/__environ.c b/src/env/__environ.c index 4052db2d..fcc881be 100644 --- a/src/env/__environ.c +++ b/src/env/__environ.c @@ -8,9 +8,7 @@ weak_alias(__environ, environ); #ifdef __EMSCRIPTEN__ #include #include -// Included for emscripten_builtin_free / emscripten_builtin_malloc -// TODO(sbc): Should these be in their own header to avoid emmalloc here? -#include +#include // We use emscripten_builtin_malloc here because this memory is never freed and // and we don't want LSan to consider this a leak. diff --git a/src/exit/atexit.c b/src/exit/atexit.c index 854e9fdd..f2401780 100644 --- a/src/exit/atexit.c +++ b/src/exit/atexit.c @@ -36,11 +36,11 @@ void __funcs_on_exit() } } -void __cxa_finalize(void *dso) +void ___cxa_finalize(void *dso) { } -int __cxa_atexit(void (*func)(void *), void *arg, void *dso) +int ___cxa_atexit(void (*func)(void *), void *arg, void *dso) { LOCK(lock); @@ -73,7 +73,13 @@ static void call(void *p) ((void (*)(void))(uintptr_t)p)(); } -int atexit(void (*func)(void)) +int __atexit(void (*func)(void)) { - return __cxa_atexit(call, (void *)(uintptr_t)func, 0); + return ___cxa_atexit(call, (void *)(uintptr_t)func, 0); } + +// XXX: EMSCRIPTEN: Use weak aliases here so that we can override these symbols +// in when EXIT_RUNTIME is set to 0. +weak_alias(__atexit, atexit); +weak_alias(___cxa_atexit, __cxa_atexit); +weak_alias(___cxa_finalize, __cxa_finalize); diff --git a/src/internal/libc.c b/src/internal/libc.c index 4b626320..c84ed3d2 100644 --- a/src/internal/libc.c +++ b/src/internal/libc.c @@ -3,14 +3,9 @@ struct __libc __libc; size_t __hwcap; +#ifndef __EMSCRIPTEN__ char *__progname=0, *__progname_full=0; weak_alias(__progname, program_invocation_short_name); weak_alias(__progname_full, program_invocation_name); - -#ifdef __EMSCRIPTEN_PTHREADS__ -#include -struct __libc* EMSCRIPTEN_KEEPALIVE emscripten_get_global_libc() { - return &libc; -} #endif diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 60137a03..c25a1c2d 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -11,6 +11,7 @@ #include "atomic.h" #ifdef __EMSCRIPTEN__ #include +#include "threading_internal.h" #endif #include "futex.h" @@ -18,22 +19,6 @@ #define pthread __pthread -#ifdef __EMSCRIPTEN__ -#define EM_THREAD_NAME_MAX 32 - -typedef struct thread_profiler_block { - // One of THREAD_STATUS_* - _Atomic int threadStatus; - // Wallclock time denoting when the current thread state was entered in. - double currentStatusStartTime; - // Accumulated duration times denoting how much time has been spent in each - // state, in msecs. - double timeSpentInStatus[EM_THREAD_STATUS_NUMFIELDS]; - // A human-readable name for this thread. - char name[EM_THREAD_NAME_MAX]; -} thread_profiler_block; -#endif - struct pthread { /* Part 1 -- these fields may be external or * internal (accessed via asm) ABI. Do not change. */ @@ -41,7 +26,8 @@ struct pthread { #ifndef TLS_ABOVE_TP uintptr_t *dtv; #endif - struct pthread *prev, *next; /* non-ABI */ + // TODO(sbc): Implement circular list of threads + //struct pthread *prev, *next; /* non-ABI */ uintptr_t sysinfo; #ifndef TLS_ABOVE_TP #ifdef CANARY_PAD @@ -90,6 +76,9 @@ struct pthread { // If --threadprofiler is enabled, this pointer is allocated to contain // internal information about the thread state for profiling purposes. thread_profiler_block * _Atomic profilerBlock; + // The TLS base to use the main module TLS data. Secondary modules + // still require dynamic allocation. + void* tls_base; #endif }; @@ -129,7 +118,7 @@ enum { // XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, so use an extra field // _rw_wr_owner to record which thread owns the write lock in order to avoid hangs. // Points to the pthread that currently has the write lock. -#define _rw_wr_owner __u.__p[3] +#define _rw_wr_owner __u.__vi[3] #endif #define _b_lock __u.__vi[0] #define _b_waiters __u.__vi[1] diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 3951f7a0..ec67b735 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -19,7 +19,14 @@ #endif #ifndef __scc +#ifdef __EMSCRIPTEN__ +// With emscripten we allow the passing of longer-than-word-sized +// argument (such as off_t on wasm32) and let binaryen handle splitting +// them into a pair of i32 arguments. +#define __scc(X) ((long long) (X)) +#else #define __scc(X) ((long) (X)) +#endif typedef long syscall_arg_t; #endif @@ -128,7 +135,6 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l #undef SYS_setgid #undef SYS_setfsuid #undef SYS_setfsgid -#define SYS_lchown SYS_lchown32 #define SYS_getuid SYS_getuid32 #define SYS_getgid SYS_getgid32 #define SYS_geteuid SYS_geteuid32 @@ -142,7 +148,6 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l #define SYS_getresuid SYS_getresuid32 #define SYS_setresgid SYS_setresgid32 #define SYS_getresgid SYS_getresgid32 -#define SYS_chown SYS_chown32 #define SYS_setuid SYS_setuid32 #define SYS_setgid SYS_setgid32 #define SYS_setfsuid SYS_setfsuid32 @@ -417,10 +422,10 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l #define __sys_open_cp3(x,pn,fl,mo) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) #endif #else // __EMSCRIPTEN__ -#define __sys_open2(x,pn,fl) __syscall_open(__scc(pn), __scc((fl)|O_LARGEFILE)) -#define __sys_open3(x,pn,fl,mo) __syscall_open(__scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) -#define __sys_open_cp2(x,pn,fl) __syscall_open(__scc(pn), __scc((fl)|O_LARGEFILE)) -#define __sys_open_cp3(x,pn,fl,mo) __syscall_open(__scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) +#define __sys_open2(x,pn,fl) __syscall_openat(__scc(AT_FDCWD), __scc(pn), __scc((fl)|O_LARGEFILE)) +#define __sys_open3(x,pn,fl,mo) __syscall_openat(__scc(AT_FDCWD), __scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) +#define __sys_open_cp2(x,pn,fl) __syscall_openat(__scc(AT_FDCWD), __scc(pn), __scc((fl)|O_LARGEFILE)) +#define __sys_open_cp3(x,pn,fl,mo) __syscall_openat(__scc(AT_FDCWD), __scc(pn), __scc((fl)|O_LARGEFILE), __scc(mo)) #endif #define __sys_open(...) __SYSCALL_DISP(__sys_open,,__VA_ARGS__) diff --git a/src/math/sqrtl.c b/src/math/sqrtl.c index 1b9f19c7..66bf2867 100644 --- a/src/math/sqrtl.c +++ b/src/math/sqrtl.c @@ -176,6 +176,10 @@ static inline u128 mul128_tail(u128 a, u128 b) /* see sqrt.c for detailed comments. */ +#ifdef __EMSCRIPTEN__ +// https://github.com/emscripten-core/emscripten/issues/15655 +__attribute__((no_sanitize("address"))) +#endif long double sqrtl(long double x) { u128 ix, ml; diff --git a/src/mman/mmap.c b/src/mman/mmap.c index eff88d82..e22f3110 100644 --- a/src/mman/mmap.c +++ b/src/mman/mmap.c @@ -37,5 +37,6 @@ void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off) } weak_alias(__mmap, mmap); +weak_alias(__mmap, emscripten_builtin_mmap); weak_alias(mmap, mmap64); diff --git a/src/mman/munmap.c b/src/mman/munmap.c index 2bf83bbe..083e7728 100644 --- a/src/mman/munmap.c +++ b/src/mman/munmap.c @@ -11,3 +11,4 @@ int __munmap(void *start, size_t len) } weak_alias(__munmap, munmap); +weak_alias(__munmap, emscripten_builtin_munmap); diff --git a/src/network/freeaddrinfo.c b/src/network/freeaddrinfo.c index 62241c23..c4016d9f 100644 --- a/src/network/freeaddrinfo.c +++ b/src/network/freeaddrinfo.c @@ -6,6 +6,13 @@ void freeaddrinfo(struct addrinfo *p) { +#if __EMSCRIPTEN__ + // Emscripten's usage of this structure is very simple: we always allocate + // ai_addr, and do not use the linked list aspect at all. There is also no + // aliasing with aibuf. + free(p->ai_addr); + free(p); +#else size_t cnt; for (cnt=1; p->ai_next; cnt++, p=p->ai_next); struct aibuf *b = (void *)((char *)p - offsetof(struct aibuf, ai)); @@ -13,4 +20,5 @@ void freeaddrinfo(struct addrinfo *p) LOCK(b->lock); if (!(b->ref -= cnt)) free(b); else UNLOCK(b->lock); +#endif } diff --git a/src/sched/sched_yield.c b/src/sched/sched_yield.c index 3f50030a..c9e6968f 100644 --- a/src/sched/sched_yield.c +++ b/src/sched/sched_yield.c @@ -1,12 +1,17 @@ #include #include "syscall.h" +#if __EMSCRIPTEN__ +#include +#endif + int sched_yield() { #if __EMSCRIPTEN__ - // SharedArrayBuffer and wasm threads do not support explicit yielding, - // but in practice it should happen automatically well enough anyhow, so - // report success in order to not break apps. + // SharedArrayBuffer and wasm threads do not support explicit yielding. + // For now we at least call `emscripten_yield` which processes the event queue + // (along with other essential tasks). + _emscripten_yield(); return 0; #else return syscall(SYS_sched_yield); diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index cd555acc..8da7d68e 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -146,6 +146,8 @@ int fstatat(int fd, const char *restrict path, struct stat *restrict st, int fla ret = __syscall(SYS_fstat, fd, st); else if ((fd == AT_FDCWD || *path=='/') && !flag) ret = __syscall(SYS_stat, path, st); + else if ((fd == AT_FDCWD || *path=='/') && flag==AT_SYMLINK_NOFOLLOW) + ret = __syscall(SYS_lstat, path, st); else ret = __syscall(SYS_fstatat, fd, path, st, flag); #else diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index eeeef53c..6c8284f6 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -5,7 +5,6 @@ #include #include #include -#include "pthread_impl.h" #else #include "futex.h" #endif @@ -38,10 +37,6 @@ static int __futex4_cp(volatile void *addr, int op, int val, const struct timesp static volatile int dummy = 0; weak_alias(dummy, __eintr_valid_flag); -#ifdef __EMSCRIPTEN__ -int _pthread_isduecanceled(struct pthread *pthread_ptr); -#endif - int __timedwait_cp(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int priv) { @@ -64,33 +59,35 @@ int __timedwait_cp(volatile int *addr, int val, #ifdef __EMSCRIPTEN__ double msecsToSleep = top ? (top->tv_sec * 1000 + top->tv_nsec / 1000000.0) : INFINITY; - int is_main_thread = emscripten_is_main_browser_thread(); + int is_runtime_thread = emscripten_is_main_runtime_thread(); + + // Main runtime thread may need to run proxied calls, so sleep in very small slices to be responsive. + double max_ms_slice_to_sleep = is_runtime_thread ? 1 : 100; + // cp suffix in the function name means "cancellation point", so this wait can be cancelled // by the users unless current threads cancelability is set to PTHREAD_CANCEL_DISABLE // which may be either done by the user of __timedwait() function. - if (is_main_thread || + if (is_runtime_thread || pthread_self()->canceldisable != PTHREAD_CANCEL_DISABLE || pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { double sleepUntilTime = emscripten_get_now() + msecsToSleep; do { - if (_pthread_isduecanceled(pthread_self())) { + if (pthread_self()->cancel) { // Emscripten-specific return value: The wait was canceled by user calling // pthread_cancel() for this thread, and the caller needs to cooperatively // cancel execution. return ECANCELED; } - // Assist other threads by executing proxied operations that are effectively singlethreaded. - if (is_main_thread) emscripten_main_thread_process_queued_calls(); - // Must wait in slices in case this thread is cancelled in between. - double waitMsecs = sleepUntilTime - emscripten_get_now(); - if (waitMsecs <= 0) { + msecsToSleep = sleepUntilTime - emscripten_get_now(); + if (msecsToSleep <= 0) { r = ETIMEDOUT; break; } - if (waitMsecs > 100) waitMsecs = 100; // non-main threads can sleep in longer slices. - if (is_main_thread && waitMsecs > 1) waitMsecs = 1; // main thread may need to run proxied calls, so sleep in very small slices to be responsive. - r = -emscripten_futex_wait((void*)addr, val, waitMsecs); - } while(r == ETIMEDOUT); + // Must wait in slices in case this thread is cancelled in between. + if (msecsToSleep > max_ms_slice_to_sleep) + msecsToSleep = max_ms_slice_to_sleep; + r = -emscripten_futex_wait((void*)addr, val, msecsToSleep); + } while (r == ETIMEDOUT); } else { // Can wait in one go. r = -emscripten_futex_wait((void*)addr, val, msecsToSleep); diff --git a/src/thread/__wait.c b/src/thread/__wait.c index 816f4c4a..5351eeca 100644 --- a/src/thread/__wait.c +++ b/src/thread/__wait.c @@ -5,10 +5,6 @@ #include "pthread_impl.h" -#ifdef __EMSCRIPTEN__ -int _pthread_isduecanceled(struct pthread *pthread_ptr); -#endif - void __wait(volatile int *addr, volatile int *waiters, int val, int priv) { int spins=100; @@ -19,22 +15,22 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv) } if (waiters) a_inc(waiters); #ifdef __EMSCRIPTEN__ - int is_main_thread = emscripten_is_main_runtime_thread(); + int is_runtime_thread = emscripten_is_main_runtime_thread(); + + // Main runtime thread may need to run proxied calls, so sleep in very small slices to be responsive. + double max_ms_slice_to_sleep = is_runtime_thread ? 1 : 100; + while (*addr==val) { - if (is_main_thread || pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { - // Must wait in slices in case this thread is cancelled in between. + if (is_runtime_thread || pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { int e; do { - if (_pthread_isduecanceled(pthread_self())) { + if (pthread_self()->cancel) { if (waiters) a_dec(waiters); return; } - // Assist other threads by executing proxied operations that are effectively singlethreaded. - if (is_main_thread) emscripten_main_thread_process_queued_calls(); - // Main thread waits in _very_ small slices so that it stays responsive to assist proxied - // pthread calls. - e = emscripten_futex_wait((void*)addr, val, is_main_thread ? 1 : 100); - } while(e == -ETIMEDOUT); + // Must wait in slices in case this thread is cancelled in between. + e = emscripten_futex_wait((void*)addr, val, max_ms_slice_to_sleep); + } while (e == -ETIMEDOUT); } else { // Can wait in one go. emscripten_futex_wait((void*)addr, val, INFINITY); diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c index ee2d17e8..36add3a7 100644 --- a/src/thread/pthread_barrier_wait.c +++ b/src/thread/pthread_barrier_wait.c @@ -88,17 +88,14 @@ int pthread_barrier_wait(pthread_barrier_t *b) a_spin(); a_inc(&inst->finished); #ifdef __EMSCRIPTEN__ - int is_main_thread = emscripten_is_main_browser_thread(); + int is_runtime_thread = emscripten_is_main_runtime_thread(); while (inst->finished == 1) { - if (is_main_thread) { + if (is_runtime_thread) { int e; do { - // Main thread waits in _very_ small slices so that it stays responsive to assist proxied - // pthread calls. + // Main runtime thread may need to run proxied calls, so sleep in very small slices to be responsive. e = emscripten_futex_wait(&inst->finished, 1, 1); - // Assist other threads by executing proxied operations that are effectively singlethreaded. - emscripten_main_thread_process_queued_calls(); - } while(e == -ETIMEDOUT); + } while (e == -ETIMEDOUT); } else { // Can wait in one go. emscripten_futex_wait(&inst->finished, 1, INFINITY); diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c index 2f9d5e97..e974746f 100644 --- a/src/thread/pthread_cancel.c +++ b/src/thread/pthread_cancel.c @@ -14,6 +14,7 @@ long __cancel() return -ECANCELED; } +#ifndef __EMSCRIPTEN__ 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); @@ -66,6 +67,7 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx) __syscall(SYS_tkill, self->tid, SIGCANCEL); } +#endif void __testcancel() { @@ -74,6 +76,7 @@ void __testcancel() __cancel(); } +#ifndef __EMSCRIPTEN__ static void init_cancellation() { struct sigaction sa = { @@ -83,14 +86,17 @@ static void init_cancellation() memset(&sa.sa_mask, -1, _NSIG/8); __libc_sigaction(SIGCANCEL, &sa, 0); } +#endif int pthread_cancel(pthread_t t) { +#ifndef __EMSCRIPTEN__ static int init; if (!init) { init_cancellation(); init = 1; } +#endif a_store(&t->cancel, 1); if (t == pthread_self()) { if (t->canceldisable == PTHREAD_CANCEL_ENABLE && t->cancelasync) diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index f46f5fed..58212cdb 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -55,7 +55,7 @@ static inline void unlock_requeue(volatile int *l, volatile int *r, int w) // primitive is strictly not needed, since it is more like an optimization to avoid spuriously waking // all waiters, just to make them wait on another location immediately afterwards. Here we do exactly // that: wake every waiter. - emscripten_futex_wake(l, 0x7FFFFFFF); + emscripten_futex_wake(l, INT_MAX); #else if (w) __wake(l, 1, 1); else __syscall(SYS_futex, l, FUTEX_REQUEUE|FUTEX_PRIVATE, 0, 1, r) != -ENOSYS @@ -187,10 +187,6 @@ int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restri __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); } -#ifdef __EMSCRIPTEN__ - pthread_testcancel(); -#endif - return e; } diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c index 06487441..bdcd2ddf 100644 --- a/src/thread/pthread_detach.c +++ b/src/thread/pthread_detach.c @@ -3,10 +3,12 @@ static int __pthread_detach(pthread_t t) { +#ifdef __EMSCRIPTEN__ // XXX EMSCRIPTEN: Add check for invalid (already joined) thread. Again // for the benefit of the conformance tests. - if (t->self != t) + if (!_emscripten_thread_is_valid(t)) return ESRCH; +#endif /* If the cas fails, detach state is either already-detached * or exiting/exited, and pthread_join will trap or cleanup. */ if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE) diff --git a/src/thread/pthread_join.c b/src/thread/pthread_join.c index 17dae85d..d68d149c 100644 --- a/src/thread/pthread_join.c +++ b/src/thread/pthread_join.c @@ -9,32 +9,70 @@ weak_alias(dummy1, __tl_sync); static int __pthread_timedjoin_np(pthread_t t, void **res, const struct timespec *at) { +#ifdef __EMSCRIPTEN__ + // Attempt to join a thread which does not point to a valid thread, or + // does not exist anymore. + if (!_emscripten_thread_is_valid(t)) return ESRCH; + // Thread is attempting to join to itself. Already detached threads are + // handled below by returning EINVAL instead. + // TODO: The detached check here is just to satisfy the + // `other.test_{proxy,main}_pthread_join_detach` tests. + if (t->detach_state != DT_DETACHED && __pthread_self() == t) return EDEADLK; +#endif int state, cs, r = 0; __pthread_testcancel(); __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); if (cs == PTHREAD_CANCEL_ENABLE) __pthread_setcancelstate(cs, 0); while ((state = t->detach_state) && r != ETIMEDOUT && r != EINVAL) { +#ifdef __EMSCRIPTEN__ + // The thread is (already) detached and therefore not joinable. + // This also handle cases where the thread becomes detached + // *during* the join. + if (state >= DT_DETACHED) { + // Even though the man page says this is undefined + // behaviour we ave several tests in the posixtest suite + // that depend on this. + r = EINVAL; + break; + } +#else if (state >= DT_DETACHED) a_crash(); +#endif r = __timedwait_cp(&t->detach_state, state, CLOCK_REALTIME, at, 1); } __pthread_setcancelstate(cs, 0); if (r == ETIMEDOUT || r == EINVAL) return r; __tl_sync(t); if (res) *res = t->result; +#ifdef __EMSCRIPTEN__ + // Thread was exited during this call, be sure to clean it up. + if (state == DT_EXITED) __emscripten_thread_cleanup(t); +#else // XXX Emscripten map_base unused if (t->map_base) __munmap(t->map_base, t->map_size); +#endif return 0; } int __pthread_join(pthread_t t, void **res) { +#ifdef __EMSCRIPTEN__ // XXX Emscripten check whether blocking is allowed. + emscripten_check_blocking_allowed(); +#endif return __pthread_timedjoin_np(t, res, 0); } static int __pthread_tryjoin_np(pthread_t t, void **res) { +#ifdef __EMSCRIPTEN__ // XXX Emscripten call __pthread_timedjoin_np directly to avoid additional check + return t->detach_state==DT_JOINABLE ? EBUSY : __pthread_timedjoin_np(t, res, 0); +#else return t->detach_state==DT_JOINABLE ? EBUSY : __pthread_join(t, res); +#endif } weak_alias(__pthread_tryjoin_np, pthread_tryjoin_np); weak_alias(__pthread_timedjoin_np, pthread_timedjoin_np); weak_alias(__pthread_join, pthread_join); +#ifdef __EMSCRIPTEN__ // XXX Emscripten add an extra alias for LSan +weak_alias(__pthread_join, emscripten_builtin_pthread_join); +#endif diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c index 522dd076..53caad40 100644 --- a/src/thread/pthread_key_create.c +++ b/src/thread/pthread_key_create.c @@ -57,10 +57,13 @@ int __pthread_key_delete(pthread_key_t k) __block_app_sigs(&set); __pthread_rwlock_wrlock(&key_lock); + // TODO(sbc): Implement circular list of threads + /* __tl_lock(); do td->tsd[k] = 0; while ((td=td->next)!=self); __tl_unlock(); + */ keys[k] = 0; diff --git a/src/thread/pthread_rwlock_timedwrlock.c b/src/thread/pthread_rwlock_timedwrlock.c index 60a2902b..b147cb92 100644 --- a/src/thread/pthread_rwlock_timedwrlock.c +++ b/src/thread/pthread_rwlock_timedwrlock.c @@ -5,7 +5,7 @@ int __pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct tim #ifdef __EMSCRIPTEN__ /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. /// If attempting to lock the write lock that we already own, error out. - if (rw->_rw_wr_owner == (void *)pthread_self()) return EDEADLK; + if (rw->_rw_wr_owner == __pthread_self()->tid) return EDEADLK; #endif int r, t; @@ -27,7 +27,7 @@ int __pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct tim #ifdef __EMSCRIPTEN__ /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. /// Mark this thread as the owner of this write lock. - rw->_rw_wr_owner = (void *)pthread_self(); + rw->_rw_wr_owner = __pthread_self()->tid; #endif return r; } diff --git a/src/thread/pthread_rwlock_trywrlock.c b/src/thread/pthread_rwlock_trywrlock.c index d03cad43..e275bdaf 100644 --- a/src/thread/pthread_rwlock_trywrlock.c +++ b/src/thread/pthread_rwlock_trywrlock.c @@ -6,7 +6,7 @@ int __pthread_rwlock_trywrlock(pthread_rwlock_t *rw) #ifdef __EMSCRIPTEN__ /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. /// Mark this thread to own the write lock, to ignore multiple attempts to lock. - rw->_rw_wr_owner = (void *)pthread_self(); + rw->_rw_wr_owner = __pthread_self()->tid; #endif return 0; } diff --git a/src/thread/pthread_rwlock_unlock.c b/src/thread/pthread_rwlock_unlock.c index 34879145..7a55a085 100644 --- a/src/thread/pthread_rwlock_unlock.c +++ b/src/thread/pthread_rwlock_unlock.c @@ -7,7 +7,7 @@ int __pthread_rwlock_unlock(pthread_rwlock_t *rw) #ifdef __EMSCRIPTEN__ /// XXX Emscripten: The spec allows detecting when multiple write locks would deadlock, which we do here to avoid hangs. /// Mark this thread to not own the write lock anymore. - if (rw->_rw_wr_owner == (void *)pthread_self()) rw->_rw_wr_owner = 0; + if (rw->_rw_wr_owner == __pthread_self()->tid) rw->_rw_wr_owner = 0; #endif do { diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index a5cb0a87..e84c67d4 100644 --- a/src/time/clock_gettime.c +++ b/src/time/clock_gettime.c @@ -59,10 +59,15 @@ _Static_assert(CLOCK_MONOTONIC == __WASI_CLOCKID_MONOTONIC, "monotonic clock mus int __clock_gettime(clockid_t clk, struct timespec *ts) { __wasi_timestamp_t timestamp; + // See https://github.com/bytecodealliance/wasmtime/issues/3714 + if (clk > __WASI_CLOCKID_THREAD_CPUTIME_ID || clk < 0) { + errno = EINVAL; + return -1; + } if (__wasi_syscall_ret(__wasi_clock_time_get(clk, 1, ×tamp))) { return -1; } - *ts = __wasi_timestamp_to_timespec(timestamp); + *ts = __wasi_timestamp_to_timespec(timestamp); return 0; } #else // __EMSCRIPTEN__ diff --git a/src/time/clock_nanosleep.c b/src/time/clock_nanosleep.c index 434fc493..7ad2aba1 100644 --- a/src/time/clock_nanosleep.c +++ b/src/time/clock_nanosleep.c @@ -16,7 +16,18 @@ int __clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, stru if (!req || req->tv_nsec < 0 || req->tv_nsec > 999999999L || req->tv_sec < 0) { return EINVAL; } - emscripten_thread_sleep(req->tv_sec * 1000.0 + req->tv_nsec / 1e6); + struct timespec sleep_for = *req; + if (flags & TIMER_ABSTIME) { + struct timespec now; + clock_gettime(clk, &now); + if (now.tv_sec > req->tv_sec || (now.tv_sec == req->tv_sec && now.tv_nsec >= req->tv_nsec)) { + // The requested time has already passed + return 0; + } + sleep_for.tv_sec = req->tv_sec - now.tv_sec; + sleep_for.tv_nsec = req->tv_nsec - now.tv_nsec; + } + emscripten_thread_sleep(sleep_for.tv_sec * 1000.0 + sleep_for.tv_nsec / 1e6); return 0; #else #ifdef SYS_clock_nanosleep_time64 diff --git a/src/time/localtime_r.c b/src/time/localtime_r.c index 874c0b69..ac0f3705 100644 --- a/src/time/localtime_r.c +++ b/src/time/localtime_r.c @@ -4,13 +4,18 @@ struct tm *__localtime_r(const time_t *restrict t, struct tm *restrict tm) { + /* Unlike other musl targets emscripten uses `int` for time_t rather than + * `int64`, so these checks don't apply (they rightly trigger + * `autological-constant-out-of-range-compare` warnings). + * TODO(sbc): Remove this if/when we switch to using int64 too. */ +#ifndef __EMSCRIPTEN__ /* Reject time_t values whose year would overflow int because * __secs_to_zone cannot safely handle them. */ - // XXX EMSCRIPTEN: add casts to (long long) to avoid a new clang warning - if (((long long)*t) < INT_MIN * 31622400LL || ((long long)*t) > INT_MAX * 31622400LL) { + if (*t < INT_MIN * 31622400LL || *t > INT_MAX * 31622400LL) { errno = EOVERFLOW; return 0; } +#endif __secs_to_zone(*t, 0, &tm->tm_isdst, &tm->__tm_gmtoff, 0, &tm->__tm_zone); if (__secs_to_tm((long long)*t + tm->__tm_gmtoff, tm) < 0) { errno = EOVERFLOW; diff --git a/src/unistd/fchown.c b/src/unistd/fchown.c index e8959b1d..a3281895 100644 --- a/src/unistd/fchown.c +++ b/src/unistd/fchown.c @@ -10,12 +10,12 @@ int fchown(int fd, uid_t uid, gid_t gid) { int ret = __syscall(SYS_fchown, fd, uid, gid); #if __EMSCRIPTEN__ - if (ret != -EBADF || !__wasi_fd_is_valid(fd)) - return __syscall_ret(ret); + // We can't continue onwards to try the /proc/fd/NNN approach that musl does, + // as we don't support that much of POSIX. + return __syscall_ret(ret); #else if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0) return __syscall_ret(ret); -#endif char buf[15+3*sizeof(int)]; __procfdname(buf, fd); @@ -24,5 +24,5 @@ int fchown(int fd, uid_t uid, gid_t gid) #else return syscall(SYS_fchownat, AT_FDCWD, buf, uid, gid, 0); #endif - +#endif // EMSCRIPTEN } From 25085c85a0055a94919bf522c96803db7c885431 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 7 Sep 2022 18:41:09 -0400 Subject: [PATCH 129/297] fix fwprintf missing output to open_wmemstream FILEs open_wmemstream's write method was written assuming no buffering, since it sets the FILE up with buf_len of zero in order to avoid issues with position/seeking. however, as a consequence of commit bd57e2b43a5b56c00a82adbde0e33e5820c81164, a FILE being written to by the printf core has a temporary local buffer for the duration of the operation if it was unbuffered to begin with. since this was disregarded by the wide memstream's write method, output produced through this code path, particularly numeric fields, was missing from the output wchar buffer. copy the equivalent logic for using the buffered data from the byte-oriented open_memstream. --- src/stdio/open_wmemstream.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/stdio/open_wmemstream.c b/src/stdio/open_wmemstream.c index ed1b561d..b8ae4a79 100644 --- a/src/stdio/open_wmemstream.c +++ b/src/stdio/open_wmemstream.c @@ -40,8 +40,12 @@ static off_t wms_seek(FILE *f, off_t off, int whence) static size_t wms_write(FILE *f, const unsigned char *buf, size_t len) { struct cookie *c = f->cookie; - size_t len2; + size_t len2 = f->wpos - f->wbase; wchar_t *newbuf; + if (len2) { + f->wpos = f->wbase; + if (wms_write(f, f->wbase, len2) < len2) return 0; + } if (len + c->pos >= c->space) { len2 = 2*c->space+1 | c->pos+len+1; if (len2 > SSIZE_MAX/4) return 0; From 6f3ead0ae16deb9f0004b275e29a276c9712ee3c Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 12 Sep 2022 08:30:36 -0400 Subject: [PATCH 130/297] process DT_RELR relocations in ldso-startup/static-pie commit d32dadd60efb9d3b255351a3b532f8e4c3dd0db1 added DT_RELR processing for programs and shared libraries processed by the dynamic linker, but left them unsupported in the dynamic linker itseld and in static pie binaries, which self-relocate via code in dlstart.c. add the equivalent processing to this code path so that there are not arbitrary restrictions on where the new packed relative relocation form can be used. --- ldso/dlstart.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ldso/dlstart.c b/ldso/dlstart.c index 20d50f2c..259f5e18 100644 --- a/ldso/dlstart.c +++ b/ldso/dlstart.c @@ -140,6 +140,21 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv) size_t *rel_addr = (void *)(base + rel[0]); *rel_addr = base + rel[2]; } + + rel = (void *)(base+dyn[DT_RELR]); + rel_size = dyn[DT_RELRSZ]; + size_t *relr_addr = 0; + for (; rel_size; rel++, rel_size-=sizeof(size_t)) { + if ((rel[0]&1) == 0) { + relr_addr = (void *)(base + rel[0]); + *relr_addr++ += base; + } else { + for (size_t i=0, bitmap=rel[0]; bitmap>>=1; i++) + if (bitmap&1) + relr_addr[i] += base; + relr_addr += 8*sizeof(size_t)-1; + } + } #endif stage2_func dls2; From bf14ef193b4203aa9a8b173faeeea06d98397f65 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 12 Sep 2022 08:38:03 -0400 Subject: [PATCH 131/297] re-enable vdso clock_gettime on arm (32-bit) with workaround commit 4486c579cbf0d989080705f515d08cb48636ba88 disabled vdso clock_gettime on arm due to a Linux kernel bug that was not understood at the time, whereby the vdso function silently produced catastrophically wrong results on some systems. since then, the bug was tracked down to the way the arm kernel disabled use of vdso clock_gettime on kernels where the necessary timer was not available or was disabled. it simply patched out the symbols, but it only did this for the legacy time32 functions, and left the time64 function in place but non-operational. kernel commit 4405bdf3c57ec28d606bdf5325f1167505bfdcd4 (first present in 5.8) provided the fix. if this were a bug that impacted all users of the broken kernel versions, we could probably ignore it and assume it had been patched or replaced. however, it's very possible that these kernels appear in the wild in devices running time32 userspace (glibc, musl 1.1.x, or some other environment) where they appear to work fine, but where our new binaries would fail catastrophically if we used the time64 vdso function. since the kernel has not (yet?) given us a way to probe for the working time64 vdso function semantically, we work around the problem by refusing to use the time64 one unless the time32 one is also present. this will revert to not using vdso at all if the time32 one is ever removed, but at least that's safe against wrong results and is just a missed optimization. --- arch/arm/syscall_arch.h | 7 +++++++ src/time/clock_gettime.c | 3 +++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/syscall_arch.h b/arch/arm/syscall_arch.h index a877b2cf..624e992e 100644 --- a/arch/arm/syscall_arch.h +++ b/arch/arm/syscall_arch.h @@ -101,3 +101,10 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo #define SYSCALL_FADVISE_6_ARG #define SYSCALL_IPC_BROKEN_MODE + +#define VDSO_USEFUL +#define VDSO_CGT32_SYM "__vdso_clock_gettime" +#define VDSO_CGT32_VER "LINUX_2.6" +#define VDSO_CGT_SYM "__vdso_clock_gettime64" +#define VDSO_CGT_VER "LINUX_2.6" +#define VDSO_CGT_WORKAROUND 1 diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index c7e66a51..4d2ec22f 100644 --- a/src/time/clock_gettime.c +++ b/src/time/clock_gettime.c @@ -42,6 +42,9 @@ static int cgt_init(clockid_t clk, struct timespec *ts) p = cgt_time32_wrap; } } +#ifdef VDSO_CGT_WORKAROUND + if (!__vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM)) p = 0; +#endif #endif int (*f)(clockid_t, struct timespec *) = (int (*)(clockid_t, struct timespec *))p; From 3ad3fa962efee12067d68c3405a537dce156a7ac Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Thu, 8 Sep 2022 12:18:56 +0300 Subject: [PATCH 132/297] fix thread leak on timer_create(SIGEV_THREAD) failure After commit 5b74eed3b301e2227385f3bf26d3bb7c2d822cf8 the timer thread doesn't check whether timer_create() actually created the timer, proceeding to wait for a signal that might never arrive. We can't fix this by simply checking for a negative timer_id after pthread_barrier_wait() because we have no way to distinguish a timer creation failure and a request to delete a timer with INT_MAX id if it happens to arrive quickly (a variation of this bug existed before 5b74eed3b301e2227385f3bf26d3bb7c2d822cf8, where the timer would be leaked in this case). So (ab)use cancel field of pthread_t instead. --- src/time/timer_create.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 4bef2390..cd32c945 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -43,6 +43,8 @@ static void *start(void *arg) union sigval val = args->sev->sigev_value; pthread_barrier_wait(&args->b); + if (self->cancel) + return 0; for (;;) { siginfo_t si; while (sigwaitinfo(SIGTIMER_SET, &si) < 0); @@ -113,8 +115,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict ksev.sigev_signo = SIGTIMER; ksev.sigev_notify = SIGEV_THREAD_ID; ksev.sigev_tid = td->tid; - if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) + if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) { timerid = -1; + td->cancel = 1; + } td->timer_id = timerid; pthread_barrier_wait(&args.b); if (timerid < 0) return -1; From 001c1afb0a08912a6fdc7c462c53e221de4bc9f1 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 19 Sep 2022 15:38:00 -0400 Subject: [PATCH 133/297] res_mkquery: error out on consecutive final dots in name the main loop already errors out on zero-length labels within the name, but terminates before having a chance to check for an erroneous final zero-length label, instead producing a malformed query packet with a '.' byte instead of the terminating zero. rather than poke at the look logic, simply detect this condition early and error out without doing anything. this also fixes behavior of getaddrinfo when "." appears in the search domain list, which produces a name ending in ".." after concatenation, at least in the sense of no longer emitting malformed packets on the network. however, due to other issues, the lookup will still fail. --- src/network/res_mkquery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/res_mkquery.c b/src/network/res_mkquery.c index 33f50cb9..614bf786 100644 --- a/src/network/res_mkquery.c +++ b/src/network/res_mkquery.c @@ -13,6 +13,7 @@ int __res_mkquery(int op, const char *dname, int class, int type, int n; if (l && dname[l-1]=='.') l--; + if (l && dname[l-1]=='.') return -1; n = 17+l+!!l; if (l>253 || buflen15u || class>255u || type>255u) return -1; From 1e7fb12f775a3e599be08da9835422d96c56f479 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 19 Sep 2022 15:51:04 -0400 Subject: [PATCH 134/297] dns: treat names rejected by res_mkquery as nonexistent rather than error this distinction only affects search, but allows search to continue when concatenating one of the search domains onto the requested name produces a result that's not valid. this can happen when the concatenation is too long, or one of the search list entries is itself not valid. as a consequence of this change, having "." in the search domains list will now be ignored/skipped rather than making the lookup abort with no results (due to producing a concatenation ending in ".."). this behavior could be changed later if needed. --- src/network/lookup_name.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index b5232ce8..bec6ba22 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -153,7 +153,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static qlens[nq] = __res_mkquery(0, name, 1, afrr[i].rr, 0, 0, 0, qbuf[nq], sizeof *qbuf); if (qlens[nq] == -1) - return EAI_NONAME; + return 0; qbuf[nq][3] = 0; /* don't need AD flag */ /* Ensure query IDs are distinct. */ if (nq && qbuf[nq][0] == qbuf[0][0]) From f081d5336a80b68d3e1bed789cc373c5c3d6699b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 19 Sep 2022 19:02:40 -0400 Subject: [PATCH 135/297] fix return value of gethostnbyname[2]_r on result not found these functions are horribly underspecified, inconsistent between historical systems, and should never have been included. however, the signatures we have match the glibc ones, and the glibc behavior is to treat NxDomain and NODATA results as a success condition, not an ENOENT error. --- src/network/gethostbyname2_r.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c index fc894877..f012ec2f 100644 --- a/src/network/gethostbyname2_r.c +++ b/src/network/gethostbyname2_r.c @@ -22,7 +22,7 @@ int gethostbyname2_r(const char *name, int af, if (cnt<0) switch (cnt) { case EAI_NONAME: *err = HOST_NOT_FOUND; - return ENOENT; + return 0; case EAI_AGAIN: *err = TRY_AGAIN; return EAGAIN; From f9827fc7da55c7b03ea5f36598ce8782c03e9d6e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 19 Sep 2022 19:09:02 -0400 Subject: [PATCH 136/297] remove impossible error case from gethostbyname2_r EAI_MEMORY is not possible because the resolver backend does not allocate. if it did, it would be necessary for us to explicitly return ENOMEM as the error, since errno is not guaranteed to reflect the error cause except in the case of EAI_SYSTEM, so the existing code was not correct anyway. --- src/network/gethostbyname2_r.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c index f012ec2f..c9f3acc4 100644 --- a/src/network/gethostbyname2_r.c +++ b/src/network/gethostbyname2_r.c @@ -30,7 +30,6 @@ int gethostbyname2_r(const char *name, int af, case EAI_FAIL: *err = NO_RECOVERY; return EBADMSG; - case EAI_MEMORY: case EAI_SYSTEM: *err = NO_RECOVERY; return errno; From dc9285ad1dc19349c407072cc48ba70dab86de45 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 19 Sep 2022 19:12:09 -0400 Subject: [PATCH 137/297] fix error cases in gethostbyaddr_r EAI_MEMORY is not possible (but would not provide errno if it were) and EAI_FAIL does not provide errno. treat the latter as EBADMSG to match how it's handled in gethostbyname2_r (it indicates erroneous or failure response from the nameserver). --- src/network/gethostbyaddr_r.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/gethostbyaddr_r.c b/src/network/gethostbyaddr_r.c index 0f1e61aa..ceaf3935 100644 --- a/src/network/gethostbyaddr_r.c +++ b/src/network/gethostbyaddr_r.c @@ -54,9 +54,10 @@ int gethostbyaddr_r(const void *a, socklen_t l, int af, case EAI_OVERFLOW: return ERANGE; default: - case EAI_MEMORY: - case EAI_SYSTEM: case EAI_FAIL: + *err = NO_RECOVERY; + return EBADMSG; + case EAI_SYSTEM: *err = NO_RECOVERY; return errno; case 0: From 85050ac5a2677a8ebf2722e93b5c037ec675c036 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 19 Sep 2022 20:10:10 -0400 Subject: [PATCH 138/297] getaddrinfo: add EAI_NODATA error code to distinguish NODATA vs NxDomain this was apparently omitted long ago out of a lack of understanding of its importance and the fact that POSIX doesn't specify it. despite not being officially standardized, however, it turns out that at least AIX, glibc, NetBSD, OpenBSD, QNX, and Solaris document and support it. in certain usage cases, such as implementing a DNS gateway on top of the stub resolver interfaces, it's necessary to distinguish the case where a name does not exit (NxDomain) from one where it exists but has no addresses (or other records) of the requested type (NODATA). in fact, even the legacy gethostbyname API had this distinction, which we were previously unable to support correctly because the backend lacked it. apart from fixing an important functionality gap, adding this distinction helps clarify to users how search domain fallback works (falling back in cases corresponding to EAI_NONAME, not in ones corresponding to EAI_NODATA), a topic that has been a source of ongoing confusion and frustration. as a result of this change, EAI_NONAME is no longer a valid universal error code for getaddrinfo in the case where AI_ADDRCONFIG has suppressed use of all address families. in order to return an accurate result in this case, getaddrinfo is modified to still perform at least one lookup. this will almost surely fail (with a network error, since there is no v4 or v6 network to query DNS over) unless a result comes from the hosts file or from ip literal parsing, but in case it does succeed, the result is replaced by EAI_NODATA. glibc has a related error code, EAI_ADDRFAMILY, that could be used for the AI_ADDRCONFIG case and certain NODATA cases, but distinguishing them properly in full generality seems to require additional DNS queries that are otherwise not useful. on glibc, it is only used for ip literals with mismatching family, not for DNS or hosts file results where the name has addresses only in the opposite family. since this seems misleading and inconsistent, and since EAI_NODATA already covers the semantic case where the "name" exists but doesn't have any addresses in the requested family, we do not adopt EAI_ADDRFAMILY at this time. this could be changed at some point if desired, but the logic for getting all the corner cases with AI_ADDRCONFIG right is slightly nontrivial. --- include/netdb.h | 1 + src/network/gai_strerror.c | 2 +- src/network/getaddrinfo.c | 5 ++++- src/network/gethostbyname2_r.c | 3 +++ src/network/lookup_ipliteral.c | 4 ++-- src/network/lookup_name.c | 4 ++-- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/netdb.h b/include/netdb.h index d096c781..3af065e2 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -44,6 +44,7 @@ struct addrinfo { #define EAI_NONAME -2 #define EAI_AGAIN -3 #define EAI_FAIL -4 +#define EAI_NODATA -5 #define EAI_FAMILY -6 #define EAI_SOCKTYPE -7 #define EAI_SERVICE -8 diff --git a/src/network/gai_strerror.c b/src/network/gai_strerror.c index 9596580e..56b71503 100644 --- a/src/network/gai_strerror.c +++ b/src/network/gai_strerror.c @@ -6,7 +6,7 @@ static const char msgs[] = "Name does not resolve\0" "Try again\0" "Non-recoverable error\0" - "Unknown error\0" + "Name has no usable address\0" "Unrecognized address family or invalid length\0" "Unrecognized socket type\0" "Unrecognized service\0" diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c index 9df045f6..64ad259a 100644 --- a/src/network/getaddrinfo.c +++ b/src/network/getaddrinfo.c @@ -16,6 +16,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru char canon[256], *outcanon; int nservs, naddrs, nais, canon_len, i, j, k; int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0; + int no_family = 0; struct aibuf *out; if (!host && !serv) return EAI_NONAME; @@ -82,7 +83,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru default: return EAI_SYSTEM; } - if (family == tf[i]) return EAI_NONAME; + if (family == tf[i]) no_family = 1; family = tf[1-i]; } } @@ -93,6 +94,8 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru naddrs = __lookup_name(addrs, canon, host, family, flags); if (naddrs < 0) return naddrs; + if (no_family) return EAI_NODATA; + nais = nservs * naddrs; canon_len = strlen(canon); out = calloc(1, nais * sizeof(*out) + canon_len + 1); diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c index c9f3acc4..a5eb67fe 100644 --- a/src/network/gethostbyname2_r.c +++ b/src/network/gethostbyname2_r.c @@ -23,6 +23,9 @@ int gethostbyname2_r(const char *name, int af, case EAI_NONAME: *err = HOST_NOT_FOUND; return 0; + case EAI_NODATA: + *err = NO_DATA; + return 0; case EAI_AGAIN: *err = TRY_AGAIN; return EAGAIN; diff --git a/src/network/lookup_ipliteral.c b/src/network/lookup_ipliteral.c index 2fddab73..1e766206 100644 --- a/src/network/lookup_ipliteral.c +++ b/src/network/lookup_ipliteral.c @@ -15,7 +15,7 @@ int __lookup_ipliteral(struct address buf[static 1], const char *name, int famil struct in6_addr a6; if (__inet_aton(name, &a4) > 0) { if (family == AF_INET6) /* wrong family */ - return EAI_NONAME; + return EAI_NODATA; memcpy(&buf[0].addr, &a4, sizeof a4); buf[0].family = AF_INET; buf[0].scopeid = 0; @@ -34,7 +34,7 @@ int __lookup_ipliteral(struct address buf[static 1], const char *name, int famil if (inet_pton(AF_INET6, name, &a6) <= 0) return 0; if (family == AF_INET) /* wrong family */ - return EAI_NONAME; + return EAI_NODATA; memcpy(&buf[0].addr, &a6, sizeof a6); buf[0].family = AF_INET6; diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index bec6ba22..37d481f9 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -79,7 +79,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati case 0: continue; default: - badfam = EAI_NONAME; + badfam = EAI_NODATA; break; } @@ -175,7 +175,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); if (ctx.cnt) return ctx.cnt; - return EAI_NONAME; + return EAI_NODATA; } static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) From c87d75f2aa6fde49a99cf3287e535a14f354f781 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 21 Sep 2022 18:49:53 -0400 Subject: [PATCH 139/297] adapt res_msend DNS query core for working with multiple sockets this is groundwork for TCP fallback support, but does not itself change behavior in any way. --- src/network/res_msend.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 9adaea13..98e6d8a3 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -16,7 +16,9 @@ static void cleanup(void *p) { - __syscall(SYS_close, (intptr_t)p); + struct pollfd *pfd = p; + for (int i=0; pfd[i].fd >= -1; i++) + if (pfd[i].fd >= 0) __syscall(SYS_close, pfd[i].fd); } static unsigned long mtime() @@ -44,7 +46,7 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, int next; int i, j; int cs; - struct pollfd pfd; + struct pollfd pfd[nqueries+2]; unsigned long t0, t1, t2; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); @@ -92,7 +94,12 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, * yield either no reply (indicated by zero length) or an answer * packet which is up to the caller to interpret. */ - pthread_cleanup_push(cleanup, (void *)(intptr_t)fd); + for (i=0; i= 0) { From e2e9517607f67c1e23c059769b19bf4270d22123 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 22 Sep 2022 12:41:23 -0400 Subject: [PATCH 140/297] res_send: use a temp buffer if caller's buffer is under 512 bytes for extremely small buffer sizes, the DNS query core in __res_msend may malfunction completely, being unable to get even the headers to determine the response code. but there is also a problem for reasonable sizes under 512 bytes: __res_msend is unable to determine if the udp answer was truncated at the recv layer, in which case it may be incomplete, and res_send is then unable to honor its contract to return the length of the full, non-truncated answer. at present, res_send does not honor that contract anyway when the full answer would exceed 512 bytes, since there is no tcp fallback, but this change at least makes it consistent in a context where this is the only "full answer" to be had. --- src/network/res_send.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/network/res_send.c b/src/network/res_send.c index ee4abf1f..9593164d 100644 --- a/src/network/res_send.c +++ b/src/network/res_send.c @@ -1,8 +1,16 @@ #include +#include int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen) { - int r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen); + int r; + if (anslen < 512) { + unsigned char buf[512]; + r = __res_send(msg, msglen, buf, sizeof buf); + if (r >= 0) memcpy(answer, buf, r < anslen ? r : anslen); + return r; + } + r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen); return r<0 || !anslen ? -1 : anslen; } From 51d4669fb97782f6a66606da852b5afd49a08001 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 22 Sep 2022 14:17:05 -0400 Subject: [PATCH 141/297] dns: implement tcp fallback in __res_msend query core tcp fallback was originally deemed unwanted and unnecessary, since we aim to return a bounded-size result from getaddrinfo anyway and normally plenty of address records fit in the 512-byte udp dns limit. however, this turned out to have several problems: - some recursive nameservers truncate by omitting all the answers, rather than sending as many as can fit. - a pathological worst-case CNAME for a worst-case name can fill the entire 512-byte space with just the two names, leaving no room for any addresses. - the res_* family of interfaces allow querying of non-address records such as TLSA (DANE), TXT, etc. which can be very large. for many of these, it's critical that the caller see the whole RRset. also, res_send/res_query are specified to return the complete, untruncated length so that the caller can retry with an appropriately-sized buffer. determining this is not possible without tcp. so, it's time to add tcp fallback. the fallback strategy implemented here uses one tcp socket per question (1 or 2 questions), initiated via tcp fastopen when possible. the connection is made to the nameserver that issued the truncated answer. right now, fallback happens unconditionally when truncation is seen. this can, and may later be, relaxed for queries made by the getaddrinfo system, since it will only use a bounded number of results anyway. retry is not attempted again after failure over tcp. the logic could easily be adapted to do that, but it's of questionable value, since the tcp stack automatically handles retransmission and the successs answer with TC=1 over udp strongly suggests that the nameserver has the full answer ready to give. further retry is likely just "take longer to fail". --- src/network/res_msend.c | 119 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 98e6d8a3..1e76886a 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -29,6 +30,51 @@ static unsigned long mtime() + ts.tv_nsec / 1000000; } +static int start_tcp(struct pollfd *pfd, int family, const void *sa, socklen_t sl, const unsigned char *q, int ql) +{ + struct msghdr mh = { + .msg_name = (void *)sa, + .msg_namelen = sl, + .msg_iovlen = 2, + .msg_iov = (struct iovec [2]){ + { .iov_base = (uint8_t[]){ ql>>8, ql }, .iov_len = 2 }, + { .iov_base = (void *)q, .iov_len = ql } } + }; + int r; + int fd = socket(family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + pfd->fd = fd; + pfd->events = POLLOUT; + if (!setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, + &(int){1}, sizeof(int))) { + r = sendmsg(fd, &mh, MSG_FASTOPEN|MSG_NOSIGNAL); + if (r == ql+2) pfd->events = POLLIN; + if (r >= 0) return r; + if (errno == EINPROGRESS) return 0; + } + r = connect(fd, sa, sl); + if (!r || errno == EINPROGRESS) return 0; + close(fd); + pfd->fd = -1; + return -1; +} + +static void step_mh(struct msghdr *mh, size_t n) +{ + /* Adjust iovec in msghdr to skip first n bytes. */ + while (mh->msg_iovlen && n >= mh->msg_iov->iov_len) { + n -= mh->msg_iov->iov_len; + mh->msg_iov++; + mh->msg_iovlen--; + } + if (!mh->msg_iovlen) return; + mh->msg_iov->iov_base = (char *)mh->msg_iov->iov_base + n; + mh->msg_iov->iov_len -= n; +} + +/* Internal contract for __res_msend[_rc]: asize must be >=512, nqueries + * must be sufficiently small to be safe as VLA size. In practice it's + * either 1 or 2, anyway. */ + int __res_msend_rc(int nqueries, const unsigned char *const *queries, const int *qlens, unsigned char *const *answers, int *alens, int asize, const struct resolvconf *conf) @@ -47,6 +93,9 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, int i, j; int cs; struct pollfd pfd[nqueries+2]; + int qpos[nqueries], apos[nqueries]; + unsigned char alen_buf[nqueries][2]; + int r; unsigned long t0, t1, t2; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); @@ -125,6 +174,11 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, t1 = t2 - retry_interval; for (; t2-t0 < timeout; t2=mtime()) { + /* This is the loop exit condition: that all queries + * have an accepted answer. */ + for (i=0; i0; i++); + if (i==nqueries) break; + if (t2-t1 >= retry_interval) { /* Query all configured namservers in parallel */ for (i=0; i= 0) { /* Ignore non-identifiable packets */ @@ -181,12 +236,72 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, else memcpy(answers[i], answers[next], rlen); - if (next == nqueries) goto out; + /* Ignore further UDP if all slots full or TCP-mode */ + if (next == nqueries) pfd[nqueries].events = 0; + + /* If answer is truncated (TC bit), fallback to TCP */ + if (answers[i][2] & 2) { + alens[i] = -1; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); + r = start_tcp(pfd+i, family, ns+j, sl, queries[i], qlens[i]); + pthread_setcancelstate(cs, 0); + if (r >= 0) { + qpos[i] = r; + apos[i] = 0; + } + continue; + } + } + + for (i=0; i>8, qlens[i] }, .iov_len = 2 }, + { .iov_base = (void *)queries[i], .iov_len = qlens[i] } } + }; + step_mh(&mh, qpos[i]); + r = sendmsg(pfd[i].fd, &mh, MSG_NOSIGNAL); + if (r < 0) goto out; + qpos[i] += r; + if (qpos[i] == qlens[i]+2) + pfd[i].events = POLLIN; + } + + for (i=0; i Date: Thu, 22 Sep 2022 18:44:15 -0400 Subject: [PATCH 142/297] arpa/nameser.h: update RR types list our RR type list in arpa/nameser.h was badly outdated, and missing important types for DNSSEC and DANE use, among other things. --- include/arpa/nameser.h | 71 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h index 581925a4..9c1327a1 100644 --- a/include/arpa/nameser.h +++ b/include/arpa/nameser.h @@ -188,6 +188,36 @@ typedef enum __ns_type { ns_t_sink = 40, ns_t_opt = 41, ns_t_apl = 42, + ns_t_ds = 43, + ns_t_sshfp = 44, + ns_t_ipseckey = 45, + ns_t_rrsig = 46, + ns_t_nsec = 47, + ns_t_dnskey = 48, + ns_t_dhcid = 49, + ns_t_nsec3 = 50, + ns_t_nsec3param = 51, + ns_t_tlsa = 52, + ns_t_smimea = 53, + ns_t_hip = 55, + ns_t_ninfo = 56, + ns_t_rkey = 57, + ns_t_talink = 58, + ns_t_cds = 59, + ns_t_cdnskey = 60, + ns_t_openpgpkey = 61, + ns_t_csync = 62, + ns_t_spf = 99, + ns_t_uinfo = 100, + ns_t_uid = 101, + ns_t_gid = 102, + ns_t_unspec = 103, + ns_t_nid = 104, + ns_t_l32 = 105, + ns_t_l64 = 106, + ns_t_lp = 107, + ns_t_eui48 = 108, + ns_t_eui64 = 109, ns_t_tkey = 249, ns_t_tsig = 250, ns_t_ixfr = 251, @@ -196,6 +226,11 @@ typedef enum __ns_type { ns_t_maila = 254, ns_t_any = 255, ns_t_zxfr = 256, + ns_t_uri = 256, + ns_t_caa = 257, + ns_t_avc = 258, + ns_t_ta = 32768, + ns_t_dlv = 32769, ns_t_max = 65536 } ns_type; @@ -430,12 +465,48 @@ typedef struct { #define T_NAPTR ns_t_naptr #define T_A6 ns_t_a6 #define T_DNAME ns_t_dname +#define T_DS ns_t_ds +#define T_SSHFP ns_t_sshfp +#define T_IPSECKEY ns_t_ipseckey +#define T_RRSIG ns_t_rrsig +#define T_NSEC ns_t_nsec +#define T_DNSKEY ns_t_dnskey +#define T_DHCID ns_t_dhcid +#define T_NSEC3 ns_t_nsec3 +#define T_NSEC3PARAM ns_t_nsec3param +#define T_TLSA ns_t_tlsa +#define T_SMIMEA ns_t_smimea +#define T_HIP ns_t_hip +#define T_NINFO ns_t_ninfo +#define T_RKEY ns_t_rkey +#define T_TALINK ns_t_talink +#define T_CDS ns_t_cds +#define T_CDNSKEY ns_t_cdnskey +#define T_OPENPGPKEY ns_t_openpgpkey +#define T_CSYNC ns_t_csync +#define T_SPF ns_t_spf +#define T_UINFO ns_t_uinfo +#define T_UID ns_t_uid +#define T_GID ns_t_gid +#define T_UNSPEC ns_t_unspec +#define T_NID ns_t_nid +#define T_L32 ns_t_l32 +#define T_L64 ns_t_l64 +#define T_LP ns_t_lp +#define T_EUI48 ns_t_eui48 +#define T_EUI64 ns_t_eui64 +#define T_TKEY ns_t_tkey #define T_TSIG ns_t_tsig #define T_IXFR ns_t_ixfr #define T_AXFR ns_t_axfr #define T_MAILB ns_t_mailb #define T_MAILA ns_t_maila #define T_ANY ns_t_any +#define T_URI ns_t_uri +#define T_CAA ns_t_caa +#define T_AVC ns_t_avc +#define T_TA ns_t_ta +#define T_DLV ns_t_dlv #define C_IN ns_c_in #define C_CHAOS ns_c_chaos From 8c408937da4cb7f6460972a0f645694304de3c8c Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 22 Sep 2022 19:11:48 -0400 Subject: [PATCH 143/297] getaddrinfo dns lookup: use larger answer buffer to handle long CNAMEs the size of 512 is not sufficient to get at least one address in the worst case where the name is at or near max length and resolves to a CNAME at or near max length. prior to tcp fallback, there was nothing we could do about this case anyway, but now it's fixable. the new limit 768 is chosen so as to admit roughly the number of addresses with a worst-case CNAME as could fit for a worst-case name that's not a CNAME in the old 512-byte limit. outside of this worst-case, the number of addresses that might be obtained is increased. MAXADDRS (48) was originally chosen as an upper bound on the combined number of A and AAAA records that could fit in 512-byte packets (31 and 17, respectively). it is not increased at this time. so as to prevent a situation where the A records consume almost all of these slots (at 768 bytes, a "best-case" name can fit almost 47 A records), the order of parsing is swapped to process AAAA first. this ensures roughly half of the slots are available to each address family. --- src/network/lookup_name.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index 37d481f9..4a6999cb 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -108,6 +108,8 @@ struct dpc_ctx { #define RR_CNAME 5 #define RR_AAAA 28 +#define ABUF_SIZE 768 + static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) { char tmp[256]; @@ -127,7 +129,7 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const memcpy(ctx->addrs[ctx->cnt++].addr, data, 16); break; case RR_CNAME: - if (__dn_expand(packet, (const unsigned char *)packet + 512, + if (__dn_expand(packet, (const unsigned char *)packet + ABUF_SIZE, data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp)) strcpy(ctx->canon, tmp); break; @@ -137,7 +139,7 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, const struct resolvconf *conf) { - unsigned char qbuf[2][280], abuf[2][512]; + unsigned char qbuf[2][280], abuf[2][ABUF_SIZE]; const unsigned char *qp[2] = { qbuf[0], qbuf[1] }; unsigned char *ap[2] = { abuf[0], abuf[1] }; int qlens[2], alens[2]; @@ -171,7 +173,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static if ((abuf[i][3] & 15) != 0) return EAI_FAIL; } - for (i=0; i=0; i--) __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); if (ctx.cnt) return ctx.cnt; From dec8f0a4fa7aa533c843e6eaec862be674ff3a1a Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 25 Sep 2022 22:48:12 -0400 Subject: [PATCH 144/297] dns query core: detect udp truncation at recv time we already attempt to preclude this case by having res_send use a sufficiently large temporary buffer even if the caller did not provide one as large as or larger than the udp dns max of 512 bytes. however, it's possible that the caller passed a custom-crafted query packet using EDNS0, e.g. to get detailed DNSSEC results, with a larger udp size allowance. I have also seen claims that there are some broken nameservers in the wild that do not honor the dns udp limit of 512 and send large answers without the TC bit set, when the query was not using EDNS. we generally don't aim to support broken nameservers, but in this case both problems, if the latter is even real, have a common solution: using recvmsg instead of recvfrom so we can examine the MSG_TRUNC flag. --- src/network/res_msend.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 1e76886a..11c6aa0e 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -194,9 +194,18 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, /* Wait for a response, or until time to retry */ if (poll(pfd, nqueries+1, t1+retry_interval-t2) <= 0) continue; - while (next < nqueries && - (rlen = recvfrom(fd, answers[next], asize, 0, - (void *)&sa, (socklen_t[1]){sl})) >= 0) { + while (next < nqueries) { + struct msghdr mh = { + .msg_name = (void *)&sa, + .msg_namelen = sl, + .msg_iovlen = 1, + .msg_iov = (struct iovec []){ + { .iov_base = (void *)answers[next], + .iov_len = asize } + } + }; + rlen = recvmsg(fd, &mh, 0); + if (rlen < 0) break; /* Ignore non-identifiable packets */ if (rlen < 4) continue; @@ -240,7 +249,7 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, if (next == nqueries) pfd[nqueries].events = 0; /* If answer is truncated (TC bit), fallback to TCP */ - if (answers[i][2] & 2) { + if ((answers[i][2] & 2) || (mh.msg_flags & MSG_TRUNC)) { alens[i] = -1; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); r = start_tcp(pfd+i, family, ns+j, sl, queries[i], qlens[i]); From 246f1c811448f37a44b41cd8df8d0ef9736d95f4 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 26 Sep 2022 17:14:18 -0400 Subject: [PATCH 145/297] remove LFS64 symbol aliases; replace with dynamic linker remapping originally the namespace-infringing "large file support" interfaces were included as part of glibc-ABI-compat, with the intent that they not be used for linking, since our off_t is and always has been unconditionally 64-bit and since we usually do not aim to support nonstandard interfaces when there is an equivalent standard interface. unfortunately, having the symbols present and available for linking caused configure scripts to detect them and attempt to use them without declarations, producing all the expected ill effects that entails. as a result, commit 2dd8d5e1b8ba1118ff1782e96545cb8a2318592c was made to prevent this, using macros to redirect the LFS64 names to the standard names, conditional on _GNU_SOURCE or _LARGEFILE64_SOURCE. however, this has turned out to be a source of further problems, especially since g++ defines _GNU_SOURCE by default. in particular, the presence of these names as macros breaks a lot of valid code. this commit removes all the LFS64 symbols and replaces them with a mechanism in the dynamic linker symbol lookup failure path to retry with the spurious "64" removed from the symbol name. in the future, if/when the rest of glibc-ABI-compat is moved out of libc, this can be removed. --- compat/time32/__xstat.c | 8 +++---- compat/time32/aio_suspend_time32.c | 2 -- compat/time32/fstat_time32.c | 2 -- compat/time32/fstatat_time32.c | 2 -- compat/time32/lstat_time32.c | 2 -- compat/time32/stat_time32.c | 2 -- ldso/dynlink.c | 34 ++++++++++++++++++++++++++++++ src/aio/aio.c | 7 ------ src/aio/aio_suspend.c | 4 ---- src/aio/lio_listio.c | 2 -- src/dirent/alphasort.c | 2 -- src/dirent/readdir.c | 2 -- src/dirent/readdir_r.c | 2 -- src/dirent/scandir.c | 2 -- src/dirent/versionsort.c | 3 --- src/fcntl/creat.c | 2 -- src/fcntl/open.c | 2 -- src/fcntl/openat.c | 2 -- src/fcntl/posix_fadvise.c | 2 -- src/fcntl/posix_fallocate.c | 2 -- src/legacy/ftw.c | 2 -- src/linux/fallocate.c | 3 --- src/linux/getdents.c | 2 -- src/linux/prlimit.c | 3 --- src/linux/sendfile.c | 2 -- src/misc/getrlimit.c | 2 -- src/misc/lockf.c | 2 -- src/misc/nftw.c | 2 -- src/misc/setrlimit.c | 2 -- src/mman/mmap.c | 2 -- src/regex/glob.c | 3 --- src/stat/__xstat.c | 5 ----- src/stat/fstat.c | 4 ---- src/stat/fstatat.c | 4 ---- src/stat/lstat.c | 4 ---- src/stat/stat.c | 4 ---- src/stat/statvfs.c | 5 ----- src/stdio/fgetpos.c | 2 -- src/stdio/fopen.c | 2 -- src/stdio/freopen.c | 2 -- src/stdio/fseek.c | 2 -- src/stdio/fsetpos.c | 2 -- src/stdio/ftell.c | 2 -- src/stdio/tmpfile.c | 2 -- src/temp/mkostemp.c | 2 -- src/temp/mkostemps.c | 1 - src/temp/mkstemp.c | 2 -- src/temp/mkstemps.c | 2 -- src/unistd/ftruncate.c | 2 -- src/unistd/lseek.c | 1 - src/unistd/mipsn32/lseek.c | 1 - src/unistd/pread.c | 2 -- src/unistd/preadv.c | 2 -- src/unistd/pwrite.c | 2 -- src/unistd/pwritev.c | 2 -- src/unistd/truncate.c | 2 -- src/unistd/x32/lseek.c | 1 - 57 files changed, 38 insertions(+), 135 deletions(-) diff --git a/compat/time32/__xstat.c b/compat/time32/__xstat.c index acfbd3cc..e52b5deb 100644 --- a/compat/time32/__xstat.c +++ b/compat/time32/__xstat.c @@ -3,22 +3,22 @@ struct stat32; -int __fxstat64(int ver, int fd, struct stat32 *buf) +int __fxstat(int ver, int fd, struct stat32 *buf) { return __fstat_time32(fd, buf); } -int __fxstatat64(int ver, int fd, const char *path, struct stat32 *buf, int flag) +int __fxstatat(int ver, int fd, const char *path, struct stat32 *buf, int flag) { return __fstatat_time32(fd, path, buf, flag); } -int __lxstat64(int ver, const char *path, struct stat32 *buf) +int __lxstat(int ver, const char *path, struct stat32 *buf) { return __lstat_time32(path, buf); } -int __xstat64(int ver, const char *path, struct stat32 *buf) +int __xstat(int ver, const char *path, struct stat32 *buf) { return __stat_time32(path, buf); } diff --git a/compat/time32/aio_suspend_time32.c b/compat/time32/aio_suspend_time32.c index ed5119bd..d99cb651 100644 --- a/compat/time32/aio_suspend_time32.c +++ b/compat/time32/aio_suspend_time32.c @@ -7,5 +7,3 @@ int __aio_suspend_time32(const struct aiocb *const cbs[], int cnt, const struct return aio_suspend(cbs, cnt, ts32 ? (&(struct timespec){ .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0); } - -weak_alias(aio_suspend, aio_suspend64); diff --git a/compat/time32/fstat_time32.c b/compat/time32/fstat_time32.c index 3e084398..e5d52022 100644 --- a/compat/time32/fstat_time32.c +++ b/compat/time32/fstat_time32.c @@ -13,5 +13,3 @@ int __fstat_time32(int fd, struct stat32 *restrict st32) if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim)); return r; } - -weak_alias(fstat, fstat64); diff --git a/compat/time32/fstatat_time32.c b/compat/time32/fstatat_time32.c index 85dcb008..31d42e63 100644 --- a/compat/time32/fstatat_time32.c +++ b/compat/time32/fstatat_time32.c @@ -13,5 +13,3 @@ int __fstatat_time32(int fd, const char *restrict path, struct stat32 *restrict if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim)); return r; } - -weak_alias(fstatat, fstatat64); diff --git a/compat/time32/lstat_time32.c b/compat/time32/lstat_time32.c index c1257a14..28cb5a0b 100644 --- a/compat/time32/lstat_time32.c +++ b/compat/time32/lstat_time32.c @@ -13,5 +13,3 @@ int __lstat_time32(const char *restrict path, struct stat32 *restrict st32) if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim)); return r; } - -weak_alias(lstat, lstat64); diff --git a/compat/time32/stat_time32.c b/compat/time32/stat_time32.c index 8c6121da..b154b0f9 100644 --- a/compat/time32/stat_time32.c +++ b/compat/time32/stat_time32.c @@ -13,5 +13,3 @@ int __stat_time32(const char *restrict path, struct stat32 *restrict st32) if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim)); return r; } - -weak_alias(stat, stat64); diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 03f5fd59..7b47b163 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -337,6 +337,39 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def) return find_sym2(dso, s, need_def, 0); } +static struct symdef get_lfs64(const char *name) +{ + static const char *p, lfs64_list[] = + "aio_cancel\0aio_error\0aio_fsync\0aio_read\0aio_return\0" + "aio_suspend\0aio_write\0alphasort\0creat\0fallocate\0" + "fgetpos\0fopen\0freopen\0fseeko\0fsetpos\0fstat\0" + "fstatat\0fstatfs\0fstatvfs\0ftello\0ftruncate\0ftw\0" + "getdents\0getrlimit\0glob\0globfree\0lio_listio\0" + "lockf\0lseek\0lstat\0mkostemp\0mkostemps\0mkstemp\0" + "mkstemps\0mmap\0nftw\0open\0openat\0posix_fadvise\0" + "posix_fallocate\0pread\0preadv\0prlimit\0pwrite\0" + "pwritev\0readdir\0scandir\0sendfile\0setrlimit\0" + "stat\0statfs\0statvfs\0tmpfile\0truncate\0versionsort\0" + "__fxstat\0__fxstatat\0__lxstat\0__xstat\0"; + size_t l; + char buf[16]; + for (l=0; name[l]; l++) { + if (l >= sizeof buf) goto nomatch; + buf[l] = name[l]; + } + if (!strcmp(name, "readdir64_r")) + return find_sym(&ldso, "readdir_r", 1); + if (l<2 || name[l-2]!='6' || name[l-1]!='4') + goto nomatch; + buf[l-=2] = 0; + for (p=lfs64_list; *p; p++) { + if (!strcmp(buf, p)) return find_sym(&ldso, buf, 1); + while (*p) p++; + } +nomatch: + return (struct symdef){ 0 }; +} + static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride) { unsigned char *base = dso->base; @@ -390,6 +423,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri def = (sym->st_info>>4) == STB_LOCAL ? (struct symdef){ .dso = dso, .sym = sym } : find_sym(ctx, name, type==REL_PLT); + if (!def.sym) def = get_lfs64(name); if (!def.sym && (sym->st_shndx != SHN_UNDEF || sym->st_info>>4 != STB_WEAK)) { if (dso->lazy && (type==REL_PLT || type==REL_GOT)) { diff --git a/src/aio/aio.c b/src/aio/aio.c index a1a3e791..fa24f6b6 100644 --- a/src/aio/aio.c +++ b/src/aio/aio.c @@ -409,10 +409,3 @@ void __aio_atfork(int who) map[a][b][c][d] = 0; pthread_rwlock_unlock(&maplock); } - -weak_alias(aio_cancel, aio_cancel64); -weak_alias(aio_error, aio_error64); -weak_alias(aio_fsync, aio_fsync64); -weak_alias(aio_read, aio_read64); -weak_alias(aio_write, aio_write64); -weak_alias(aio_return, aio_return64); diff --git a/src/aio/aio_suspend.c b/src/aio/aio_suspend.c index 1c1060e3..95def796 100644 --- a/src/aio/aio_suspend.c +++ b/src/aio/aio_suspend.c @@ -73,7 +73,3 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec } } } - -#if !_REDIR_TIME64 -weak_alias(aio_suspend, aio_suspend64); -#endif diff --git a/src/aio/lio_listio.c b/src/aio/lio_listio.c index 0799c15d..a672812f 100644 --- a/src/aio/lio_listio.c +++ b/src/aio/lio_listio.c @@ -139,5 +139,3 @@ int lio_listio(int mode, struct aiocb *restrict const *restrict cbs, int cnt, st return 0; } - -weak_alias(lio_listio, lio_listio64); diff --git a/src/dirent/alphasort.c b/src/dirent/alphasort.c index bee672eb..ab2624e2 100644 --- a/src/dirent/alphasort.c +++ b/src/dirent/alphasort.c @@ -5,5 +5,3 @@ int alphasort(const struct dirent **a, const struct dirent **b) { return strcoll((*a)->d_name, (*b)->d_name); } - -weak_alias(alphasort, alphasort64); diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c index 569fc705..5a03b363 100644 --- a/src/dirent/readdir.c +++ b/src/dirent/readdir.c @@ -25,5 +25,3 @@ struct dirent *readdir(DIR *dir) dir->tell = de->d_off; return de; } - -weak_alias(readdir, readdir64); diff --git a/src/dirent/readdir_r.c b/src/dirent/readdir_r.c index e2a818f3..0d5de5f5 100644 --- a/src/dirent/readdir_r.c +++ b/src/dirent/readdir_r.c @@ -25,5 +25,3 @@ int readdir_r(DIR *restrict dir, struct dirent *restrict buf, struct dirent **re *result = buf; return 0; } - -weak_alias(readdir_r, readdir64_r); diff --git a/src/dirent/scandir.c b/src/dirent/scandir.c index 7ee195dd..7456b9b8 100644 --- a/src/dirent/scandir.c +++ b/src/dirent/scandir.c @@ -43,5 +43,3 @@ int scandir(const char *path, struct dirent ***res, *res = names; return cnt; } - -weak_alias(scandir, scandir64); diff --git a/src/dirent/versionsort.c b/src/dirent/versionsort.c index d4c48923..97696105 100644 --- a/src/dirent/versionsort.c +++ b/src/dirent/versionsort.c @@ -6,6 +6,3 @@ int versionsort(const struct dirent **a, const struct dirent **b) { return strverscmp((*a)->d_name, (*b)->d_name); } - -#undef versionsort64 -weak_alias(versionsort, versionsort64); diff --git a/src/fcntl/creat.c b/src/fcntl/creat.c index 8f8aab64..c9c43910 100644 --- a/src/fcntl/creat.c +++ b/src/fcntl/creat.c @@ -4,5 +4,3 @@ int creat(const char *filename, mode_t mode) { return open(filename, O_CREAT|O_WRONLY|O_TRUNC, mode); } - -weak_alias(creat, creat64); diff --git a/src/fcntl/open.c b/src/fcntl/open.c index 1d817a2d..4c3c8275 100644 --- a/src/fcntl/open.c +++ b/src/fcntl/open.c @@ -19,5 +19,3 @@ int open(const char *filename, int flags, ...) return __syscall_ret(fd); } - -weak_alias(open, open64); diff --git a/src/fcntl/openat.c b/src/fcntl/openat.c index ad165ec3..83a9e0d0 100644 --- a/src/fcntl/openat.c +++ b/src/fcntl/openat.c @@ -15,5 +15,3 @@ int openat(int fd, const char *filename, int flags, ...) return syscall_cp(SYS_openat, fd, filename, flags|O_LARGEFILE, mode); } - -weak_alias(openat, openat64); diff --git a/src/fcntl/posix_fadvise.c b/src/fcntl/posix_fadvise.c index 75b8e1ae..07346d21 100644 --- a/src/fcntl/posix_fadvise.c +++ b/src/fcntl/posix_fadvise.c @@ -14,5 +14,3 @@ int posix_fadvise(int fd, off_t base, off_t len, int advice) __SYSCALL_LL_E(len), advice); #endif } - -weak_alias(posix_fadvise, posix_fadvise64); diff --git a/src/fcntl/posix_fallocate.c b/src/fcntl/posix_fallocate.c index c57a24ae..80a65cbf 100644 --- a/src/fcntl/posix_fallocate.c +++ b/src/fcntl/posix_fallocate.c @@ -6,5 +6,3 @@ int posix_fallocate(int fd, off_t base, off_t len) return -__syscall(SYS_fallocate, fd, 0, __SYSCALL_LL_E(base), __SYSCALL_LL_E(len)); } - -weak_alias(posix_fallocate, posix_fallocate64); diff --git a/src/legacy/ftw.c b/src/legacy/ftw.c index 506bd29c..e757fc6f 100644 --- a/src/legacy/ftw.c +++ b/src/legacy/ftw.c @@ -7,5 +7,3 @@ int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int * actually undefined, but works on all real-world machines. */ return nftw(path, (int (*)())fn, fd_limit, FTW_PHYS); } - -weak_alias(ftw, ftw64); diff --git a/src/linux/fallocate.c b/src/linux/fallocate.c index 7d68bc8f..9146350e 100644 --- a/src/linux/fallocate.c +++ b/src/linux/fallocate.c @@ -7,6 +7,3 @@ int fallocate(int fd, int mode, off_t base, off_t len) return syscall(SYS_fallocate, fd, mode, __SYSCALL_LL_E(base), __SYSCALL_LL_E(len)); } - -#undef fallocate64 -weak_alias(fallocate, fallocate64); diff --git a/src/linux/getdents.c b/src/linux/getdents.c index 796c1e5c..97f76e14 100644 --- a/src/linux/getdents.c +++ b/src/linux/getdents.c @@ -8,5 +8,3 @@ int getdents(int fd, struct dirent *buf, size_t len) if (len>INT_MAX) len = INT_MAX; return syscall(SYS_getdents, fd, buf, len); } - -weak_alias(getdents, getdents64); diff --git a/src/linux/prlimit.c b/src/linux/prlimit.c index 3df9ffba..fcf45aab 100644 --- a/src/linux/prlimit.c +++ b/src/linux/prlimit.c @@ -21,6 +21,3 @@ int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlim } return r; } - -#undef prlimit64 -weak_alias(prlimit, prlimit64); diff --git a/src/linux/sendfile.c b/src/linux/sendfile.c index 9afe6dd6..fc1577d3 100644 --- a/src/linux/sendfile.c +++ b/src/linux/sendfile.c @@ -5,5 +5,3 @@ ssize_t sendfile(int out_fd, int in_fd, off_t *ofs, size_t count) { return syscall(SYS_sendfile, out_fd, in_fd, ofs, count); } - -weak_alias(sendfile, sendfile64); diff --git a/src/misc/getrlimit.c b/src/misc/getrlimit.c index bf676307..a5558d81 100644 --- a/src/misc/getrlimit.c +++ b/src/misc/getrlimit.c @@ -26,5 +26,3 @@ int getrlimit(int resource, struct rlimit *rlim) return ret; #endif } - -weak_alias(getrlimit, getrlimit64); diff --git a/src/misc/lockf.c b/src/misc/lockf.c index 16a80bec..0162442b 100644 --- a/src/misc/lockf.c +++ b/src/misc/lockf.c @@ -28,5 +28,3 @@ int lockf(int fd, int op, off_t size) errno = EINVAL; return -1; } - -weak_alias(lockf, lockf64); diff --git a/src/misc/nftw.c b/src/misc/nftw.c index 8dcff7fe..fcd25a73 100644 --- a/src/misc/nftw.c +++ b/src/misc/nftw.c @@ -138,5 +138,3 @@ int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, str pthread_setcancelstate(cs, 0); return r; } - -weak_alias(nftw, nftw64); diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c index 5b713cf3..edb413fa 100644 --- a/src/misc/setrlimit.c +++ b/src/misc/setrlimit.c @@ -49,5 +49,3 @@ int setrlimit(int resource, const struct rlimit *rlim) return __syscall_ret(ret); #endif } - -weak_alias(setrlimit, setrlimit64); diff --git a/src/mman/mmap.c b/src/mman/mmap.c index eff88d82..43e5e029 100644 --- a/src/mman/mmap.c +++ b/src/mman/mmap.c @@ -37,5 +37,3 @@ void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off) } weak_alias(__mmap, mmap); - -weak_alias(mmap, mmap64); diff --git a/src/regex/glob.c b/src/regex/glob.c index 9de080ed..a4906446 100644 --- a/src/regex/glob.c +++ b/src/regex/glob.c @@ -306,6 +306,3 @@ void globfree(glob_t *g) g->gl_pathc = 0; g->gl_pathv = NULL; } - -weak_alias(glob, glob64); -weak_alias(globfree, globfree64); diff --git a/src/stat/__xstat.c b/src/stat/__xstat.c index 630936a0..b4560df7 100644 --- a/src/stat/__xstat.c +++ b/src/stat/__xstat.c @@ -22,11 +22,6 @@ int __xstat(int ver, const char *path, struct stat *buf) return stat(path, buf); } -weak_alias(__fxstat, __fxstat64); -weak_alias(__fxstatat, __fxstatat64); -weak_alias(__lxstat, __lxstat64); -weak_alias(__xstat, __xstat64); - #endif int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev) diff --git a/src/stat/fstat.c b/src/stat/fstat.c index 27db0ccb..fd28b8ac 100644 --- a/src/stat/fstat.c +++ b/src/stat/fstat.c @@ -11,7 +11,3 @@ int __fstat(int fd, struct stat *st) } weak_alias(__fstat, fstat); - -#if !_REDIR_TIME64 -weak_alias(fstat, fstat64); -#endif diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index 74c51cf5..04506375 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -151,7 +151,3 @@ int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int f } weak_alias(__fstatat, fstatat); - -#if !_REDIR_TIME64 -weak_alias(fstatat, fstatat64); -#endif diff --git a/src/stat/lstat.c b/src/stat/lstat.c index 6fe004de..6822fcae 100644 --- a/src/stat/lstat.c +++ b/src/stat/lstat.c @@ -5,7 +5,3 @@ int lstat(const char *restrict path, struct stat *restrict buf) { return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW); } - -#if !_REDIR_TIME64 -weak_alias(lstat, lstat64); -#endif diff --git a/src/stat/stat.c b/src/stat/stat.c index ea70efc4..23570e7a 100644 --- a/src/stat/stat.c +++ b/src/stat/stat.c @@ -5,7 +5,3 @@ int stat(const char *restrict path, struct stat *restrict buf) { return fstatat(AT_FDCWD, path, buf, 0); } - -#if !_REDIR_TIME64 -weak_alias(stat, stat64); -#endif diff --git a/src/stat/statvfs.c b/src/stat/statvfs.c index f65d1b54..bfbb5fee 100644 --- a/src/stat/statvfs.c +++ b/src/stat/statvfs.c @@ -56,8 +56,3 @@ int fstatvfs(int fd, struct statvfs *buf) fixup(buf, &kbuf); return 0; } - -weak_alias(statvfs, statvfs64); -weak_alias(statfs, statfs64); -weak_alias(fstatvfs, fstatvfs64); -weak_alias(fstatfs, fstatfs64); diff --git a/src/stdio/fgetpos.c b/src/stdio/fgetpos.c index 50813d2c..392f7323 100644 --- a/src/stdio/fgetpos.c +++ b/src/stdio/fgetpos.c @@ -7,5 +7,3 @@ int fgetpos(FILE *restrict f, fpos_t *restrict pos) *(long long *)pos = off; return 0; } - -weak_alias(fgetpos, fgetpos64); diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c index e1b91e12..80bc341e 100644 --- a/src/stdio/fopen.c +++ b/src/stdio/fopen.c @@ -29,5 +29,3 @@ FILE *fopen(const char *restrict filename, const char *restrict mode) __syscall(SYS_close, fd); return 0; } - -weak_alias(fopen, fopen64); diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c index 96bfbb42..1641a4c5 100644 --- a/src/stdio/freopen.c +++ b/src/stdio/freopen.c @@ -51,5 +51,3 @@ FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *re fclose(f); return NULL; } - -weak_alias(freopen, freopen64); diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c index c07f7e95..c7425802 100644 --- a/src/stdio/fseek.c +++ b/src/stdio/fseek.c @@ -46,5 +46,3 @@ int fseek(FILE *f, long off, int whence) } weak_alias(__fseeko, fseeko); - -weak_alias(fseeko, fseeko64); diff --git a/src/stdio/fsetpos.c b/src/stdio/fsetpos.c index 77ab8d82..779cb3cc 100644 --- a/src/stdio/fsetpos.c +++ b/src/stdio/fsetpos.c @@ -4,5 +4,3 @@ int fsetpos(FILE *f, const fpos_t *pos) { return __fseeko(f, *(const long long *)pos, SEEK_SET); } - -weak_alias(fsetpos, fsetpos64); diff --git a/src/stdio/ftell.c b/src/stdio/ftell.c index 1a2afbbc..1e1a08d8 100644 --- a/src/stdio/ftell.c +++ b/src/stdio/ftell.c @@ -37,5 +37,3 @@ long ftell(FILE *f) } weak_alias(__ftello, ftello); - -weak_alias(ftello, ftello64); diff --git a/src/stdio/tmpfile.c b/src/stdio/tmpfile.c index ae493987..2fa8803f 100644 --- a/src/stdio/tmpfile.c +++ b/src/stdio/tmpfile.c @@ -27,5 +27,3 @@ FILE *tmpfile(void) } return 0; } - -weak_alias(tmpfile, tmpfile64); diff --git a/src/temp/mkostemp.c b/src/temp/mkostemp.c index d8dcb805..e3dfdd91 100644 --- a/src/temp/mkostemp.c +++ b/src/temp/mkostemp.c @@ -5,5 +5,3 @@ int mkostemp(char *template, int flags) { return __mkostemps(template, 0, flags); } - -weak_alias(mkostemp, mkostemp64); diff --git a/src/temp/mkostemps.c b/src/temp/mkostemps.c index ef24eeae..093d2380 100644 --- a/src/temp/mkostemps.c +++ b/src/temp/mkostemps.c @@ -26,4 +26,3 @@ int __mkostemps(char *template, int len, int flags) } weak_alias(__mkostemps, mkostemps); -weak_alias(__mkostemps, mkostemps64); diff --git a/src/temp/mkstemp.c b/src/temp/mkstemp.c index 166b8afe..76c835bb 100644 --- a/src/temp/mkstemp.c +++ b/src/temp/mkstemp.c @@ -4,5 +4,3 @@ int mkstemp(char *template) { return __mkostemps(template, 0, 0); } - -weak_alias(mkstemp, mkstemp64); diff --git a/src/temp/mkstemps.c b/src/temp/mkstemps.c index 6b7531b5..f8eabfec 100644 --- a/src/temp/mkstemps.c +++ b/src/temp/mkstemps.c @@ -5,5 +5,3 @@ int mkstemps(char *template, int len) { return __mkostemps(template, len, 0); } - -weak_alias(mkstemps, mkstemps64); diff --git a/src/unistd/ftruncate.c b/src/unistd/ftruncate.c index b41be0fa..54ff34bc 100644 --- a/src/unistd/ftruncate.c +++ b/src/unistd/ftruncate.c @@ -5,5 +5,3 @@ int ftruncate(int fd, off_t length) { return syscall(SYS_ftruncate, fd, __SYSCALL_LL_O(length)); } - -weak_alias(ftruncate, ftruncate64); diff --git a/src/unistd/lseek.c b/src/unistd/lseek.c index b4984f3e..f5b66682 100644 --- a/src/unistd/lseek.c +++ b/src/unistd/lseek.c @@ -12,4 +12,3 @@ off_t __lseek(int fd, off_t offset, int whence) } weak_alias(__lseek, lseek); -weak_alias(__lseek, lseek64); diff --git a/src/unistd/mipsn32/lseek.c b/src/unistd/mipsn32/lseek.c index 60e74a51..0f6cbcaa 100644 --- a/src/unistd/mipsn32/lseek.c +++ b/src/unistd/mipsn32/lseek.c @@ -17,4 +17,3 @@ off_t __lseek(int fd, off_t offset, int whence) } weak_alias(__lseek, lseek); -weak_alias(__lseek, lseek64); diff --git a/src/unistd/pread.c b/src/unistd/pread.c index 5681b045..b03fb0ad 100644 --- a/src/unistd/pread.c +++ b/src/unistd/pread.c @@ -5,5 +5,3 @@ ssize_t pread(int fd, void *buf, size_t size, off_t ofs) { return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL_PRW(ofs)); } - -weak_alias(pread, pread64); diff --git a/src/unistd/preadv.c b/src/unistd/preadv.c index 8376d60f..890ab403 100644 --- a/src/unistd/preadv.c +++ b/src/unistd/preadv.c @@ -8,5 +8,3 @@ ssize_t preadv(int fd, const struct iovec *iov, int count, off_t ofs) return syscall_cp(SYS_preadv, fd, iov, count, (long)(ofs), (long)(ofs>>32)); } - -weak_alias(preadv, preadv64); diff --git a/src/unistd/pwrite.c b/src/unistd/pwrite.c index ca376576..869b69f0 100644 --- a/src/unistd/pwrite.c +++ b/src/unistd/pwrite.c @@ -5,5 +5,3 @@ ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs) { return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL_PRW(ofs)); } - -weak_alias(pwrite, pwrite64); diff --git a/src/unistd/pwritev.c b/src/unistd/pwritev.c index f5a612c4..becf9deb 100644 --- a/src/unistd/pwritev.c +++ b/src/unistd/pwritev.c @@ -8,5 +8,3 @@ ssize_t pwritev(int fd, const struct iovec *iov, int count, off_t ofs) return syscall_cp(SYS_pwritev, fd, iov, count, (long)(ofs), (long)(ofs>>32)); } - -weak_alias(pwritev, pwritev64); diff --git a/src/unistd/truncate.c b/src/unistd/truncate.c index 97296800..077351e1 100644 --- a/src/unistd/truncate.c +++ b/src/unistd/truncate.c @@ -5,5 +5,3 @@ int truncate(const char *path, off_t length) { return syscall(SYS_truncate, path, __SYSCALL_LL_O(length)); } - -weak_alias(truncate, truncate64); diff --git a/src/unistd/x32/lseek.c b/src/unistd/x32/lseek.c index 32636429..5f93292f 100644 --- a/src/unistd/x32/lseek.c +++ b/src/unistd/x32/lseek.c @@ -12,4 +12,3 @@ off_t __lseek(int fd, off_t offset, int whence) } weak_alias(__lseek, lseek); -weak_alias(__lseek, lseek64); From 25e6fee27f4a293728dd15b659170e7b9c7db9bc Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 27 Sep 2022 15:04:05 -0400 Subject: [PATCH 146/297] remove LFS64 programming interfaces (macro-only) from _GNU_SOURCE these badly pollute the namespace with macros whenever _GNU_SOURCE is defined, which is always the case with g++, and especially tends to interfere with C++ constructs. as our implementation of these was macro-only, their removal cannot affect any existing binaries. at the source level, portable software should be prepared for them not to exist. for now, they are left in place with explicit _LARGEFILE64_SOURCE. this provides an easy temporary path for integrators/distributions to get packages building again right away if they break while working on a proper, upstreamable fix. the intent is that this be a very short-term measure and that the macros be removed entirely in the next release cycle. --- include/aio.h | 2 +- include/dirent.h | 2 +- include/fcntl.h | 2 +- include/ftw.h | 2 +- include/glob.h | 2 +- include/stdio.h | 2 +- include/stdlib.h | 2 +- include/sys/mman.h | 2 +- include/sys/resource.h | 2 +- include/sys/sendfile.h | 2 +- include/sys/stat.h | 2 +- include/sys/statfs.h | 2 +- include/sys/statvfs.h | 2 +- include/sys/types.h | 2 +- include/sys/uio.h | 2 +- include/unistd.h | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/aio.h b/include/aio.h index 453c41b7..a938fcad 100644 --- a/include/aio.h +++ b/include/aio.h @@ -49,7 +49,7 @@ int aio_fsync(int, struct aiocb *); int lio_listio(int, struct aiocb *__restrict const *__restrict, int, struct sigevent *__restrict); -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define aiocb64 aiocb #define aio_read64 aio_read #define aio_write64 aio_write diff --git a/include/dirent.h b/include/dirent.h index 650ecf64..2d8fffb2 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -56,7 +56,7 @@ int getdents(int, struct dirent *, size_t); int versionsort(const struct dirent **, const struct dirent **); #endif -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define dirent64 dirent #define readdir64 readdir #define readdir64_r readdir_r diff --git a/include/fcntl.h b/include/fcntl.h index b664cdc4..515f255d 100644 --- a/include/fcntl.h +++ b/include/fcntl.h @@ -195,7 +195,7 @@ ssize_t tee(int, int, size_t, unsigned); #define loff_t off_t #endif -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define F_GETLK64 F_GETLK #define F_SETLK64 F_SETLK #define F_SETLKW64 F_SETLKW diff --git a/include/ftw.h b/include/ftw.h index b15c062a..d0445e8a 100644 --- a/include/ftw.h +++ b/include/ftw.h @@ -29,7 +29,7 @@ struct FTW { int ftw(const char *, int (*)(const char *, const struct stat *, int), int); int nftw(const char *, int (*)(const char *, const struct stat *, int, struct FTW *), int, int); -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define ftw64 ftw #define nftw64 nftw #endif diff --git a/include/glob.h b/include/glob.h index 4a562a20..fed06745 100644 --- a/include/glob.h +++ b/include/glob.h @@ -39,7 +39,7 @@ void globfree(glob_t *); #define GLOB_NOMATCH 3 #define GLOB_NOSYS 4 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define glob64 glob #define globfree64 globfree #define glob64_t glob_t diff --git a/include/stdio.h b/include/stdio.h index d1ed01f0..cb858618 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -205,7 +205,7 @@ typedef struct _IO_cookie_io_functions_t { FILE *fopencookie(void *, const char *, cookie_io_functions_t); #endif -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define tmpfile64 tmpfile #define fopen64 fopen #define freopen64 freopen diff --git a/include/stdlib.h b/include/stdlib.h index b507ca33..b117a452 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -163,7 +163,7 @@ double strtod_l(const char *__restrict, char **__restrict, struct __locale_struc long double strtold_l(const char *__restrict, char **__restrict, struct __locale_struct *); #endif -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define mkstemp64 mkstemp #define mkostemp64 mkostemp #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) diff --git a/include/sys/mman.h b/include/sys/mman.h index 80a3baae..3d5d0f9c 100644 --- a/include/sys/mman.h +++ b/include/sys/mman.h @@ -141,7 +141,7 @@ int mincore (void *, size_t, unsigned char *); int shm_open (const char *, int, mode_t); int shm_unlink (const char *); -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define mmap64 mmap #define off64_t off_t #endif diff --git a/include/sys/resource.h b/include/sys/resource.h index 3068328d..e8bfbe1f 100644 --- a/include/sys/resource.h +++ b/include/sys/resource.h @@ -95,7 +95,7 @@ int prlimit(pid_t, int, const struct rlimit *, struct rlimit *); #define RLIM_NLIMITS RLIMIT_NLIMITS -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define RLIM64_INFINITY RLIM_INFINITY #define RLIM64_SAVED_CUR RLIM_SAVED_CUR #define RLIM64_SAVED_MAX RLIM_SAVED_MAX diff --git a/include/sys/sendfile.h b/include/sys/sendfile.h index e7570d8e..253a041b 100644 --- a/include/sys/sendfile.h +++ b/include/sys/sendfile.h @@ -10,7 +10,7 @@ extern "C" { ssize_t sendfile(int, int, off_t *, size_t); -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define sendfile64 sendfile #define off64_t off_t #endif diff --git a/include/sys/stat.h b/include/sys/stat.h index 10d446c4..e6d0049c 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -98,7 +98,7 @@ int lchmod(const char *, mode_t); #define S_IEXEC S_IXUSR #endif -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define stat64 stat #define fstat64 fstat #define lstat64 lstat diff --git a/include/sys/statfs.h b/include/sys/statfs.h index 6f4c6230..7a2e11cd 100644 --- a/include/sys/statfs.h +++ b/include/sys/statfs.h @@ -18,7 +18,7 @@ typedef struct __fsid_t { int statfs (const char *, struct statfs *); int fstatfs (int, struct statfs *); -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define statfs64 statfs #define fstatfs64 fstatfs #define fsblkcnt64_t fsblkcnt_t diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h index 793490b6..57a6b806 100644 --- a/include/sys/statvfs.h +++ b/include/sys/statvfs.h @@ -42,7 +42,7 @@ int fstatvfs (int, struct statvfs *); #define ST_NODIRATIME 2048 #define ST_RELATIME 4096 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define statvfs64 statvfs #define fstatvfs64 fstatvfs #define fsblkcnt64_t fsblkcnt_t diff --git a/include/sys/types.h b/include/sys/types.h index 0c35541d..3363374f 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -71,7 +71,7 @@ typedef unsigned long long u_quad_t; #include #endif -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define blkcnt64_t blkcnt_t #define fsblkcnt64_t fsblkcnt_t #define fsfilcnt64_t fsfilcnt_t diff --git a/include/sys/uio.h b/include/sys/uio.h index 00f73a2f..90e5939e 100644 --- a/include/sys/uio.h +++ b/include/sys/uio.h @@ -29,7 +29,7 @@ ssize_t writev (int, const struct iovec *, int); #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) ssize_t preadv (int, const struct iovec *, int, off_t); ssize_t pwritev (int, const struct iovec *, int, off_t); -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define preadv64 preadv #define pwritev64 pwritev #define off64_t off_t diff --git a/include/unistd.h b/include/unistd.h index 0e8149e4..5bc7f798 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -198,7 +198,7 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned); pid_t gettid(void); #endif -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#if defined(_LARGEFILE64_SOURCE) #define lseek64 lseek #define pread64 pread #define pwrite64 pwrite From e6e8213244a816511e95e14fb99176442922abac Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 28 Sep 2022 08:33:05 -0400 Subject: [PATCH 147/297] disable MADV_FREE usage in mallocng the entire intent of using madvise/MADV_FREE on freed slots is to improve system performance by avoiding evicting cache of useful data, or swapping useless data to disk, by marking any whole pages in the freed slot as discardable by the kernel. in particular, unlike unmapping the memory or replacing it with a PROT_NONE region, use of MADV_FREE does not make any difference to memory accounting for commit charge purposes, and so does not increase the memory available to other processes in a non-overcommitted environment. however, various measurements have shown that inordinate amounts of time are spent performing madvise syscalls in processes which frequently allocate and free medium sized objects in the size range roughly between PAGESIZE and MMAP_THRESHOLD, to the point that the net effect is almost surely significant performance degredation. so, turn it off. the code, which has some nontrivial logic for efficiently determining whether there is a whole-page range to apply madvise to, is left in place so that it can easily be re-enabled if desired, or later tuned to only apply to certain sizes or to use additional heuristics. --- src/malloc/mallocng/free.c | 2 +- src/malloc/mallocng/glue.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/malloc/mallocng/free.c b/src/malloc/mallocng/free.c index 418a085c..43f32aad 100644 --- a/src/malloc/mallocng/free.c +++ b/src/malloc/mallocng/free.c @@ -119,7 +119,7 @@ void free(void *p) if (((uintptr_t)(start-1) ^ (uintptr_t)end) >= 2*PGSZ && g->last_idx) { unsigned char *base = start + (-(uintptr_t)start & (PGSZ-1)); size_t len = (end-base) & -PGSZ; - if (len) { + if (len && USE_MADV_FREE) { int e = errno; madvise(base, len, MADV_FREE); errno = e; diff --git a/src/malloc/mallocng/glue.h b/src/malloc/mallocng/glue.h index 151c48b8..77f4c812 100644 --- a/src/malloc/mallocng/glue.h +++ b/src/malloc/mallocng/glue.h @@ -24,6 +24,8 @@ #define realloc __libc_realloc #define free __libc_free +#define USE_MADV_FREE 0 + #if USE_REAL_ASSERT #include #else From 833a469167521040c7ae94f3c990e258e29445f9 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 30 Sep 2022 21:20:32 -0400 Subject: [PATCH 148/297] configure: disable TBAA optimization because most compilers are buggy unlike most projects that use -fno-strict-aliasing, we aim to have all sources respect the C language rules for effective type that make type-based alias analysis optimizations possible. unfortunately, it turns out that there are deep, and likely very difficult to fix, flaws in the TBAA performed by GCC and likely other compilers, whereby this kind of optimization can transform code that follows the rules strictly in ways that will make it malfunction. see for example GCC bugs 107107 and 107115, the latter of which also affects clang. there are not presently any known instances of breakage due to wrong type-based aliasing optimizations in our codebase. nonetheless, since the transformations are unsound and could introduce breakage, configure CFLAGS to build with -fno-strict-aliasing. some casual analysis of the effects on codegen suggest that this is unlikely to affect performance except possibly in the regex engine. in general, we should probably prefer making better use of the restrict keyword over relying on types to imply non-aliasing for optimization purposes; doing so should be able to get back any performance that was lost and more, should it turn out to matter (unlikely). --- configure | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure b/configure index 6f5453f5..853bf05e 100755 --- a/configure +++ b/configure @@ -353,6 +353,14 @@ tryflag CFLAGS_C99FSE -fexcess-precision=standard \ || { test "$ARCH" = i386 && tryflag CFLAGS_C99FSE -ffloat-store ; } tryflag CFLAGS_C99FSE -frounding-math +# +# Semantically we want to insist that our sources follow the +# C rules for type-based aliasing, but most if not all real-world +# compilers are known or suspected to have critical bugs in their +# type-based aliasing analysis. See for example GCC bug 107107. +# +tryflag CFLAGS_C99FSE -fno-strict-aliasing + # # We may use the may_alias attribute if __GNUC__ is defined, so # if the compiler defines __GNUC__ but does not provide it, From 36b72cd6fdfed2cac6b6ff1ed58a96d8265785cf Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 5 Oct 2022 10:41:30 -0400 Subject: [PATCH 149/297] fix potential deadlock in dlerror buffer handling at thread exit ever since commit 8f11e6127fe93093f81a52b15bb1537edc3fc8af introduced the thread list lock, this has been wrong. initially, it was wrong via calling free from the context with the thread list lock held. commit aa5a9d15e09851f7b4a1668e9dbde0f6234abada deferred the unsafe free but added a lock, which was also unsafe. in particular, it could deadlock if code holding freebuf_queue_lock was interrupted by a signal handler that takes the thread list lock. commit 4d5aa20a94a2d3fae3e69289dc23ecafbd0c16c4 observed that there was a lock here but failed to notice that it's invalid. there is no easy solution to this problem with locks; any attempt at solving it while still using locks would require the lock to be an AS-safe one (blocking signals on each access to the dlerror buffer list to check if there's deferred free work to be done) which would be excessively costly, and there are also lock order considerations with respect to how the lock would be handled at fork. instead, just use an atomic list. --- src/internal/fork_impl.h | 1 - src/ldso/dlerror.c | 34 ++++++++++++++++++---------------- src/process/fork.c | 2 -- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/internal/fork_impl.h b/src/internal/fork_impl.h index 5892c13b..ae3a79e5 100644 --- a/src/internal/fork_impl.h +++ b/src/internal/fork_impl.h @@ -2,7 +2,6 @@ extern hidden volatile int *const __at_quick_exit_lockptr; extern hidden volatile int *const __atexit_lockptr; -extern hidden volatile int *const __dlerror_lockptr; extern hidden volatile int *const __gettext_lockptr; extern hidden volatile int *const __locale_lockptr; extern hidden volatile int *const __random_lockptr; diff --git a/src/ldso/dlerror.c b/src/ldso/dlerror.c index afe59253..dae0f3a9 100644 --- a/src/ldso/dlerror.c +++ b/src/ldso/dlerror.c @@ -3,8 +3,7 @@ #include #include "pthread_impl.h" #include "dynlink.h" -#include "lock.h" -#include "fork_impl.h" +#include "atomic.h" #define malloc __libc_malloc #define calloc __libc_calloc @@ -23,28 +22,31 @@ char *dlerror() return s; } -static volatile int freebuf_queue_lock[1]; -static void **freebuf_queue; -volatile int *const __dlerror_lockptr = freebuf_queue_lock; +/* Atomic singly-linked list, used to store list of thread-local dlerror + * buffers for deferred free. They cannot be freed at thread exit time + * because, by the time it's known they can be freed, the exiting thread + * is in a highly restrictive context where it cannot call (even the + * libc-internal) free. It also can't take locks; thus the atomic list. */ + +static void *volatile freebuf_queue; void __dl_thread_cleanup(void) { pthread_t self = __pthread_self(); - if (self->dlerror_buf && self->dlerror_buf != (void *)-1) { - LOCK(freebuf_queue_lock); - void **p = (void **)self->dlerror_buf; - *p = freebuf_queue; - freebuf_queue = p; - UNLOCK(freebuf_queue_lock); - } + if (!self->dlerror_buf || self->dlerror_buf == (void *)-1) + return; + void *h; + do { + h = freebuf_queue; + *(void **)self->dlerror_buf = h; + } while (a_cas_p(&freebuf_queue, h, self->dlerror_buf) != h); } hidden void __dl_vseterr(const char *fmt, va_list ap) { - LOCK(freebuf_queue_lock); - void **q = freebuf_queue; - freebuf_queue = 0; - UNLOCK(freebuf_queue_lock); + void **q; + do q = freebuf_queue; + while (q && a_cas_p(&freebuf_queue, q, 0) != q); while (q) { void **p = *q; diff --git a/src/process/fork.c b/src/process/fork.c index 54bc2892..ff71845c 100644 --- a/src/process/fork.c +++ b/src/process/fork.c @@ -9,7 +9,6 @@ static volatile int *const dummy_lockptr = 0; weak_alias(dummy_lockptr, __at_quick_exit_lockptr); weak_alias(dummy_lockptr, __atexit_lockptr); -weak_alias(dummy_lockptr, __dlerror_lockptr); weak_alias(dummy_lockptr, __gettext_lockptr); weak_alias(dummy_lockptr, __locale_lockptr); weak_alias(dummy_lockptr, __random_lockptr); @@ -24,7 +23,6 @@ weak_alias(dummy_lockptr, __vmlock_lockptr); static volatile int *const *const atfork_locks[] = { &__at_quick_exit_lockptr, &__atexit_lockptr, - &__dlerror_lockptr, &__gettext_lockptr, &__locale_lockptr, &__random_lockptr, From d64148a8743ad9ed0594091d2ff141b1e9334d4b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 5 Oct 2022 11:07:52 -0400 Subject: [PATCH 150/297] fix potential unsynchronized access to killlock state at thread exit as reported by Alexey Izbyshev, when the second-to-last thread exits causing a return to single-threaded (no locks needed) state, it creates a situation where the last remaining thread may obtain the killlock that's already held by the exiting thread. this means it may erroneously use the tid of the exiting thread, and may corrupt the lock state due to double-unlock. commit 8d81ba8c0bc6fe31136cb15c9c82ef4c24965040, which (re)introduced the switch back to single-threaded state, documents the intent that the first lock after switching back should provide the necessary synchronization. this is correct, but only works if the switch back is made after there is no further need for synchronization with locks (other than the thread list lock, which can't be bypassed) held by the exiting thread. in order to hit the bug, the remaining thread must first take a different lock, causing it to perform an actual lock one last time, consume the need_locks==-1 state, and transition to need_locks==0. after that, the next attempt to lock the exiting thread's killlock will bypass locking. fix this by reordering the unlocking of killlock at thread exit time, along with changes to the state protected by it, to occur earlier, before the switch to single-threaded state. there are really no constraints on where it's done, except that it occur after there is no longer any possibility of application code executing in the exiting thread, so do it as early as possible. --- src/thread/pthread_create.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 6f187ee8..087f6206 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -107,6 +107,16 @@ _Noreturn void __pthread_exit(void *result) /* At this point we are committed to thread termination. */ + /* After the kernel thread exits, its tid may be reused. Clear it + * to prevent inadvertent use and inform functions that would use + * it that it's no longer available. At this point the killlock + * may be released, since functions that use it will consistently + * see the thread as having exited. Release it now so that no + * remaining locks (except thread list) are held if we end up + * resetting need_locks below. */ + self->tid = 0; + UNLOCK(self->killlock); + /* Process robust list in userspace to handle non-pshared mutexes * and the detached thread case where the robust list head will * be invalid when the kernel would process it. */ @@ -159,12 +169,6 @@ _Noreturn void __pthread_exit(void *result) a_store(&self->detach_state, DT_EXITED); __wake(&self->detach_state, 1, 1); - /* After the kernel thread exits, its tid may be reused. Clear it - * to prevent inadvertent use and inform functions that would use - * it that it's no longer available. */ - self->tid = 0; - UNLOCK(self->killlock); - for (;;) __syscall(SYS_exit, 0); } From aebd6a36449e91c06763a40121d558b6cea90d50 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 6 Oct 2022 20:53:01 -0400 Subject: [PATCH 151/297] fix potential deadlock between multithreaded fork and aio as reported by Alexey Izbyshev, there is a lock order inversion deadlock between the malloc lock and aio maplock at MT-fork time: _Fork attempts to take the aio maplock while fork already has the malloc lock, but a concurrent aio operation holding the maplock may attempt to allocate memory. move the __aio_atfork calls in the parent from _Fork to fork, and reorder the lock before most other locks, since nothing else depends on aio(*). this leaves us with the possibility that the child will not be able to obtain the read lock, if _Fork is used directly and happens concurrent with an aio operation. however, in that case, the child context is an async signal context that cannot call any further aio functions, so all we need is to ensure that close does not attempt to perform any aio cancellation. this can be achieved just by nulling out the map pointer. (*) even if other functions call close, they will only need a read lock, not a write lock, and read locks being recursive ensures they can obtain it. moreover, the number of read references held is bounded by something like twice the number of live threads, meaning that the read lock count cannot saturate. --- src/aio/aio.c | 19 +++++++++++++++++-- src/process/_Fork.c | 3 +-- src/process/fork.c | 3 +++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/aio/aio.c b/src/aio/aio.c index fa24f6b6..82f8eccb 100644 --- a/src/aio/aio.c +++ b/src/aio/aio.c @@ -401,11 +401,26 @@ void __aio_atfork(int who) if (who<0) { pthread_rwlock_rdlock(&maplock); return; + } else if (!who) { + pthread_rwlock_unlock(&maplock); + return; } - if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++) + aio_fd_cnt = 0; + if (pthread_rwlock_tryrdlock(&maplock)) { + /* Obtaining lock may fail if _Fork was called nor via + * fork. In this case, no further aio is possible from + * child and we can just null out map so __aio_close + * does not attempt to do anything. */ + map = 0; + return; + } + if (map) for (int a=0; a<(-1U/2+1)>>24; a++) if (map[a]) for (int b=0; b<256; b++) if (map[a][b]) for (int c=0; c<256; c++) if (map[a][b][c]) for (int d=0; d<256; d++) map[a][b][c][d] = 0; - pthread_rwlock_unlock(&maplock); + /* Re-initialize the rwlock rather than unlocking since there + * may have been more than one reference on it in the parent. + * We are not a lock holder anyway; the thread in the parent was. */ + pthread_rwlock_init(&maplock, 0); } diff --git a/src/process/_Fork.c b/src/process/_Fork.c index da063868..fb0fdc2c 100644 --- a/src/process/_Fork.c +++ b/src/process/_Fork.c @@ -14,7 +14,6 @@ pid_t _Fork(void) pid_t ret; sigset_t set; __block_all_sigs(&set); - __aio_atfork(-1); LOCK(__abort_lock); #ifdef SYS_fork ret = __syscall(SYS_fork); @@ -32,7 +31,7 @@ pid_t _Fork(void) if (libc.need_locks) libc.need_locks = -1; } UNLOCK(__abort_lock); - __aio_atfork(!ret); + if (!ret) __aio_atfork(1); __restore_sigs(&set); return __syscall_ret(ret); } diff --git a/src/process/fork.c b/src/process/fork.c index ff71845c..80e804b1 100644 --- a/src/process/fork.c +++ b/src/process/fork.c @@ -36,6 +36,7 @@ static volatile int *const *const atfork_locks[] = { static void dummy(int x) { } weak_alias(dummy, __fork_handler); weak_alias(dummy, __malloc_atfork); +weak_alias(dummy, __aio_atfork); weak_alias(dummy, __ldso_atfork); static void dummy_0(void) { } @@ -50,6 +51,7 @@ pid_t fork(void) int need_locks = libc.need_locks > 0; if (need_locks) { __ldso_atfork(-1); + __aio_atfork(-1); __inhibit_ptc(); for (int i=0; i Date: Fri, 7 Oct 2022 15:23:57 +0300 Subject: [PATCH 152/297] fix use of uninitialized dummy_fut in aio_suspend aio_suspend waits on a dummy futex in the corner case when the array of requests contains NULL pointers only. But the value of this futex was left uninitialized, so if it happens to be non-zero, aio_suspend degrades to spinning instead of blocking. --- src/aio/aio_suspend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aio/aio_suspend.c b/src/aio/aio_suspend.c index 95def796..1f0c9aaa 100644 --- a/src/aio/aio_suspend.c +++ b/src/aio/aio_suspend.c @@ -9,7 +9,7 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec { int i, tid = 0, ret, expect = 0; struct timespec at; - volatile int dummy_fut, *pfut; + volatile int dummy_fut = 0, *pfut; int nzcnt = 0; const struct aiocb *cb = 0; From d8f35e29d0e35a90f44c04de585470c211afddf9 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 7 Oct 2022 18:51:36 -0400 Subject: [PATCH 153/297] fix AS-safety of close when aio is in use and fd map is expanded the aio operations that lead to calling __aio_get_queue with the possibility to expand the fd map are not AS-safe, but if they are interrupted by a signal handler, the signal handler may call close, which is required to be AS-safe. due to __aio_get_queue taking the write lock without blocking signals, such a call to close from a signal handler could deadlock. change __aio_get_queue to block signals if it needs to obtain a write lock, and restore when finished. --- src/aio/aio.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/aio/aio.c b/src/aio/aio.c index 82f8eccb..d7e063bf 100644 --- a/src/aio/aio.c +++ b/src/aio/aio.c @@ -82,6 +82,8 @@ static size_t io_thread_stack_size; static struct aio_queue *__aio_get_queue(int fd, int need) { + sigset_t allmask, origmask; + int masked = 0; if (fd < 0) { errno = EBADF; return 0; @@ -93,6 +95,9 @@ static struct aio_queue *__aio_get_queue(int fd, int need) if ((!map || !map[a] || !map[a][b] || !map[a][b][c] || !(q=map[a][b][c][d])) && need) { pthread_rwlock_unlock(&maplock); if (fcntl(fd, F_GETFD) < 0) return 0; + sigfillset(&allmask); + masked = 1; + pthread_sigmask(SIG_BLOCK, &allmask, &origmask); pthread_rwlock_wrlock(&maplock); if (!io_thread_stack_size) { unsigned long val = __getauxval(AT_MINSIGSTKSZ); @@ -119,6 +124,7 @@ static struct aio_queue *__aio_get_queue(int fd, int need) if (q) pthread_mutex_lock(&q->lock); out: pthread_rwlock_unlock(&maplock); + if (masked) pthread_sigmask(SIG_SETMASK, &origmask, 0); return q; } From 5ff3eea91fa6bdce25b3a35644433f68e076beca Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 7 Oct 2022 19:37:56 -0400 Subject: [PATCH 154/297] fgets: avoid arithmetic overflow when n==INT_MIN is passed performing n-- is not a safe operation for arbitrary signed input n. only perform the decrement in the code path where the initial n is greater than 1, and adjust the condition in the n<=1 code path to compensate for it not having been decremented. --- src/stdio/fgets.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/stdio/fgets.c b/src/stdio/fgets.c index 6171f398..4a100b39 100644 --- a/src/stdio/fgets.c +++ b/src/stdio/fgets.c @@ -12,13 +12,14 @@ char *fgets(char *restrict s, int n, FILE *restrict f) FLOCK(f); - if (n--<=1) { + if (n<=1) { f->mode |= f->mode-1; FUNLOCK(f); - if (n) return 0; + if (n<1) return 0; *s = 0; return s; } + n--; while (n) { if (f->rpos != f->rend) { From cf76df0e1fe09b0d504ca650fdaa01df5bf9ab72 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 7 Oct 2022 21:36:25 -0400 Subject: [PATCH 155/297] fix missing synchronization of pthread TSD keys with MT-fork commit 167390f05564e0a4d3fcb4329377fd7743267560 seems to have overlooked the presence of a lock here, probably because it was one of the exceptions not using LOCK() but a rwlock. as such, it can't be added to the generic table of locks to take, so add an explicit atfork function for the pthread keys table. the order it is called does not particularly matter since nothing else in libc but pthread_exit interacts with keys. --- src/internal/fork_impl.h | 1 + src/process/fork.c | 3 +++ src/thread/pthread_key_create.c | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/src/internal/fork_impl.h b/src/internal/fork_impl.h index ae3a79e5..354e733b 100644 --- a/src/internal/fork_impl.h +++ b/src/internal/fork_impl.h @@ -16,3 +16,4 @@ extern hidden volatile int *const __vmlock_lockptr; hidden void __malloc_atfork(int); hidden void __ldso_atfork(int); +hidden void __pthread_key_atfork(int); diff --git a/src/process/fork.c b/src/process/fork.c index 80e804b1..56f19313 100644 --- a/src/process/fork.c +++ b/src/process/fork.c @@ -37,6 +37,7 @@ static void dummy(int x) { } weak_alias(dummy, __fork_handler); weak_alias(dummy, __malloc_atfork); weak_alias(dummy, __aio_atfork); +weak_alias(dummy, __pthread_key_atfork); weak_alias(dummy, __ldso_atfork); static void dummy_0(void) { } @@ -51,6 +52,7 @@ pid_t fork(void) int need_locks = libc.need_locks > 0; if (need_locks) { __ldso_atfork(-1); + __pthread_key_atfork(-1); __aio_atfork(-1); __inhibit_ptc(); for (int i=0; i Date: Wed, 19 Oct 2022 13:15:11 -0400 Subject: [PATCH 156/297] dns response handling: ignore presence of wrong-type RRs reportedly there is nameserver software with question-rewriting "functionality" which gives A answers when AAAA is queried. since we made no effort to validate that the answer RR type actually corresponds to the question asked, it was possible (depending on flags, etc.) for these answers to leak through, which the caller might not be prepared for. indeed, our implementation of gethostbyname2_r makes an assumption that the resulting addresses are in the family requested, and will misinterpret the results if they don't. commit 45ca5d3fcb6f874bf5ba55d0e9651cef68515395 already noted in fixing CVE-2017-15650 that this could happen, but did nothing to validate that the RR type of the answer matches the question; it just enforced the limit on number of results to preclude overflow. presently, name_from_dns ignores the return value of __dns_parse, so it doesn't really matter whether we return 0 (ignoring the RR) or -1 (parse-ending error) upon encountering the mismatched RR. if that ever changes, though, ignoring irrelevant answer RRs sounds like the semantically correct thing to do, so for now let's return 0 from the callback when this happens. --- src/network/lookup_name.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index 4a6999cb..de0fefee 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -102,6 +102,7 @@ struct dpc_ctx { struct address *addrs; char *canon; int cnt; + int rrtype; }; #define RR_A 1 @@ -117,12 +118,14 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const if (ctx->cnt >= MAXADDRS) return -1; switch (rr) { case RR_A: + if (rr != ctx->rrtype) return 0; if (len != 4) return -1; ctx->addrs[ctx->cnt].family = AF_INET; ctx->addrs[ctx->cnt].scopeid = 0; memcpy(ctx->addrs[ctx->cnt++].addr, data, 4); break; case RR_AAAA: + if (rr != ctx->rrtype) return 0; if (len != 16) return -1; ctx->addrs[ctx->cnt].family = AF_INET6; ctx->addrs[ctx->cnt].scopeid = 0; @@ -142,7 +145,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static unsigned char qbuf[2][280], abuf[2][ABUF_SIZE]; const unsigned char *qp[2] = { qbuf[0], qbuf[1] }; unsigned char *ap[2] = { abuf[0], abuf[1] }; - int qlens[2], alens[2]; + int qlens[2], alens[2], qtypes[2]; int i, nq = 0; struct dpc_ctx ctx = { .addrs = buf, .canon = canon }; static const struct { int af; int rr; } afrr[2] = { @@ -156,6 +159,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 0, 0, 0, qbuf[nq], sizeof *qbuf); if (qlens[nq] == -1) return 0; + qtypes[nq] = afrr[i].rr; qbuf[nq][3] = 0; /* don't need AD flag */ /* Ensure query IDs are distinct. */ if (nq && qbuf[nq][0] == qbuf[0][0]) @@ -173,8 +177,10 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static if ((abuf[i][3] & 15) != 0) return EAI_FAIL; } - for (i=nq-1; i>=0; i--) + for (i=nq-1; i>=0; i--) { + ctx.rrtype = qtypes[i]; __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); + } if (ctx.cnt) return ctx.cnt; return EAI_NODATA; From 0a7b4323b0f2b944dbd47a813c0c6e6813e7fd67 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 19 Oct 2022 13:33:03 -0400 Subject: [PATCH 157/297] dns response handling: don't treat too many addresses as an error returning -1 rather than 0 from the parse function causes __dns_parse to bail out and return an error. presently, name_from_dns does not check the return value anyway, so this does not matter, but if it ever started treating this as an error, lookups with large numbers of addresses would break. this is a consequence of adding TCP support and extending the buffer size used in name_from_dns. --- src/network/lookup_name.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index de0fefee..be0c0bdd 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -115,7 +115,7 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const { char tmp[256]; struct dpc_ctx *ctx = c; - if (ctx->cnt >= MAXADDRS) return -1; + if (ctx->cnt >= MAXADDRS) return 0; switch (rr) { case RR_A: if (rr != ctx->rrtype) return 0; From 63402be229facae2d0de9c5943a6ed25246fd021 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 19 Oct 2022 14:02:48 -0400 Subject: [PATCH 158/297] clean up dns_parse_callback the only functional change here should be that MAXADDRS is only checked for RRs that provide address results, so that a CNAME which appears after an excessive number of address RRs does not get ignored. I'm not aware of any servers that order the RRs this way, and it may even be forbidden to do so, but I prefer having the callback logic not be order dependent. other than that, the motivation for this change is that the A and AAAA cases were mostly duplicate code that could be combined as a single code path. --- src/network/lookup_name.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index be0c0bdd..5f6867cb 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -114,29 +114,29 @@ struct dpc_ctx { static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) { char tmp[256]; + int family; struct dpc_ctx *ctx = c; + if (rr == RR_CNAME) { + if (__dn_expand(packet, (const unsigned char *)packet + ABUF_SIZE, + data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp)) + strcpy(ctx->canon, tmp); + return 0; + } if (ctx->cnt >= MAXADDRS) return 0; + if (rr != ctx->rrtype) return 0; switch (rr) { case RR_A: - if (rr != ctx->rrtype) return 0; if (len != 4) return -1; - ctx->addrs[ctx->cnt].family = AF_INET; - ctx->addrs[ctx->cnt].scopeid = 0; - memcpy(ctx->addrs[ctx->cnt++].addr, data, 4); + family = AF_INET; break; case RR_AAAA: - if (rr != ctx->rrtype) return 0; if (len != 16) return -1; - ctx->addrs[ctx->cnt].family = AF_INET6; - ctx->addrs[ctx->cnt].scopeid = 0; - memcpy(ctx->addrs[ctx->cnt++].addr, data, 16); - break; - case RR_CNAME: - if (__dn_expand(packet, (const unsigned char *)packet + ABUF_SIZE, - data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp)) - strcpy(ctx->canon, tmp); + family = AF_INET6; break; } + ctx->addrs[ctx->cnt].family = family; + ctx->addrs[ctx->cnt].scopeid = 0; + memcpy(ctx->addrs[ctx->cnt++].addr, data, len); return 0; } From 8f9259450aa43a6fd539e428e61e2961b725fbae Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 20 Oct 2022 19:48:32 -0400 Subject: [PATCH 159/297] fix return value of gethostby{name[2],addr} with no result but no error commit f081d5336a80b68d3e1bed789cc373c5c3d6699b fixed gethostbyname[2]_r to treat negative results as a non-error, leaving gethostbyname[2] wrongly returning a pointer to the unfilled result buffer rather than a null pointer. since, as documented with commit fe82bb9b921be34370e6b71a1c6f062c20999ae0, the caller of gethostby{name[2],addr}_r can always rely on the result pointer being set, use that consistently rather than trying to duplicate logic about whether we have a result or not in gethostby{name[2],addr}. --- src/network/gethostbyaddr.c | 2 +- src/network/gethostbyname2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/gethostbyaddr.c b/src/network/gethostbyaddr.c index 598e2241..c3cacaac 100644 --- a/src/network/gethostbyaddr.c +++ b/src/network/gethostbyaddr.c @@ -20,5 +20,5 @@ struct hostent *gethostbyaddr(const void *a, socklen_t l, int af) err = gethostbyaddr_r(a, l, af, h, (void *)(h+1), size-sizeof *h, &res, &h_errno); } while (err == ERANGE); - return err ? 0 : h; + return res; } diff --git a/src/network/gethostbyname2.c b/src/network/gethostbyname2.c index dc9d6621..bd0da7f8 100644 --- a/src/network/gethostbyname2.c +++ b/src/network/gethostbyname2.c @@ -21,5 +21,5 @@ struct hostent *gethostbyname2(const char *name, int af) err = gethostbyname2_r(name, af, h, (void *)(h+1), size-sizeof *h, &res, &h_errno); } while (err == ERANGE); - return err ? 0 : h; + return res; } From ad5dcd398b9509cf43672e3a7f02c4b18035998c Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 5 Nov 2022 18:53:11 -0400 Subject: [PATCH 160/297] fix async thread cancellation stack alignment if async cancellation is enabled and acted upon, the stack pointer is not necessarily pointing to a __syscall_cp_asm stack frame. the contents of the stack being wrong don't really matter, but if the stack pointer is not suitably aligned, the procedure call ABI is violated when calling back into C code via __cancel, and pthread_exit, cancellation cleanup handlers, TSD destructors, etc. may malfunction or crash. for the async cancel case, just call __cancel directly like we did prior to commit 102f6a01e249ce4495f1119ae6d963a2a4a53ce5. restore the signal mask prior to doing this since the cancellation handler runs with all signals blocked. --- src/thread/pthread_cancel.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c index 2d3a98ea..139a6fc8 100644 --- a/src/thread/pthread_cancel.c +++ b/src/thread/pthread_cancel.c @@ -56,7 +56,12 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx) _sigaddset(&uc->uc_sigmask, SIGCANCEL); - if (self->cancelasync || pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) { + if (self->cancelasync) { + pthread_sigmask(SIG_SETMASK, &uc->uc_sigmask, 0); + __cancel(); + } + + if (pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) { uc->uc_mcontext.MC_PC = (uintptr_t)__cp_cancel; #ifdef CANCEL_GOT uc->uc_mcontext.MC_GOT = CANCEL_GOT; From b50eb8c36c20f967bd0ed70c0b0db38a450886ba Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 7 Nov 2022 22:17:55 -0500 Subject: [PATCH 161/297] fix strverscmp comparison of digit sequence with non-digits the rule that longest digit sequence not beginning with a zero is greater only applies when both sequences being compared are non-degenerate. this is spelled out explicitly in the man page, which may be deemed authoritative for this nonstandard function: "If one or both of these is empty, then return what strcmp(3) would have returned..." we were wrongly treating any sequence of digits not beginning with a zero as greater than a non-digit in the other string. --- src/string/strverscmp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/string/strverscmp.c b/src/string/strverscmp.c index 4daf276d..16c1da22 100644 --- a/src/string/strverscmp.c +++ b/src/string/strverscmp.c @@ -18,9 +18,9 @@ int strverscmp(const char *l0, const char *r0) else if (c!='0') z=0; } - if (l[dp]!='0' && r[dp]!='0') { - /* If we're not looking at a digit sequence that began - * with a zero, longest digit string is greater. */ + if (l[dp]-'1'<9U && r[dp]-'1'<9U) { + /* If we're looking at non-degenerate digit sequences starting + * with nonzero digits, longest digit string is greater. */ for (j=i; isdigit(l[j]); j++) if (!isdigit(r[j])) return 1; if (isdigit(r[j])) return -1; From 29e4319178cbc2a4e9f058a99ae8098d4b6ac055 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 10 Nov 2022 09:02:02 -0500 Subject: [PATCH 162/297] fix double-processing of DT_RELR relocations in ldso relocating itself this is analogous to skip_relative logic in do_relocs -- because relative relocations for the dynamic linker itself were already performed at entry (stage 1), they must not be applied again. --- ldso/dynlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 7b47b163..8068fb37 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -552,6 +552,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri static void do_relr_relocs(struct dso *dso, size_t *relr, size_t relr_size) { + if (dso == &ldso) return; /* self-relocation was done in _dlstart */ unsigned char *base = dso->base; size_t *reloc_addr; for (; relr_size; relr++, relr_size-=sizeof(size_t)) From 377218cb963aa20c6eb91781b0c79ad606631e6f Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Sat, 12 Nov 2022 16:31:01 +0300 Subject: [PATCH 163/297] pthread_atfork: fix return value on malloc failure POSIX requires pthread_atfork to report errors via its return value, not via errno. The only specified error is ENOMEM. --- src/thread/pthread_atfork.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/thread/pthread_atfork.c b/src/thread/pthread_atfork.c index 76497401..6d348ac8 100644 --- a/src/thread/pthread_atfork.c +++ b/src/thread/pthread_atfork.c @@ -1,4 +1,5 @@ #include +#include #include "libc.h" #include "lock.h" @@ -34,7 +35,7 @@ void __fork_handler(int who) int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) { struct atfork_funcs *new = malloc(sizeof *new); - if (!new) return -1; + if (!new) return ENOMEM; LOCK(lock); new->next = funcs; From 762c23a30ad3f8aff75c1f4b3112369bdff5d607 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 29 Nov 2022 15:37:34 -0800 Subject: [PATCH 164/297] Update to emscripten 3.1.27 --- src/internal/pthread_impl.h | 3 +-- src/thread/pthread_key_create.c | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index c25a1c2d..8523938f 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -26,8 +26,7 @@ struct pthread { #ifndef TLS_ABOVE_TP uintptr_t *dtv; #endif - // TODO(sbc): Implement circular list of threads - //struct pthread *prev, *next; /* non-ABI */ + struct pthread *prev, *next; /* non-ABI */ uintptr_t sysinfo; #ifndef TLS_ABOVE_TP #ifdef CANARY_PAD diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c index 53caad40..522dd076 100644 --- a/src/thread/pthread_key_create.c +++ b/src/thread/pthread_key_create.c @@ -57,13 +57,10 @@ int __pthread_key_delete(pthread_key_t k) __block_app_sigs(&set); __pthread_rwlock_wrlock(&key_lock); - // TODO(sbc): Implement circular list of threads - /* __tl_lock(); do td->tsd[k] = 0; while ((td=td->next)!=self); __tl_unlock(); - */ keys[k] = 0; From f47a8cdd250d9163fcfb39bf4e9d813957c0b187 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 30 Nov 2022 18:59:08 -0500 Subject: [PATCH 165/297] ldso: fix invalid early references to extern-linkage libc.page_size when PAGE_SIZE is not constant, internal/libc.h defines it to expand to libc.page_size. however, kernel_mapped_dso, reachable from stage 2 of the dynamic linker bootstrap (__dls2), needs PAGE_SIZE to interpret the relro range. at this point the libc object is both uninitialized and invalid to access according to our model for bootstrapping, which does not assume any external-linkage objects are accessible until stages 2b/3. in practice it likely worked because hidden visibility tends to behave like internal linkage, but this is not a property that the dynamic linker was designed to rely upon. this bug likely manifested as relro malfunction on archs with variable page size, due to incorrect mask when aligning the relro bounds to page boundaries. while there are certainly more direct ways to fix the known problem point here, a maximally future-proof way is to just bypass the libc.h PAGE_SIZE definition in the dynamic linker and instead have dynlink.c define its own internal-linkage object for variable page size. then, if anything else in stage 2 ever ends up referencing PAGE_SIZE, it will just automatically work right. --- ldso/dynlink.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 8068fb37..09f3b0a8 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -21,9 +21,15 @@ #include #include "pthread_impl.h" #include "fork_impl.h" -#include "libc.h" #include "dynlink.h" +static size_t ldso_page_size; +#ifndef PAGE_SIZE +#define PAGE_SIZE ldso_page_size +#endif + +#include "libc.h" + #define malloc __libc_malloc #define calloc __libc_calloc #define realloc __libc_realloc @@ -1723,6 +1729,7 @@ hidden void __dls2(unsigned char *base, size_t *sp) ldso.phnum = ehdr->e_phnum; ldso.phdr = laddr(&ldso, ehdr->e_phoff); ldso.phentsize = ehdr->e_phentsize; + search_vec(auxv, &ldso_page_size, AT_PAGESZ); kernel_mapped_dso(&ldso); decode_dyn(&ldso); From 159d1f6c02569091c7a48bdb2e2e824b844a1902 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 13 Dec 2022 18:39:44 -0500 Subject: [PATCH 166/297] semaphores: fix missed wakes from ABA bug in waiter count logic because the has-waiters state in the semaphore value futex word is only representable when the value is zero (the special value -1 represents "0 with potential new waiters"), it's lost if intervening operations make the semaphore value positive again. this creates an ABA issue in sem_post, whereby the post uses a stale waiters count rather than re-evaluating it, skipping the futex wake if the stale count was zero. the fix here is based on a proposal by Alexey Izbyshev, with minor changes to eliminate costly new spurious wake syscalls. the basic idea is to replace the special value -1 with a sticky waiters bit (repurposing the sign bit) preserved under both wait and post. any post that takes place with the waiters bit set will perform a futex wake. to be useful, the waiters bit needs to be removable, and to remove it safely, we perform a broadcast wake instead of a normal single-task wake whenever removing the bit. this lets any un-accounted-for waiters wake and re-add the waiters bit if they still need it. there are multiple possible choices for when to perform this broadcast, but the optimal choice seems to be doing it whenever the observed waiters count is less than two (semantically, this means exactly one, but we might see a stale count of zero). in this case, the expected number of threads to be woken is one, with exactly the same cost as a non-broadcast wake. --- src/thread/sem_getvalue.c | 3 ++- src/thread/sem_post.c | 12 ++++++++---- src/thread/sem_timedwait.c | 10 ++++++---- src/thread/sem_trywait.c | 6 +++--- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/thread/sem_getvalue.c b/src/thread/sem_getvalue.c index d9d83071..c0b7762d 100644 --- a/src/thread/sem_getvalue.c +++ b/src/thread/sem_getvalue.c @@ -1,8 +1,9 @@ #include +#include int sem_getvalue(sem_t *restrict sem, int *restrict valp) { int val = sem->__val[0]; - *valp = val < 0 ? 0 : val; + *valp = val & SEM_VALUE_MAX; return 0; } diff --git a/src/thread/sem_post.c b/src/thread/sem_post.c index 31e3293d..5c2517f2 100644 --- a/src/thread/sem_post.c +++ b/src/thread/sem_post.c @@ -1,17 +1,21 @@ #include +#include #include "pthread_impl.h" int sem_post(sem_t *sem) { - int val, waiters, priv = sem->__val[2]; + int val, new, waiters, priv = sem->__val[2]; do { val = sem->__val[0]; waiters = sem->__val[1]; - if (val == SEM_VALUE_MAX) { + if ((val & SEM_VALUE_MAX) == SEM_VALUE_MAX) { errno = EOVERFLOW; return -1; } - } while (a_cas(sem->__val, val, val+1+(val<0)) != val); - if (val<0 || waiters) __wake(sem->__val, 1, priv); + new = val + 1; + if (waiters <= 1) + new &= ~0x80000000; + } while (a_cas(sem->__val, val, new) != val); + if (val<0) __wake(sem->__val, waiters>1 ? 1 : -1, priv); return 0; } diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c index 58d3ebfe..aa67376c 100644 --- a/src/thread/sem_timedwait.c +++ b/src/thread/sem_timedwait.c @@ -1,4 +1,5 @@ #include +#include #include "pthread_impl.h" static void cleanup(void *p) @@ -13,14 +14,15 @@ int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) if (!sem_trywait(sem)) return 0; int spins = 100; - while (spins-- && sem->__val[0] <= 0 && !sem->__val[1]) a_spin(); + while (spins-- && !(sem->__val[0] & SEM_VALUE_MAX) && !sem->__val[1]) + a_spin(); while (sem_trywait(sem)) { - int r; + int r, priv = sem->__val[2]; a_inc(sem->__val+1); - a_cas(sem->__val, 0, -1); + a_cas(sem->__val, 0, 0x80000000); pthread_cleanup_push(cleanup, (void *)(sem->__val+1)); - r = __timedwait_cp(sem->__val, -1, CLOCK_REALTIME, at, sem->__val[2]); + r = __timedwait_cp(sem->__val, 0x80000000, CLOCK_REALTIME, at, priv); pthread_cleanup_pop(1); if (r) { errno = r; diff --git a/src/thread/sem_trywait.c b/src/thread/sem_trywait.c index 04edf46b..beb435da 100644 --- a/src/thread/sem_trywait.c +++ b/src/thread/sem_trywait.c @@ -1,12 +1,12 @@ #include +#include #include "pthread_impl.h" int sem_trywait(sem_t *sem) { int val; - while ((val=sem->__val[0]) > 0) { - int new = val-1-(val==1 && sem->__val[1]); - if (a_cas(sem->__val, val, new)==val) return 0; + while ((val=sem->__val[0]) & SEM_VALUE_MAX) { + if (a_cas(sem->__val, val, val-1)==val) return 0; } errno = EAGAIN; return -1; From c5f4b2dfea320356f69445dc1adf8f73596a3c36 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 25 Jul 2022 19:14:33 -0700 Subject: [PATCH 167/297] elf.h: add ELFCOMPRESS_ZSTD --- include/elf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/elf.h b/include/elf.h index 9e980a29..23f2c4bc 100644 --- a/include/elf.h +++ b/include/elf.h @@ -437,6 +437,7 @@ typedef struct { } Elf64_Chdr; #define ELFCOMPRESS_ZLIB 1 +#define ELFCOMPRESS_ZSTD 2 #define ELFCOMPRESS_LOOS 0x60000000 #define ELFCOMPRESS_HIOS 0x6fffffff #define ELFCOMPRESS_LOPROC 0x70000000 From 7d358599d4c8f793cfb42ee49ff5e1d107de6ee4 Mon Sep 17 00:00:00 2001 From: Markus Wichmann Date: Thu, 3 Nov 2022 20:42:16 +0100 Subject: [PATCH 168/297] prevent invalid reads of nl_arg in printf_core printf_core() runs twice, and during its first run, nl_arg is uninitialized and must not be read. It gets initialized at the end of the first run. Conversely, nl_type does not need to be set during the second run, as its useful life has ended at that point, since the only time it is read is during that exact same initialization. Therefore we can simply alternate the assignments. p and w do still need to get values assigned to them, since at least one line in the same if-statement depends on that, but they can be dummy values. arg does not need to be assigned, since in the first run, we encounter a continue statement before using the argument. --- src/stdio/vfprintf.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 9b961e7f..45557951 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -478,8 +478,8 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, if (*s=='*') { if (isdigit(s[1]) && s[2]=='$') { l10n=1; - nl_type[s[1]-'0'] = INT; - w = nl_arg[s[1]-'0'].i; + if (!f) nl_type[s[1]-'0'] = INT, w = 0; + else w = nl_arg[s[1]-'0'].i; s+=3; } else if (!l10n) { w = f ? va_arg(*ap, int) : 0; @@ -491,8 +491,8 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, /* Read precision */ if (*s=='.' && s[1]=='*') { if (isdigit(s[2]) && s[3]=='$') { - nl_type[s[2]-'0'] = INT; - p = nl_arg[s[2]-'0'].i; + if (!f) nl_type[s[2]-'0'] = INT, p = 0; + else p = nl_arg[s[2]-'0'].i; s+=4; } else if (!l10n) { p = f ? va_arg(*ap, int) : 0; @@ -521,8 +521,10 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, if (st==NOARG) { if (argpos>=0) goto inval; } else { - if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos]; - else if (f) pop_arg(&arg, st, ap); + if (argpos>=0) { + if (!f) nl_type[argpos]=st; + else arg=nl_arg[argpos]; + } else if (f) pop_arg(&arg, st, ap); else return 0; } From 9532ae1318201d66b235a618df16aac0b3386630 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 17 Dec 2022 16:00:19 -0500 Subject: [PATCH 169/297] use libc-internal malloc for pthread_atfork while no lock is held here making it a lock-order issue, replacement malloc is likely to want to use pthread_atfork, possibly making the call to malloc infinitely recursive. even if not, there is no reason to prefer an application-provided malloc here. --- src/thread/pthread_atfork.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/thread/pthread_atfork.c b/src/thread/pthread_atfork.c index 6d348ac8..26d32543 100644 --- a/src/thread/pthread_atfork.c +++ b/src/thread/pthread_atfork.c @@ -3,6 +3,11 @@ #include "libc.h" #include "lock.h" +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef + static struct atfork_funcs { void (*prepare)(void); void (*parent)(void); From a4b0a665b84c4a3117cca152fe28c204d23ece46 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 6 Jan 2023 06:33:19 -0500 Subject: [PATCH 170/297] expose memmem under baseline POSIX feature profile memmem has been adopted for the next issue of POSIX (outcome of tracker item 1061). since mem* is in the reserved namespace for string.h it's already fully conforming to expose it by default, so just do so. --- include/string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/string.h b/include/string.h index 43ad0942..db73d2a9 100644 --- a/include/string.h +++ b/include/string.h @@ -73,6 +73,7 @@ char *strsignal(int); char *strerror_l (int, locale_t); int strcoll_l (const char *, const char *, locale_t); size_t strxfrm_l (char *__restrict, const char *__restrict, size_t, locale_t); +void *memmem(const void *, size_t, const void *, size_t); #endif #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ @@ -92,7 +93,6 @@ void explicit_bzero (void *, size_t); int strverscmp (const char *, const char *); char *strchrnul(const char *, int); char *strcasestr(const char *, const char *); -void *memmem(const void *, size_t, const void *, size_t); void *memrchr(const void *, int, size_t); void *mempcpy(void *, const void *, size_t); #ifndef __cplusplus From f897461d4fe72bb71854a6d0662de83008caccb7 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 18 Jan 2023 10:32:14 -0500 Subject: [PATCH 171/297] fix debugger tracking of shared libraries on mips with PIE main program mips has its own mechanisms for DT_DEBUG because it makes _DYNAMIC read-only, and the original mechanism, DT_MIPS_RLD_MAP, was PIE-incompatible. DT_MIPS_RLD_MAP_REL was added to remedy this, but we never implemented support for it. add it now using the same idioms for mips-specific ldso logic. --- arch/mips/reloc.h | 1 + arch/mips64/reloc.h | 1 + arch/mipsn32/reloc.h | 1 + ldso/dynlink.c | 4 ++++ src/internal/dynlink.h | 4 ++++ 5 files changed, 11 insertions(+) diff --git a/arch/mips/reloc.h b/arch/mips/reloc.h index 88d23639..f4023b16 100644 --- a/arch/mips/reloc.h +++ b/arch/mips/reloc.h @@ -29,6 +29,7 @@ #define NEED_MIPS_GOT_RELOCS 1 #define DT_DEBUG_INDIRECT DT_MIPS_RLD_MAP +#define DT_DEBUG_INDIRECT_REL DT_MIPS_RLD_MAP_REL #define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT)) #define CRTJMP(pc,sp) __asm__ __volatile__( \ diff --git a/arch/mips64/reloc.h b/arch/mips64/reloc.h index fdb5edc9..145d8b0b 100644 --- a/arch/mips64/reloc.h +++ b/arch/mips64/reloc.h @@ -38,6 +38,7 @@ #define NEED_MIPS_GOT_RELOCS 1 #define DT_DEBUG_INDIRECT DT_MIPS_RLD_MAP +#define DT_DEBUG_INDIRECT_REL DT_MIPS_RLD_MAP_REL #define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT)) #define CRTJMP(pc,sp) __asm__ __volatile__( \ diff --git a/arch/mipsn32/reloc.h b/arch/mipsn32/reloc.h index 47c6e591..bf00bd6a 100644 --- a/arch/mipsn32/reloc.h +++ b/arch/mipsn32/reloc.h @@ -29,6 +29,7 @@ #define NEED_MIPS_GOT_RELOCS 1 #define DT_DEBUG_INDIRECT DT_MIPS_RLD_MAP +#define DT_DEBUG_INDIRECT_REL DT_MIPS_RLD_MAP_REL #define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT)) #define CRTJMP(pc,sp) __asm__ __volatile__( \ diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 09f3b0a8..fde5f346 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1992,6 +1992,10 @@ void __dls3(size_t *sp, size_t *auxv) size_t *ptr = (size_t *) app.dynv[i+1]; *ptr = (size_t)&debug; } + if (app.dynv[i]==DT_DEBUG_INDIRECT_REL) { + size_t *ptr = (size_t *)((size_t)&app.dynv[i] + app.dynv[i+1]); + *ptr = (size_t)&debug; + } } /* This must be done before final relocations, since it calls diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 830354eb..06f41d09 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -92,6 +92,10 @@ struct fdpic_dummy_loadmap { #define DT_DEBUG_INDIRECT 0 #endif +#ifndef DT_DEBUG_INDIRECT_REL +#define DT_DEBUG_INDIRECT_REL 0 +#endif + #define AUX_CNT 32 #define DYN_CNT 37 From ea3b40a321e751e016948087ef23ae7b9e8e0150 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 18 Jan 2023 23:15:58 -0500 Subject: [PATCH 172/297] fix integer overflow in WIFSTOPPED macro the result of the 0xffff mask with the exit status could have bit 15 set, in which case multiplying by 0x10001 overflows 32-bit signed int. making the multiply unsigned avoids the overflow. it also changes the sign extension behavior of the subsequent >> operation, but the affected bits are all unwanted anyway and all discarded by the cast to short. --- include/stdlib.h | 2 +- include/sys/wait.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index b117a452..475190bf 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -95,7 +95,7 @@ size_t __ctype_get_mb_cur_max(void); #define WTERMSIG(s) ((s) & 0x7f) #define WSTOPSIG(s) WEXITSTATUS(s) #define WIFEXITED(s) (!WTERMSIG(s)) -#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00) +#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001U)>>8) > 0x7f00) #define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu) int posix_memalign (void **, size_t, size_t); diff --git a/include/sys/wait.h b/include/sys/wait.h index d4b1f2e1..8ced671b 100644 --- a/include/sys/wait.h +++ b/include/sys/wait.h @@ -50,7 +50,7 @@ pid_t wait4 (pid_t, int *, int, struct rusage *); #define WSTOPSIG(s) WEXITSTATUS(s) #define WCOREDUMP(s) ((s) & 0x80) #define WIFEXITED(s) (!WTERMSIG(s)) -#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00) +#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001U)>>8) > 0x7f00) #define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu) #define WIFCONTINUED(s) ((s) == 0xffff) From 269d193820342dc109f39909d78fb30f4c978f76 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 9 Feb 2023 11:52:44 -0500 Subject: [PATCH 173/297] fix wrong sigaction syscall ABI on mips*, or1k, microblaze, riscv64 we wrongly defined a dummy SA_RESTORER flag on these archs, despite the kernel interface not actually having such a feature. on archs which lack SA_RESTORER, the kernel sigaction structure also lacks the restorer function pointer member, which means the signal mask appears at a different offset. the kernel was thereby interpreting the bits of the code address as part of the signal set to be masked while handling the signal. this patch removes the erroneous SA_RESTORER definitions from archs which do not have it, makes access to the member conditional on whether SA_RESTORER is defined for the arch, and removes the now-unused asm for the affected archs. because there are reportedly versions of qemu-user which also use the wrong ABI here, the old ksigaction struct size is preserved with an unused member at the end. this is harmless and mitigates the risk of such a bug turning into a buffer overflow onto the sigaction function's stack. --- arch/microblaze/bits/signal.h | 1 - arch/mips/bits/signal.h | 1 - arch/mips/ksigaction.h | 5 +---- arch/mips64/bits/signal.h | 1 - arch/mips64/ksigaction.h | 2 +- arch/mipsn32/bits/signal.h | 1 - arch/mipsn32/ksigaction.h | 2 +- arch/or1k/bits/signal.h | 1 - arch/riscv64/bits/signal.h | 1 - src/internal/ksigaction.h | 5 +++++ src/signal/mips/restore.s | 15 --------------- src/signal/mips64/restore.s | 11 ----------- src/signal/mipsn32/restore.s | 11 ----------- src/signal/sigaction.c | 5 ++++- 14 files changed, 12 insertions(+), 50 deletions(-) delete mode 100644 src/signal/mips/restore.s delete mode 100644 src/signal/mips64/restore.s delete mode 100644 src/signal/mipsn32/restore.s diff --git a/arch/microblaze/bits/signal.h b/arch/microblaze/bits/signal.h index 490f83bf..f25b7c6a 100644 --- a/arch/microblaze/bits/signal.h +++ b/arch/microblaze/bits/signal.h @@ -46,7 +46,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #endif diff --git a/arch/mips/bits/signal.h b/arch/mips/bits/signal.h index 1b69e762..a3b3857a 100644 --- a/arch/mips/bits/signal.h +++ b/arch/mips/bits/signal.h @@ -66,7 +66,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #undef SIG_BLOCK #undef SIG_UNBLOCK diff --git a/arch/mips/ksigaction.h b/arch/mips/ksigaction.h index 63fdfab0..485abf75 100644 --- a/arch/mips/ksigaction.h +++ b/arch/mips/ksigaction.h @@ -4,10 +4,7 @@ struct k_sigaction { unsigned flags; void (*handler)(int); unsigned long mask[4]; - /* The following field is past the end of the structure the - * kernel will read or write, and exists only to avoid having - * mips-specific preprocessor conditionals in sigaction.c. */ - void (*restorer)(); + void *unused; }; hidden void __restore(), __restore_rt(); diff --git a/arch/mips64/bits/signal.h b/arch/mips64/bits/signal.h index 4f91c9fc..ffec7fd0 100644 --- a/arch/mips64/bits/signal.h +++ b/arch/mips64/bits/signal.h @@ -85,7 +85,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #undef SIG_BLOCK #undef SIG_UNBLOCK diff --git a/arch/mips64/ksigaction.h b/arch/mips64/ksigaction.h index c16e4731..b4d0fa5f 100644 --- a/arch/mips64/ksigaction.h +++ b/arch/mips64/ksigaction.h @@ -4,7 +4,7 @@ struct k_sigaction { unsigned flags; void (*handler)(int); unsigned long mask[2]; - void (*restorer)(); + void *unused; }; hidden void __restore(), __restore_rt(); diff --git a/arch/mipsn32/bits/signal.h b/arch/mipsn32/bits/signal.h index 4f91c9fc..ffec7fd0 100644 --- a/arch/mipsn32/bits/signal.h +++ b/arch/mipsn32/bits/signal.h @@ -85,7 +85,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #undef SIG_BLOCK #undef SIG_UNBLOCK diff --git a/arch/mipsn32/ksigaction.h b/arch/mipsn32/ksigaction.h index b565f1fc..485abf75 100644 --- a/arch/mipsn32/ksigaction.h +++ b/arch/mipsn32/ksigaction.h @@ -4,7 +4,7 @@ struct k_sigaction { unsigned flags; void (*handler)(int); unsigned long mask[4]; - void (*restorer)(); + void *unused; }; hidden void __restore(), __restore_rt(); diff --git a/arch/or1k/bits/signal.h b/arch/or1k/bits/signal.h index be576d1d..c45be676 100644 --- a/arch/or1k/bits/signal.h +++ b/arch/or1k/bits/signal.h @@ -43,7 +43,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #endif diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h index 287367db..fd6157a3 100644 --- a/arch/riscv64/bits/signal.h +++ b/arch/riscv64/bits/signal.h @@ -76,7 +76,6 @@ typedef struct __ucontext #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #endif diff --git a/src/internal/ksigaction.h b/src/internal/ksigaction.h index 8ebd5938..ef333f33 100644 --- a/src/internal/ksigaction.h +++ b/src/internal/ksigaction.h @@ -6,8 +6,13 @@ struct k_sigaction { void (*handler)(int); unsigned long flags; +#ifdef SA_RESTORER void (*restorer)(void); +#endif unsigned mask[2]; +#ifndef SA_RESTORER + void *unused; +#endif }; hidden void __restore(), __restore_rt(); diff --git a/src/signal/mips/restore.s b/src/signal/mips/restore.s deleted file mode 100644 index b6dadce0..00000000 --- a/src/signal/mips/restore.s +++ /dev/null @@ -1,15 +0,0 @@ -.set noreorder - -.global __restore_rt -.hidden __restore_rt -.type __restore_rt,@function -__restore_rt: - li $2, 4193 - syscall - -.global __restore -.hidden __restore -.type __restore,@function -__restore: - li $2, 4119 - syscall diff --git a/src/signal/mips64/restore.s b/src/signal/mips64/restore.s deleted file mode 100644 index 401f8e73..00000000 --- a/src/signal/mips64/restore.s +++ /dev/null @@ -1,11 +0,0 @@ -.set noreorder -.global __restore_rt -.global __restore -.hidden __restore_rt -.hidden __restore -.type __restore_rt,@function -.type __restore,@function -__restore_rt: -__restore: - li $2,5211 - syscall diff --git a/src/signal/mipsn32/restore.s b/src/signal/mipsn32/restore.s deleted file mode 100644 index 4cd4e1b4..00000000 --- a/src/signal/mipsn32/restore.s +++ /dev/null @@ -1,11 +0,0 @@ -.set noreorder -.global __restore_rt -.global __restore -.hidden __restore_rt -.hidden __restore -.type __restore_rt,@function -.type __restore,@function -__restore_rt: -__restore: - li $2,6211 - syscall diff --git a/src/signal/sigaction.c b/src/signal/sigaction.c index 2203471b..e45308fa 100644 --- a/src/signal/sigaction.c +++ b/src/signal/sigaction.c @@ -44,8 +44,11 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact } } ksa.handler = sa->sa_handler; - ksa.flags = sa->sa_flags | SA_RESTORER; + ksa.flags = sa->sa_flags; +#ifdef SA_RESTORER + ksa.flags |= SA_RESTORER; ksa.restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore; +#endif memcpy(&ksa.mask, &sa->sa_mask, _NSIG/8); } int r = __syscall(SYS_rt_sigaction, sig, sa?&ksa:0, old?&ksa_old:0, _NSIG/8); From 5763f003a53ddaa63655058f19d9fe662751592d Mon Sep 17 00:00:00 2001 From: Pedro Falcato Date: Thu, 9 Feb 2023 16:34:12 +0000 Subject: [PATCH 174/297] riscv64: add vfork Implement vfork() using clone(CLONE_VM | CLONE_VFORK | ...). --- src/process/riscv64/vfork.s | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/process/riscv64/vfork.s diff --git a/src/process/riscv64/vfork.s b/src/process/riscv64/vfork.s new file mode 100644 index 00000000..c93dca23 --- /dev/null +++ b/src/process/riscv64/vfork.s @@ -0,0 +1,12 @@ +.global vfork +.type vfork,@function +vfork: + /* riscv does not have SYS_vfork, so we must use clone instead */ + /* note: riscv's clone = clone(flags, sp, ptidptr, tls, ctidptr) */ + li a7, 220 + li a0, 0x100 | 0x4000 | 17 /* flags = CLONE_VM | CLONE_VFORK | SIGCHLD */ + mv a1, sp + /* the other arguments are ignoreable */ + ecall + .hidden __syscall_ret + j __syscall_ret From 115149c023485a69f5bff05efd5339c0c5f77798 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Feb 2023 09:43:29 -0500 Subject: [PATCH 175/297] powerpc-sf longjmp clobbering of val argument the logic to check hwcap for SPE register file inadvertently clobbered the val argument before use. switch to a different work register so this doesn't happen. --- src/setjmp/powerpc/longjmp.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/setjmp/powerpc/longjmp.S b/src/setjmp/powerpc/longjmp.S index 611389fe..465e4cd7 100644 --- a/src/setjmp/powerpc/longjmp.S +++ b/src/setjmp/powerpc/longjmp.S @@ -42,10 +42,10 @@ longjmp: bl 1f .hidden __hwcap .long __hwcap-. -1: mflr 4 - lwz 5, 0(4) - lwzx 4, 4, 5 - andis. 4, 4, 0x80 +1: mflr 6 + lwz 5, 0(6) + lwzx 6, 6, 5 + andis. 6, 6, 0x80 beq 1f .long 0x11c35b01 /* evldd 14,88(3) */ .long 0x11e36301 /* ... */ From c3cd04fa5fecd2c349aefde090c602554ee4fa24 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Feb 2023 09:54:12 -0500 Subject: [PATCH 176/297] fix pthread_detach inadvertently acting as cancellation point in race case disabling cancellation around the pthread_join call seems to be the safest and logically simplest fix. i believe it would also be possible to just perform the unmap directly here after __tl_sync, removing the dependency on pthread_join, but such an approach duplicately encodes a lot more implementation assumptions. --- src/thread/pthread_detach.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c index 77772af2..d73a500e 100644 --- a/src/thread/pthread_detach.c +++ b/src/thread/pthread_detach.c @@ -5,8 +5,12 @@ static int __pthread_detach(pthread_t t) { /* If the cas fails, detach state is either already-detached * or exiting/exited, and pthread_join will trap or cleanup. */ - if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE) - return __pthread_join(t, 0); + if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE) { + int cs; + __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + __pthread_join(t, 0); + __pthread_setcancelstate(cs, 0); + } return 0; } From fde6891e59c315e4a0ec7e69182e1d6314e3795e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 10 Feb 2023 11:17:02 -0500 Subject: [PATCH 177/297] mq_notify: use semaphore instead of barrier to sync args consumption semaphores are a much lighter primitive, and more idiomatic with current usage in the code base. --- src/mq/mq_notify.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/mq/mq_notify.c b/src/mq/mq_notify.c index 221591c7..a42888d2 100644 --- a/src/mq/mq_notify.c +++ b/src/mq/mq_notify.c @@ -4,10 +4,11 @@ #include #include #include +#include #include "syscall.h" struct args { - pthread_barrier_t barrier; + sem_t sem; int sock; const struct sigevent *sev; }; @@ -21,7 +22,7 @@ static void *start(void *p) void (*func)(union sigval) = args->sev->sigev_notify_function; union sigval val = args->sev->sigev_value; - pthread_barrier_wait(&args->barrier); + sem_post(&args->sem); n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL); close(s); if (n==sizeof buf && buf[sizeof buf - 1] == 1) @@ -37,6 +38,7 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) int s; struct sigevent sev2; static const char zeros[32]; + int cs; if (!sev || sev->sigev_notify != SIGEV_THREAD) return syscall(SYS_mq_notify, mqd, sev); @@ -48,7 +50,7 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes; else pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_barrier_init(&args.barrier, 0, 2); + sem_init(&args.sem, 0, 0); if (pthread_create(&td, &attr, start, &args)) { __syscall(SYS_close, s); @@ -56,8 +58,10 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) return -1; } - pthread_barrier_wait(&args.barrier); - pthread_barrier_destroy(&args.barrier); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + sem_wait(&args.sem); + pthread_setcancelstate(cs, 0); + sem_destroy(&args.sem); sev2.sigev_notify = SIGEV_THREAD; sev2.sigev_signo = s; From 8c0c9c69a12acc0a82590d4fd64cf633ff1dedd2 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 10 Feb 2023 11:22:45 -0500 Subject: [PATCH 178/297] mq_notify: rework to fix use-after-close/double-close bugs in the error path where the mq_notify syscall fails, the initiating thread may have closed the socket before the worker thread calls recv on it. even in the absence of such a race, if the recv call failed, e.g. due to seccomp policy blocking it, the worker thread could proceed to close, producing a double-close condition. this can all be simplified by moving the mq_notify syscall into the new thread, so that the error case does not require pthread_cancel. now, the initiating thread only needs to read back the error status after waiting for the worker thread to consume its arguments. --- src/mq/mq_notify.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/mq/mq_notify.c b/src/mq/mq_notify.c index a42888d2..217d8888 100644 --- a/src/mq/mq_notify.c +++ b/src/mq/mq_notify.c @@ -10,6 +10,8 @@ struct args { sem_t sem; int sock; + mqd_t mqd; + int err; const struct sigevent *sev; }; @@ -21,8 +23,18 @@ static void *start(void *p) int s = args->sock; void (*func)(union sigval) = args->sev->sigev_notify_function; union sigval val = args->sev->sigev_value; + struct sigevent sev2; + static const char zeros[32]; + int err; + sev2.sigev_notify = SIGEV_THREAD; + sev2.sigev_signo = s; + sev2.sigev_value.sival_ptr = (void *)&zeros; + + args->err = err = -__syscall(SYS_mq_notify, args->mqd, &sev2); sem_post(&args->sem); + if (err) return 0; + n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL); close(s); if (n==sizeof buf && buf[sizeof buf - 1] == 1) @@ -36,8 +48,6 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) pthread_attr_t attr; pthread_t td; int s; - struct sigevent sev2; - static const char zeros[32]; int cs; if (!sev || sev->sigev_notify != SIGEV_THREAD) @@ -46,6 +56,7 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0); if (s < 0) return -1; args.sock = s; + args.mqd = mqd; if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes; else pthread_attr_init(&attr); @@ -63,13 +74,9 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) pthread_setcancelstate(cs, 0); sem_destroy(&args.sem); - sev2.sigev_notify = SIGEV_THREAD; - sev2.sigev_signo = s; - sev2.sigev_value.sival_ptr = (void *)&zeros; - - if (syscall(SYS_mq_notify, mqd, &sev2) < 0) { - pthread_cancel(td); + if (args.err) { __syscall(SYS_close, s); + errno = args.err; return -1; } From 711673ee772e20a74aaf301c2d7745c20c4f4d47 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Feb 2023 19:09:53 -0500 Subject: [PATCH 179/297] mq_notify: join worker thread before returning in error path this avoids leaving behind transient resource consumption whose cleanup is subject to scheduling behavior. --- src/mq/mq_notify.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mq/mq_notify.c b/src/mq/mq_notify.c index 217d8888..8109dfb2 100644 --- a/src/mq/mq_notify.c +++ b/src/mq/mq_notify.c @@ -35,6 +35,7 @@ static void *start(void *p) sem_post(&args->sem); if (err) return 0; + pthread_detach(pthread_self()); n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL); close(s); if (n==sizeof buf && buf[sizeof buf - 1] == 1) @@ -60,7 +61,7 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes; else pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); sem_init(&args.sem, 0, 0); if (pthread_create(&td, &attr, start, &args)) { @@ -71,14 +72,16 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); sem_wait(&args.sem); - pthread_setcancelstate(cs, 0); sem_destroy(&args.sem); if (args.err) { __syscall(SYS_close, s); + pthread_join(td, 0); + pthread_setcancelstate(cs, 0); errno = args.err; return -1; } + pthread_setcancelstate(cs, 0); return 0; } From 0ab97350f01b42de0f9fd811ee08653169661859 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Feb 2023 19:13:10 -0500 Subject: [PATCH 180/297] mq_notify: block all (application) signals in the worker thread until the mq notification event arrives, it is mandatory that signals be blocked. otherwise, a signal can be received, and its handler executed, in a thread which does not yet exist on the abstract machine. after the point of the event arriving, having signals blocked is not a conformance requirement but a QoI requirement. while the application can unblock any signals it wants unblocked in the event handler thread, if they did not start out blocked, it could not block them without a race window where they are momentarily unblocked, and this would preclude controlled delivery or other forms of acceptance (sigwait, etc.) anywhere in the application. --- src/mq/mq_notify.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mq/mq_notify.c b/src/mq/mq_notify.c index 8109dfb2..0e1e6c7a 100644 --- a/src/mq/mq_notify.c +++ b/src/mq/mq_notify.c @@ -50,6 +50,7 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) pthread_t td; int s; int cs; + sigset_t allmask, origmask; if (!sev || sev->sigev_notify != SIGEV_THREAD) return syscall(SYS_mq_notify, mqd, sev); @@ -64,11 +65,15 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); sem_init(&args.sem, 0, 0); + sigfillset(&allmask); + pthread_sigmask(SIG_BLOCK, &allmask, &origmask); if (pthread_create(&td, &attr, start, &args)) { __syscall(SYS_close, s); + pthread_sigmask(SIG_SETMASK, &origmask, 0); errno = EAGAIN; return -1; } + pthread_sigmask(SIG_SETMASK, &origmask, 0); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); sem_wait(&args.sem); From f79b973d92a322800b3e8411ccc95db280d997ae Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 9 Feb 2023 14:50:49 -0800 Subject: [PATCH 181/297] increase sendmsg internal buffer to support SCM_MAX_FD The kernel defines a limit on the number of fds that can be passed through an SCM_RIGHTS ancillary message as SCM_MAX_FD. The value was 255 before kernel 2.6.38 (after that it is 253), and an SCM_RIGHTS ancillary message with 255 fds requires 1040 bytes, slightly more than the current 1024 byte internal buffer in sendmsg. 1024 is an arbitrary size, so increase it to match the the arbitrary size limit in the kernel. This fixes tests that are verifying they support up to SCM_MAX_FD fds. --- src/network/sendmsg.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/network/sendmsg.c b/src/network/sendmsg.c index 80cc5f41..acdfdf29 100644 --- a/src/network/sendmsg.c +++ b/src/network/sendmsg.c @@ -8,13 +8,16 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) { #if LONG_MAX > INT_MAX struct msghdr h; - struct cmsghdr chbuf[1024/sizeof(struct cmsghdr)+1], *c; + /* Kernels before 2.6.38 set SCM_MAX_FD to 255, allocate enough + * space to support an SCM_RIGHTS ancillary message with 255 fds. + * Kernels since 2.6.38 set SCM_MAX_FD to 253. */ + struct cmsghdr chbuf[CMSG_SPACE(255*sizeof(int))/sizeof(struct cmsghdr)+1], *c; if (msg) { h = *msg; h.__pad1 = h.__pad2 = 0; msg = &h; if (h.msg_controllen) { - if (h.msg_controllen > 1024) { + if (h.msg_controllen > sizeof chbuf) { errno = ENOMEM; return -1; } From 7e6da7ac98efdc8167ed2d109298ba232a9a7ba3 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 3 Feb 2023 23:10:17 +0100 Subject: [PATCH 182/297] hsearch: fix null pointer arithmetic UB htab->__tab->entries pointer may be 0 so delay using it in arithmetics. this did not cause any known issue other than with ubsan instrumentation. --- src/search/hsearch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/search/hsearch.c b/src/search/hsearch.c index b3ac8796..2634a67f 100644 --- a/src/search/hsearch.c +++ b/src/search/hsearch.c @@ -41,9 +41,9 @@ static int resize(size_t nel, struct hsearch_data *htab) { size_t newsize; size_t i, j; + size_t oldsize = htab->__tab->mask + 1; ENTRY *e, *newe; ENTRY *oldtab = htab->__tab->entries; - ENTRY *oldend = htab->__tab->entries + htab->__tab->mask + 1; if (nel > MAXSIZE) nel = MAXSIZE; @@ -56,7 +56,7 @@ static int resize(size_t nel, struct hsearch_data *htab) htab->__tab->mask = newsize - 1; if (!oldtab) return 1; - for (e = oldtab; e < oldend; e++) + for (e = oldtab; e < oldtab + oldsize; e++) if (e->key) { for (i=keyhash(e->key),j=1; ; i+=j++) { newe = htab->__tab->entries + (i & htab->__tab->mask); From 7e13e5ae69a243b90b90d2f4b79b2a150f806335 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Thu, 26 Jan 2023 14:47:39 +0300 Subject: [PATCH 183/297] inet_pton: fix uninitialized memory use for IPv4-mapped IPv6 addresses When a dot is encountered, the loop counter is incremented before exiting the loop, but the corresponding ip array element is left uninitialized, so the subsequent memmove (if "::" was seen) and the loop copying ip to the output buffer will operate on an uninitialized uint16_t. The uninitialized data never directly influences the control flow and is overwritten on successful return by the second half of the parsed IPv4 address. But it's better to fix this to avoid unexpected transformations by a sufficiently smart compiler and reports from UB-detection tools. --- src/network/inet_pton.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/inet_pton.c b/src/network/inet_pton.c index d36c3689..bcbdd9ef 100644 --- a/src/network/inet_pton.c +++ b/src/network/inet_pton.c @@ -54,6 +54,7 @@ int inet_pton(int af, const char *restrict s, void *restrict a0) if (s[j]!='.' || (i<6 && brk<0)) return 0; need_v4=1; i++; + ip[i&7]=0; break; } s += j+1; From 35fdfe62a4ff471074ca53b7626ec80e83d244bd Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 20 Jan 2023 11:37:39 +0100 Subject: [PATCH 184/297] math: fix undefined shift in logf A signed int shift overflowed when computing a constant mask, use hex literal instead. This is unlikely to cause actual issues unless the code was compiled with ubsan or similar instrumentation specifically to catch this. The stripped libc.so is unchanged on x86_64. Reported by q66 on irc. --- src/math/logf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/math/logf.c b/src/math/logf.c index 7ee5d7fe..e4c2237c 100644 --- a/src/math/logf.c +++ b/src/math/logf.c @@ -53,7 +53,7 @@ float logf(float x) tmp = ix - OFF; i = (tmp >> (23 - LOGF_TABLE_BITS)) % N; k = (int32_t)tmp >> 23; /* arithmetic shift */ - iz = ix - (tmp & 0x1ff << 23); + iz = ix - (tmp & 0xff800000); invc = T[i].invc; logc = T[i].logc; z = (double_t)asfloat(iz); From 07616721f1fa6cb215ffbef23441cae80412484f Mon Sep 17 00:00:00 2001 From: Gabriel Ravier Date: Wed, 4 Jan 2023 16:07:19 +0100 Subject: [PATCH 185/297] fix return value of wcs{,n}cmp for extreme wchar_t values As a result of using simple subtraction to implement the return values for wcscmp and wcsncmp, integer overflow can occur (producing undefined behavior, and in practice, a wrong comparison result). This does not occur for meaningful character values (21-bit range) but the functions are specified to work on arbitrary wchar_t arrays. This patch replaces the subtraction with a little bit of code that orders the characters correctly, returning -1 if the character from the first string is smaller than the one from the second, 0 if they are equal and 1 if the character from the first string is larger than the one from the second. --- src/string/wcscmp.c | 2 +- src/string/wcsncmp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/string/wcscmp.c b/src/string/wcscmp.c index 26eeee70..286ec3ea 100644 --- a/src/string/wcscmp.c +++ b/src/string/wcscmp.c @@ -3,5 +3,5 @@ int wcscmp(const wchar_t *l, const wchar_t *r) { for (; *l==*r && *l && *r; l++, r++); - return *l - *r; + return *l < *r ? -1 : *l > *r; } diff --git a/src/string/wcsncmp.c b/src/string/wcsncmp.c index 4ab32a92..2b3558bf 100644 --- a/src/string/wcsncmp.c +++ b/src/string/wcsncmp.c @@ -3,5 +3,5 @@ int wcsncmp(const wchar_t *l, const wchar_t *r, size_t n) { for (; n && *l==*r && *l && *r; n--, l++, r++); - return n ? *l - *r : 0; + return n ? (*l < *r ? -1 : *l > *r) : 0; } From 7d756e1c04de6eb3f2b3d3e1141a218bb329fcfb Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 29 Dec 2022 21:21:32 -0600 Subject: [PATCH 186/297] dns: prefer monotonic clock for timeouts Before this commit, DNS timeouts always used CLOCK_REALTIME, which could produce spurious timeouts or delays if wall time changed for whatever reason. Now we try CLOCK_MONOTONIC and only fall back to CLOCK_REALTIME when it is unavailable. --- src/network/res_msend.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 11c6aa0e..fef7e3a2 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -25,7 +25,8 @@ static void cleanup(void *p) static unsigned long mtime() { struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0 && errno == ENOSYS) + clock_gettime(CLOCK_REALTIME, &ts); return (unsigned long)ts.tv_sec * 1000 + ts.tv_nsec / 1000000; } From bc695a5ac1d7929e5c1ad5297eb47e146cccd157 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 23 Feb 2023 10:10:44 -0500 Subject: [PATCH 187/297] fix incorrect unit for CPU_SETSIZE macro this macro is supposed to reflect the number of members (bits) in cpu_set_t, not the storage size (bytes). --- include/sched.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sched.h b/include/sched.h index fda4b484..204c34f5 100644 --- a/include/sched.h +++ b/include/sched.h @@ -124,7 +124,7 @@ __CPU_op_func_S(XOR, ^) #define CPU_ALLOC(n) ((cpu_set_t *)calloc(1,CPU_ALLOC_SIZE(n))) #define CPU_FREE(set) free(set) -#define CPU_SETSIZE 128 +#define CPU_SETSIZE 1024 #define CPU_SET(i, set) CPU_SET_S(i,sizeof(cpu_set_t),set) #define CPU_CLR(i, set) CPU_CLR_S(i,sizeof(cpu_set_t),set) From 12590c8bbd04ea484cee86812e2258fbdfca0e59 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Sat, 28 Jan 2023 00:17:37 +0300 Subject: [PATCH 188/297] fix out-of-bounds reads in __dns_parse There are several issues with range checks in this function: * The question section parsing loop can read up to two out-of-bounds bytes before doing the range check and bailing out. * The answer section parsing loop, in addition to the same issue as above, uses the wrong length in the range check that doesn't prevent OOB reads when computing len later. * The len range check before calling the callback is off by 10. Also, p+len can overflow in a (probably theoretical) case when p is within 2^16 from UINTPTR_MAX. Because __dns_parse is used only with stack-allocated buffers, such small overreads can't result in a segfault. The first two also don't affect the function result, but the last one may result in getaddrinfo incorrectly succeeding and returning up to 10 bytes past the response buffer as a part of the IP address, and in (canon) name returned by getaddrinfo/getnameinfo being affected by memory past the response buffer (because dn_expand might interpret it as a pointer). --- src/network/dns_parse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/dns_parse.c b/src/network/dns_parse.c index e6ee19d9..320df60d 100644 --- a/src/network/dns_parse.c +++ b/src/network/dns_parse.c @@ -15,17 +15,17 @@ int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, c if (qdcount+ancount > 64) return -1; while (qdcount--) { while (p-r < rlen && *p-1U < 127) p++; - if (*p>193 || (*p==193 && p[1]>254) || p>r+rlen-6) + if (p>r+rlen-6 || *p>193 || (*p==193 && p[1]>254)) return -1; p += 5 + !!*p; } while (ancount--) { while (p-r < rlen && *p-1U < 127) p++; - if (*p>193 || (*p==193 && p[1]>254) || p>r+rlen-6) + if (p>r+rlen-12 || *p>193 || (*p==193 && p[1]>254)) return -1; p += 1 + !!*p; len = p[8]*256 + p[9]; - if (p+len > r+rlen) return -1; + if (len+10 > r+rlen-p) return -1; if (callback(ctx, p[1], p+10, len, r) < 0) return -1; p += 10 + len; } From 9b132e556774c744f9052581d2d8d0fab417e97c Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Sun, 29 Jan 2023 19:46:51 +0300 Subject: [PATCH 189/297] prevent CNAME/PTR parsing from reading data past the response end DNS parsing callbacks pass the response buffer end instead of the actual response end to dn_expand, so a malformed DNS response can use message compression to make dn_expand jump past the response end and attempt to parse uninitialized parts of that buffer, which might succeed and return garbage. --- src/network/dns_parse.c | 4 ++-- src/network/getnameinfo.c | 4 ++-- src/network/lookup.h | 2 +- src/network/lookup_name.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/network/dns_parse.c b/src/network/dns_parse.c index 320df60d..7f83e791 100644 --- a/src/network/dns_parse.c +++ b/src/network/dns_parse.c @@ -1,7 +1,7 @@ #include #include "lookup.h" -int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, const void *, int, const void *), void *ctx) +int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, const void *, int, const void *, int), void *ctx) { int qdcount, ancount; const unsigned char *p; @@ -26,7 +26,7 @@ int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, c p += 1 + !!*p; len = p[8]*256 + p[9]; if (len+10 > r+rlen-p) return -1; - if (callback(ctx, p[1], p+10, len, r) < 0) return -1; + if (callback(ctx, p[1], p+10, len, r, rlen) < 0) return -1; p += 10 + len; } return 0; diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c index 949e1811..080d3c06 100644 --- a/src/network/getnameinfo.c +++ b/src/network/getnameinfo.c @@ -108,10 +108,10 @@ static void reverse_services(char *buf, int port, int dgram) __fclose_ca(f); } -static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) +static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet, int plen) { if (rr != RR_PTR) return 0; - if (__dn_expand(packet, (const unsigned char *)packet + 512, + if (__dn_expand(packet, (const unsigned char *)packet + plen, data, c, 256) <= 0) *(char *)c = 0; return 0; diff --git a/src/network/lookup.h b/src/network/lookup.h index ef662725..54b2f8b5 100644 --- a/src/network/lookup.h +++ b/src/network/lookup.h @@ -50,6 +50,6 @@ hidden int __lookup_ipliteral(struct address buf[static 1], const char *name, in hidden int __get_resolv_conf(struct resolvconf *, char *, size_t); hidden int __res_msend_rc(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int, const struct resolvconf *); -hidden int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *); +hidden int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *, int), void *); #endif diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index 5f6867cb..f268bcda 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -111,13 +111,13 @@ struct dpc_ctx { #define ABUF_SIZE 768 -static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) +static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet, int plen) { char tmp[256]; int family; struct dpc_ctx *ctx = c; if (rr == RR_CNAME) { - if (__dn_expand(packet, (const unsigned char *)packet + ABUF_SIZE, + if (__dn_expand(packet, (const unsigned char *)packet + plen, data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp)) strcpy(ctx->canon, tmp); return 0; From bec42ef393c0ad64e699a901ab0746d16bfde251 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Fri, 24 Feb 2023 23:48:55 +0300 Subject: [PATCH 190/297] dns: handle early eof in tcp fallback A zero returned from recvmsg is currently treated as if some data were received, so if a DNS server closes its TCP socket before sending the full answer, __res_msend_rc will spin until the timeout elapses because POLLIN event will be reported on each poll. Fix this by treating an early EOF as an error. --- src/network/res_msend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/res_msend.c b/src/network/res_msend.c index fef7e3a2..2643be22 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -287,7 +287,7 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, }; step_mh(&mh, apos[i]); r = recvmsg(pfd[i].fd, &mh, 0); - if (r < 0) goto out; + if (r <= 0) goto out; apos[i] += r; if (apos[i] < 2) continue; int alen = alen_buf[i][0]*256 + alen_buf[i][1]; From d0b7f9768df133428b6587a5273551c56c46d6a6 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Sat, 25 Feb 2023 01:07:33 +0300 Subject: [PATCH 191/297] dns: fix workaround for systems defaulting to ipv6-only sockets When IPv6 nameservers are present, __res_msend_rc attempts to disable IPV6_V6ONLY socket option to ensure that it can communicate with IPv4 nameservers (if they are present too) via IPv4-mapped IPv6 addresses. However, this option can't be disabled on bound sockets, so setsockopt always fails. --- src/network/res_msend.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 2643be22..86c2fcf4 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -133,6 +133,22 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, family = AF_INET; sl = sizeof sa.sin; } + + /* Convert any IPv4 addresses in a mixed environment to v4-mapped */ + if (fd >= 0 && family == AF_INET6) { + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0); + for (i=0; i= 0) close(fd); @@ -152,21 +168,6 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, pthread_cleanup_push(cleanup, pfd); pthread_setcancelstate(cs, 0); - /* Convert any IPv4 addresses in a mixed environment to v4-mapped */ - if (family == AF_INET6) { - setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0); - for (i=0; i Date: Sat, 25 Feb 2023 18:41:32 +0300 Subject: [PATCH 192/297] fix potential read past end of buffer in getnameinfo host name lookup This is completely analoguous to commit 633183b5d1c2. Similar code called from __lookup_name is not affected because it checks that the line contains the host name surrounded by blanks. --- src/network/getnameinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c index 080d3c06..7abe0fa9 100644 --- a/src/network/getnameinfo.c +++ b/src/network/getnameinfo.c @@ -58,6 +58,7 @@ static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, i if ((p=strchr(line, '#'))) *p++='\n', *p=0; for (p=line; *p && !isspace(*p); p++); + if (!*p) continue; *p++ = 0; if (__lookup_ipliteral(&iplit, line, AF_UNSPEC)<=0) continue; From c499c1084eaccd83e4b6e60883a5d92df0202c5e Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Tue, 28 Feb 2023 03:11:17 +0300 Subject: [PATCH 193/297] accept4: don't fall back to accept if we got unknown flags accept4 emulation via accept ignores unknown flags, so it can spuriously succeed instead of failing (or succeed without doing the action implied by an unknown flag if it's added in a future kernel). Worse, unknown flags trigger the fallback code even on modern kernels if the real accept4 syscall returns EINVAL, because this is indistinguishable from socketcall returning EINVAL due to lack of accept4 support. Fix this by always failing with EINVAL if unknown flags are present and the syscall is missing or failed with EINVAL. --- src/network/accept4.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/network/accept4.c b/src/network/accept4.c index 59ab1726..765a38ed 100644 --- a/src/network/accept4.c +++ b/src/network/accept4.c @@ -9,6 +9,10 @@ int accept4(int fd, struct sockaddr *restrict addr, socklen_t *restrict len, int if (!flg) return accept(fd, addr, len); int ret = socketcall_cp(accept4, fd, addr, len, flg, 0, 0); if (ret>=0 || (errno != ENOSYS && errno != EINVAL)) return ret; + if (flg & ~(SOCK_CLOEXEC|SOCK_NONBLOCK)) { + errno = EINVAL; + return -1; + } ret = accept(fd, addr, len); if (ret<0) return ret; if (flg & SOCK_CLOEXEC) From 1a708ece1ad8b924466e81c5fcdf4e22311fd770 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Mon, 27 Feb 2023 23:05:16 +0300 Subject: [PATCH 194/297] getifaddrs: fix UB via taking address of null pointer union dereference getifaddrs computes &ctx->first->ifa even if ctx->first is NULL. While this shouldn't be possible on the success path because the loopback interface is hardcoded into the kernel, this is still possible on the error path (for example, if __rtnetlink_enumerate couldn't create a socket due to exceeding the fd limit). --- src/network/getifaddrs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/network/getifaddrs.c b/src/network/getifaddrs.c index fed75bd8..74df4d6c 100644 --- a/src/network/getifaddrs.c +++ b/src/network/getifaddrs.c @@ -39,8 +39,8 @@ struct ifaddrs_storage { }; struct ifaddrs_ctx { - struct ifaddrs_storage *first; - struct ifaddrs_storage *last; + struct ifaddrs *first; + struct ifaddrs *last; struct ifaddrs_storage *hash[IFADDRS_HASH_SIZE]; }; @@ -195,9 +195,9 @@ static int netlink_msg_to_ifaddr(void *pctx, struct nlmsghdr *h) } if (ifs->ifa.ifa_name) { - if (!ctx->first) ctx->first = ifs; - if (ctx->last) ctx->last->ifa.ifa_next = &ifs->ifa; - ctx->last = ifs; + if (!ctx->first) ctx->first = &ifs->ifa; + if (ctx->last) ctx->last->ifa_next = &ifs->ifa; + ctx->last = &ifs->ifa; } else { free(ifs); } @@ -210,7 +210,7 @@ int getifaddrs(struct ifaddrs **ifap) int r; memset(ctx, 0, sizeof *ctx); r = __rtnetlink_enumerate(AF_UNSPEC, AF_UNSPEC, netlink_msg_to_ifaddr, ctx); - if (r == 0) *ifap = &ctx->first->ifa; - else freeifaddrs(&ctx->first->ifa); + if (r == 0) *ifap = ctx->first; + else freeifaddrs(ctx->first); return r; } From 595416b11dfbc82d40a59d0edd7e3b04ba7a2d6d Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Mon, 27 Feb 2023 23:18:02 +0300 Subject: [PATCH 195/297] getservbyport_r: fix out-of-bounds buffer read If the buffer passed to getservbyport_r is just enough to store two pointers after aligning it, getnameinfo is called with buflen == 0 (which means that service name is not needed) and trivially succeeds. Then, strtol is called on the address just past the buffer end, and if it doesn't happen to find the port number there, getservbyport_r spuriously succeeds and returns the same bad address to the caller. Fix this by ensuring that buflen is at least 1 when passed to getnameinfo. --- src/network/getservbyport_r.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/getservbyport_r.c b/src/network/getservbyport_r.c index b7f21c6b..d3a22b8c 100644 --- a/src/network/getservbyport_r.c +++ b/src/network/getservbyport_r.c @@ -26,7 +26,7 @@ int getservbyport_r(int port, const char *prots, /* Align buffer */ i = (uintptr_t)buf & sizeof(char *)-1; if (!i) i = sizeof(char *); - if (buflen < 3*sizeof(char *)-i) + if (buflen <= 3*sizeof(char *)-i) return ERANGE; buf += sizeof(char *)-i; buflen -= sizeof(char *)-i; From b1dfb734a45d4f74c7a24c5f07d37f7e74451802 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Mon, 27 Feb 2023 23:33:08 +0300 Subject: [PATCH 196/297] getservbyport_r: fix wrong result if getnameinfo fails with EAI_OVERFLOW EAI_OVERFLOW should be propagated as ERANGE to inform the caller about the need to expand the buffer. --- src/network/getservbyport_r.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/getservbyport_r.c b/src/network/getservbyport_r.c index d3a22b8c..e4cc3079 100644 --- a/src/network/getservbyport_r.c +++ b/src/network/getservbyport_r.c @@ -46,6 +46,8 @@ int getservbyport_r(int port, const char *prots, case EAI_MEMORY: case EAI_SYSTEM: return ENOMEM; + case EAI_OVERFLOW: + return ERANGE; default: return ENOENT; case 0: From fb7fb5e4bd7ccb8efa691364404efc7804fad90c Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 28 Feb 2023 12:18:43 -0500 Subject: [PATCH 197/297] fix pipe2 silently ignoring unknown flags on old kernels kernels using the fallback have an inherent close-on-exec race condition and as such support for them is only best-effort anyway. however, ignoring potential new flags is still very bad behavior. instead, fail with EINVAL. --- src/unistd/pipe2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unistd/pipe2.c b/src/unistd/pipe2.c index f24f74fb..a096990b 100644 --- a/src/unistd/pipe2.c +++ b/src/unistd/pipe2.c @@ -8,6 +8,7 @@ int pipe2(int fd[2], int flag) if (!flag) return pipe(fd); int ret = __syscall(SYS_pipe2, fd, flag); if (ret != -ENOSYS) return __syscall_ret(ret); + if (flag & ~(O_CLOEXEC|O_NONBLOCK)) return __syscall_ret(-EINVAL); ret = pipe(fd); if (ret) return ret; if (flag & O_CLOEXEC) { From c99b7daafdbf1e2415bf408e67ca7813e7ddeedf Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 28 Feb 2023 12:21:23 -0500 Subject: [PATCH 198/297] fix dup3 ignoring all flags but O_CLOEXEC on archs with SYS_dup2 syscall our dup3 code wrongly skipped directly to making the SYS_dup2 syscall whenever the O_CLOEXEC bit of flags was not set. this is incorrect if any new flags are ever added, as it would silently ignore them rather than failing with an error. archs which lack SYS_dup2 were unaffected. adjust the logic so that SYS_dup3 is attempted whenever flags is nonzero, and explicitly fail with EINVAL if SYS_dup3 is unavailable and there are any unknown flags. --- src/unistd/dup3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/unistd/dup3.c b/src/unistd/dup3.c index f919f791..1e7dc3e7 100644 --- a/src/unistd/dup3.c +++ b/src/unistd/dup3.c @@ -9,9 +9,10 @@ int __dup3(int old, int new, int flags) int r; #ifdef SYS_dup2 if (old==new) return __syscall_ret(-EINVAL); - if (flags & O_CLOEXEC) { + if (flags) { while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY); if (r!=-ENOSYS) return __syscall_ret(r); + if (flags & ~O_CLOEXEC) return __syscall_ret(-EINVAL); } while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); if (flags & O_CLOEXEC) __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC); From 3281047cfca0f3848d0613e3c0d19d41b0531564 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 28 Feb 2023 15:44:46 -0500 Subject: [PATCH 199/297] dup3: don't set FD_CLOEXEC on failure on kernels without dup3 syscall this is the best-effort fallback path for kernels that can't actually support the dup3 functionality. it was setting FD_CLOEXEC flag on the target fd (new) even if the dup2 operation failed. normally that shouldn't happen under correct usage, but it's possible if the source fd is not open or intentionally invalid (e.g. -1). --- src/unistd/dup3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/unistd/dup3.c b/src/unistd/dup3.c index 1e7dc3e7..40798bde 100644 --- a/src/unistd/dup3.c +++ b/src/unistd/dup3.c @@ -15,7 +15,8 @@ int __dup3(int old, int new, int flags) if (flags & ~O_CLOEXEC) return __syscall_ret(-EINVAL); } while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); - if (flags & O_CLOEXEC) __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC); + if (r >= 0 && (flags & O_CLOEXEC)) + __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC); #else while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY); #endif From 8949da7ab1c0dbf801e8bc78f0c0adc625020f75 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Thu, 2 Mar 2023 08:10:47 +0300 Subject: [PATCH 200/297] select: fix 64-bit timeout truncation on pre-time64 kernels If the (normalized) timeout passed to select exceeds INT_MAX seconds on an arch with SYS_pselect6_time64 and the kernel is too old to support time64 syscalls, the timeout is implicitly converted to (32-bit) long on the fallback path, losing its upper 32 bits and potentially becoming a small positive value, violating the intended semantics, or even a negative value, causing the fallback syscall failure. Fix this by saturating the timeout at INT_MAX as done in other time64 fallback cases. --- src/select/select.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/select/select.c b/src/select/select.c index 8a786884..f1d72863 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -33,6 +33,7 @@ int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict ((syscall_arg_t[]){ 0, _NSIG/8 })); if (SYS_pselect6 == SYS_pselect6_time64 || r!=-ENOSYS) return __syscall_ret(r); + s = CLAMP(s); #endif #ifdef SYS_select return syscall_cp(SYS_select, n, rfds, wfds, efds, From b6811019e62a7561a4922f90e54b30ac306efe0b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 3 Mar 2023 09:27:04 -0500 Subject: [PATCH 201/297] poll: fix misuse of timespec type on 32-bit archs without poll syscall this function was overlooked during the time64 transition, probably as a result of not having any time-related types in its application-side interface. however, for archs that lack the traditional poll syscall and have only ppoll, it used timespec as part of its interface with the kernel: the millisecond timeout was converted to a timespec to pass to SYS_ppoll. this is a type/ABI mismatch on 32-bit archs with legacy time32 syscalls. only one supported arch, or1k, is affected. all of the others either have SYS_poll, or are 64-bit. rather than using timespec, define a type locally to match what the kernel expects. the condition (SYS_ppoll_time64 == SYS_ppoll), comparable to conditions used elsewhere in timespec-handling code, evaluates true for "natively time64" 32-bit archs including x32, future riscv32, and all future 32-bit archs (via definitions in internal syscall.h). otherwise, the arch is either 64-bit or has syscalls that take the legacy type, and in either case "long" is correct. this fix is based on bug report and proposal by Alexey Izbyshev but with a different approach to the changes to minimize the contextual knowledge needed for a reader to understand the source file. --- src/select/poll.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/select/poll.c b/src/select/poll.c index c84c8a99..7883dfab 100644 --- a/src/select/poll.c +++ b/src/select/poll.c @@ -8,8 +8,13 @@ int poll(struct pollfd *fds, nfds_t n, int timeout) #ifdef SYS_poll return syscall_cp(SYS_poll, fds, n, timeout); #else +#if SYS_ppoll_time64 == SYS_ppoll + typedef long long ppoll_ts_t[2]; +#else + typedef long ppoll_ts_t[2]; +#endif return syscall_cp(SYS_ppoll, fds, n, timeout>=0 ? - &((struct timespec){ .tv_sec = timeout/1000, - .tv_nsec = timeout%1000*1000000 }) : 0, 0, _NSIG/8); + ((ppoll_ts_t){ timeout/1000, timeout%1000*1000000 }) : 0, + 0, _NSIG/8); #endif } From d055e6a45a17673b8dd3ec16e786bb2fe1700dd5 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 20 Mar 2023 13:48:50 -0400 Subject: [PATCH 202/297] fix wide printf forms ignoring width for %lc format specifier since the code path for %c was already doing it right, and the logic is identical, condense them into a single case. --- src/stdio/vfwprintf.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c index 85b036c3..e69a2d5e 100644 --- a/src/stdio/vfwprintf.c +++ b/src/stdio/vfwprintf.c @@ -258,16 +258,13 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ } continue; case 'c': + case 'C': if (w<1) w=1; if (w>1 && !(fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, ""); - fputwc(btowc(arg.i), f); + fputwc(t=='C' ? arg.i : btowc(arg.i), f); if (w>1 && (fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, ""); l = w; continue; - case 'C': - fputwc(arg.i, f); - l = 1; - continue; case 'S': a = arg.p; z = a + wcsnlen(a, p<0 ? INT_MAX : p); From 0440ed69eac766c712e974358c3e09d63e330f40 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 20 Mar 2023 18:48:20 -0400 Subject: [PATCH 203/297] fix wide printf continuation after output or encoding errors this fixes a broader bug for which a special case was reported by Bruno Haible, in the form of %n getting processed (and reporting the number of wide characters which would have been written, but weren't) after an encoding error (EILSEQ). in addition to the %n case, some but not all of the format specifiers continued to attempt output after an error. in particular, %c, %lc, and %s all used fputwc directly without any check for error status. as long as the error condition was permanent rather than transient, these write attempts had no visible side effects, but in theory it could be visible, for example with EAGAIN/EWOULDBLOCK or ENOSPC, if the condition precluding output came to an end. this could produce output with missing non-final data, rather than just truncated output, albeit with the function still returning -1 as expected to report an error. to fix this, a check is added to stop processing of any new directive (including %n) if the stream is already in error state, and direct use of fputwc is replaced with calls to the out() helper function, which checks for error status. note that fprintf is also used directly without checking error status, but due to how commit d42269d7c85308abdbf8cee38b1a1097249eb38b previously attempted to solve the issue of output after error, the call to fprintf does not attempt to write anything when the wide-oriented stream is already in error state. this is non-obvious, and is quite a hack, so it should be changed, but I've left it alone for now to make the bug fix commit itself as non-invasive as possible. --- src/stdio/vfwprintf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c index e69a2d5e..119fdffc 100644 --- a/src/stdio/vfwprintf.c +++ b/src/stdio/vfwprintf.c @@ -242,6 +242,10 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ } if (!f) continue; + + /* Do not process any new directives once in error state. */ + if (ferror(f)) return -1; + t = s[-1]; if (ps && (t&15)==3) t&=~32; @@ -261,7 +265,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ case 'C': if (w<1) w=1; if (w>1 && !(fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, ""); - fputwc(t=='C' ? arg.i : btowc(arg.i), f); + out(f, &(wchar_t){t=='C' ? arg.i : btowc(arg.i)}, 1); if (w>1 && (fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, ""); l = w; continue; @@ -291,7 +295,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ while (l--) { i=mbtowc(&wc, bs, MB_LEN_MAX); bs+=i; - fputwc(wc, f); + out(f, &wc, 1); } if ((fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, ""); l=w; From 3a051769c4a91c3a7d1f1310d888faa4abf363e7 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 20 Mar 2023 19:07:54 -0400 Subject: [PATCH 204/297] fix (normal, narrow) printf erroneously processing %n after output errors unlike with wide printf variants, encoding errors are not a vector by which this bug is reachable, and the out() helper function already ensured that no further output could be written after an output error, transient or otherwise. however, the %n specifier could still be processed after an error, yielding a side effect that wrongly implied output had succeeded. due to buffering effects, it's still possible for %n to show output as having "succeeded", but for it never to appear on the underlying file due to an error at flush time. this change, however, ensures that processing of %n does not conflict with any error which has already been seen. --- src/stdio/vfprintf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 45557951..2dbdb5e2 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -530,6 +530,9 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, if (!f) continue; + /* Do not process any new directives once in error state. */ + if (ferror(f)) return -1; + z = buf + sizeof(buf); prefix = "-+ 0X0x"; pl = 0; From 868c96430093cd864512283b43071cb70b39b24e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 20 Mar 2023 18:59:14 -0400 Subject: [PATCH 205/297] remove wide printf dependency on ugly hack in vfprintf commit d42269d7c85308abdbf8cee38b1a1097249eb38b appropriated the stream error flag temporarily to let the printf family of functions suppress further output attempts after encountering a write error. since the wide printf code relies on (narrow) vfprintf to print padding and numeric conversions, a hack was put in vfprintf not to clear the initial error status unless the stream is narrow oriented. this was okay, because calling vfprintf on a wide-oriented stream (outside of internal use by the implementation) produces undefined behavior. however, it was highly non-obvious to anyone reading the wide printf code, where the calls to fprintf without first checking for error status appeared erroneous. this patch removes all direct use of fprintf from the wide printf core, except in the numeric conversions case where it was already checked before starting processing of the directive that the error status is not set. the other calls, which were performing padding, are replaced by a new pad() helper function, which performs the check and abstracts out the mechanism of writing the padding. direct use of the error flag is also replaced by ferror, which is defined as a macro in stdio_impl.h, expanding directly to the flag check with no call or locking overhead. --- src/stdio/vfprintf.c | 2 +- src/stdio/vfwprintf.c | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 2dbdb5e2..7b848080 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -677,7 +677,7 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) FLOCK(f); olderr = f->flags & F_ERR; - if (f->mode < 1) f->flags &= ~F_ERR; + f->flags &= ~F_ERR; if (!f->buf_size) { saved_buf = f->buf; f->buf = internal_buf; diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c index 119fdffc..18784113 100644 --- a/src/stdio/vfwprintf.c +++ b/src/stdio/vfwprintf.c @@ -125,7 +125,13 @@ static void pop_arg(union arg *arg, int type, va_list *ap) static void out(FILE *f, const wchar_t *s, size_t l) { - while (l-- && !(f->flags & F_ERR)) fputwc(*s++, f); + while (l-- && !ferror(f)) fputwc(*s++, f); +} + +static void pad(FILE *f, int n, int fl) +{ + if ((fl & LEFT_ADJ) || !n || ferror(f)) return; + fprintf(f, "%*s", n, ""); } static int getint(wchar_t **s) { @@ -264,9 +270,9 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ case 'c': case 'C': if (w<1) w=1; - if (w>1 && !(fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, ""); + pad(f, w-1, fl); out(f, &(wchar_t){t=='C' ? arg.i : btowc(arg.i)}, 1); - if (w>1 && (fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, ""); + pad(f, w-1, fl^LEFT_ADJ); l = w; continue; case 'S': @@ -275,9 +281,9 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ if (p<0 && *z) goto overflow; p = z-a; if (wflags & F_ERR; f->flags &= ~F_ERR; ret = wprintf_core(f, fmt, &ap2, nl_arg, nl_type); - if (f->flags & F_ERR) ret = -1; + if (ferror(f)) ret = -1; f->flags |= olderr; FUNLOCK(f); va_end(ap2); From 0e5234807dcdc76c43f9313c6ba9e2b7da408d8c Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 20 Mar 2023 19:16:21 -0400 Subject: [PATCH 206/297] in printf, use ferror macro rather than directly inspecting flags bit this is purely aesthetic and should not affect code generation or functionality. --- src/stdio/vfprintf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 7b848080..a712d80f 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -132,7 +132,7 @@ static void pop_arg(union arg *arg, int type, va_list *ap) static void out(FILE *f, const char *s, size_t l) { - if (!(f->flags & F_ERR)) __fwritex((void *)s, l, f); + if (!ferror(f)) __fwritex((void *)s, l, f); } static void pad(FILE *f, char c, int w, int l, int fl) @@ -693,7 +693,7 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) f->buf_size = 0; f->wpos = f->wbase = f->wend = 0; } - if (f->flags & F_ERR) ret = -1; + if (ferror(f)) ret = -1; f->flags |= olderr; FUNLOCK(f); va_end(ap2); From 1d5750b95c06913a1f18a995481276d698d20fae Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 22 Mar 2023 12:56:46 -0400 Subject: [PATCH 207/297] fix swprintf handling of nul character in output the buffer-flush function did not account for mbtowc returning 0 rather than 1 when converting the nul character. this prevented advancing past it, instead repeatedly converting it into the output wide character string until the max output length was exhausted. --- src/stdio/vswprintf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stdio/vswprintf.c b/src/stdio/vswprintf.c index 7f98c5c9..fc223cf2 100644 --- a/src/stdio/vswprintf.c +++ b/src/stdio/vswprintf.c @@ -18,6 +18,7 @@ static size_t sw_write(FILE *f, const unsigned char *s, size_t l) if (s!=f->wbase && sw_write(f, f->wbase, f->wpos-f->wbase)==-1) return -1; while (c->l && l && (i=mbtowc(c->ws, (void *)s, l))>=0) { + if (!i) i=1; s+=i; l-=i; c->l--; From 77327ed064bd57b0e1865cd0e0364057ff4a53b4 Mon Sep 17 00:00:00 2001 From: Alexey Kodanev Date: Wed, 22 Mar 2023 17:48:40 +0300 Subject: [PATCH 208/297] dns: check length field in tcp response message The received length field in the message may be greater than the size of the 'answer' buffer in which the message resides. Currently, ABUF_SIZE is 768. And if we get a larger 'alens[i]', it will result in an out-of-bounds reading in __dns_parse(). To fix this, limit the length to the size of the received buffer. --- src/network/lookup_name.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index f268bcda..4281482e 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -179,6 +179,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static for (i=nq-1; i>=0; i--) { ctx.rrtype = qtypes[i]; + if (alens[i] > sizeof(abuf[i])) alens[i] = sizeof abuf[i]; __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); } From 7c41047285a24a97e700b4fb5b6b69f4505e2d82 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 11 Apr 2023 09:06:27 -0400 Subject: [PATCH 209/297] fix inadvertently static local var in dynlink get_lfs64 commit 246f1c811448f37a44b41cd8df8d0ef9736d95f4 inadvertently introduced the local variable p as static by declaring it together with lfs64_list. the function is only reachable under lock, and is not called reentrantly, so this is not a functional bug, but it is confusing and inefficient. fix by separating the declarations. --- ldso/dynlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index fde5f346..ceca3c98 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -345,7 +345,8 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def) static struct symdef get_lfs64(const char *name) { - static const char *p, lfs64_list[] = + const char *p; + static const char lfs64_list[] = "aio_cancel\0aio_error\0aio_fsync\0aio_read\0aio_return\0" "aio_suspend\0aio_write\0alphasort\0creat\0fallocate\0" "fgetpos\0fopen\0freopen\0fseeko\0fsetpos\0fstat\0" From 35e9831156efc1b54e1a91917ba0f787d5df3353 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Fri, 10 Mar 2023 17:00:50 +0300 Subject: [PATCH 210/297] nftw: fix use of uninitialized struct stat If lstat/stat fails with EACCES, st is left uninitialized, but its st_dev/st_ino fields are then used in several places: * for FTW_MOUNT check (in practice typically results in a false positive and an early return) * for copying to the new struct history (though the struct is not used afterwards since we don't recurse in this case) * for cycle detection check (could theoretically result in a false positive and an early return) To avoid adding FTW_NS checks to all these places, fix this by zero-initializing st_dev/st_ino (which can never match an existing dentry due to zero inode being reserved in Linux), and check for FTW_NS only when handling FTW_MOUNT since we need two valid dentries there. --- src/misc/nftw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/misc/nftw.c b/src/misc/nftw.c index fcd25a73..71bc62ee 100644 --- a/src/misc/nftw.c +++ b/src/misc/nftw.c @@ -31,6 +31,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, int err; struct FTW lev; + st.st_dev = st.st_ino = 0; + if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) { if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st)) type = FTW_SLN; @@ -46,7 +48,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, type = FTW_F; } - if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev) + if ((flags & FTW_MOUNT) && h && type != FTW_NS && st.st_dev != h->dev) return 0; new.chain = h; From 6d322159c633050a405b03b927db76b89e402014 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Fri, 10 Mar 2023 20:00:31 +0300 Subject: [PATCH 211/297] getopt: fix null pointer arithmetic ub When an option that requires an argument is the last character of argv[argc-1], getopt computes argv[argc] + optpos. While optpos is always zero in this case, adding it to null pointer is still undefined. --- src/misc/getopt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/misc/getopt.c b/src/misc/getopt.c index c3f66995..b02b81c3 100644 --- a/src/misc/getopt.c +++ b/src/misc/getopt.c @@ -87,7 +87,8 @@ int getopt(int argc, char * const argv[], const char *optstring) if (optstring[i] == ':') { optarg = 0; if (optstring[i+1] != ':' || optpos) { - optarg = argv[optind++] + optpos; + optarg = argv[optind++]; + if (optpos) optarg += optpos; optpos = 0; } if (optind > argc) { From 9b12982d52c5bc5b0158c07dfdbd5485f3a773a0 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Mon, 6 Mar 2023 20:56:25 +0300 Subject: [PATCH 212/297] semtimedop: fix timespec kernel ABI mismatch for 32-bit timeouts on x32 For time64 support, musl normally defines SYS_foo to the time32 variant of that syscall on arches that have it, and to the time64 variant otherwise, so that "SYS_foo == SYS_foo_time64" implies that the arch is time64-only. However, SYS_semtimedop is an odd case: some arches define only SYS_semtimedop_time64, yet they are not time64-only, because the time32 variant is provided via SYS_ipc instead. For such arches, defining SYS_semtimedop to SYS_semtimedop_time64 would break the implication above, so commit 4bbd7baea7c8538b3fb8e30f7b022a1eee071450 doesn't do this. Commit eb2e298cdc814493a6ced8c05cf0d0f5cccc8b63 attempts to detect time64-only arches by checking that both SYS_semtimedop and SYS_ipc are undefined, but this doesn't work for x32, because it's a time64-only arch that does define SYS_semtimedop. As a result, 32-bit timeouts trigger the fallback path that passes a 32-bit timespec to the kernel while it expects a 64-bit one, so the effective tv_sec is formed by interpreting 32-bit tv_sec and tv_nsec as a single long long, and the effective tv_nsec is whatever is located in the next 64 bits of the stack. Fix this by expanding the time64-only check to include arches where SYS_semtimedop is the time64 variant of the syscall. --- src/ipc/semtimedop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ipc/semtimedop.c b/src/ipc/semtimedop.c index 1632e7b0..a104af21 100644 --- a/src/ipc/semtimedop.c +++ b/src/ipc/semtimedop.c @@ -7,7 +7,8 @@ #define IS32BIT(x) !((x)+0x80000000ULL>>32) #define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63)) -#if !defined(SYS_semtimedop) && !defined(SYS_ipc) +#if !defined(SYS_semtimedop) && !defined(SYS_ipc) || \ + SYS_semtimedop == SYS_semtimedop_time64 #define NO_TIME32 1 #else #define NO_TIME32 0 From c1b42c4a3a0324ec25877980f59db233fa420925 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Mon, 6 Mar 2023 11:59:21 +0300 Subject: [PATCH 213/297] wait4: fix missing rusage on x32 due to wrong success condition Resource usage data is filled by the kernel only when wait4 returns a pid, i.e. a positive value. Commit 5850546e9669f793aab61dfc7c4f2c1ff35c4b29 introduced this bug, possibly because of copy-pasting from getrusage. --- src/linux/wait4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/wait4.c b/src/linux/wait4.c index 83650e34..ff2e3e66 100644 --- a/src/linux/wait4.c +++ b/src/linux/wait4.c @@ -12,7 +12,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru) if (ru) { long long kru64[18]; r = __syscall(SYS_wait4_time64, pid, status, options, kru64); - if (!r) { + if (r > 0) { ru->ru_utime = (struct timeval) { .tv_sec = kru64[0], .tv_usec = kru64[1] }; ru->ru_stime = (struct timeval) From 4724793f96b163e95cb15e1b7374ff2b0434ed15 Mon Sep 17 00:00:00 2001 From: Gabriel Ravier Date: Fri, 14 Apr 2023 16:55:42 +0200 Subject: [PATCH 214/297] fix wide printf numbered argument buffer overflow The nl_type and nl_arg arrays defined in vfwprintf may be accessed with an index up to and including NL_ARGMAX, but they are only of size NL_ARGMAX, meaning they may be written to or read from 1 element too far. --- src/stdio/vfwprintf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c index 18784113..53697701 100644 --- a/src/stdio/vfwprintf.c +++ b/src/stdio/vfwprintf.c @@ -347,8 +347,8 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_ int vfwprintf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap) { va_list ap2; - int nl_type[NL_ARGMAX] = {0}; - union arg nl_arg[NL_ARGMAX]; + int nl_type[NL_ARGMAX+1] = {0}; + union arg nl_arg[NL_ARGMAX+1]; int olderr; int ret; From b928c7234f62c35a9b4927586ff4c3cbf6e513b5 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 24 Apr 2023 11:21:13 -0400 Subject: [PATCH 215/297] fix return value of wmemcmp for extreme wchar_t values analogous to the bug in wcscmp and wcsncmp that was fixed in commit 07616721f1fa6cb215ffbef23441cae80412484f. --- src/string/wmemcmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string/wmemcmp.c b/src/string/wmemcmp.c index 2a193263..717d77b1 100644 --- a/src/string/wmemcmp.c +++ b/src/string/wmemcmp.c @@ -3,5 +3,5 @@ int wmemcmp(const wchar_t *l, const wchar_t *r, size_t n) { for (; n && *l==*r; n--, l++, r++); - return n ? *l-*r : 0; + return n ? (*l < *r ? -1 : *l > *r) : 0; } From f5f55d6589940fd2c2188d76686efe3a530e64e0 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 1 May 2023 23:39:41 -0400 Subject: [PATCH 216/297] release 1.2.4 --- VERSION | 2 +- WHATSNEW | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0495c4a8..e8ea05db 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.3 +1.2.4 diff --git a/WHATSNEW b/WHATSNEW index f9bb2482..c5c8c9f4 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -2327,3 +2327,72 @@ bugs fixed: arch-specific bugs fixed: - powerpc (32-bit) struct shmid_ds layout was wrong for some fields - time64 struct layout was wrong in sound ioctl fallback (32-bit archs) + + + +1.2.4 release notes + +new features: +- large dns record lookups via tcp fallback +- new getaddrinfo EAI_NODATA result to distinguish NODATA/NxDomain +- support for new RELR compressed format for relative relocations +- sysconf keys for querying signal stack size requirements +- real vfork on riscv64 + +performance: +- mallocng no longer uses MADV_FREE (high performance cost, little gain) +- vdso clock_gettime is supported once again on 32-bit arm + +compatibility: +- gethostbyname family now distinguishes NO_DATA from HOST_NOT_FOUND +- res_send now works with caller-provided edns0 queries +- arpa/nameser.h RR types list is now up-to-date +- previously-missing POSIX confstr keys have been added +- mntent interfaces now accept missing fields +- alt signal stack, if any, is now used for internal signals +- the LFS64 macros are no longer exposed without _LARGEFILE64_SOURCE +- memmem (POSIX-future) is now exposed in default feature profile +- pthread_atfork now admits calls from an application-provided malloc +- debugger tracking of shared libraries now works on MIPS PIE binaries +- sendmsg now supports up to SCM_MAX_FD fds in SCM_RIGHTS messages + +bugs fixed: +- gethostbyname[2]_r wrongly returned nonzero (error) on negative result +- parallel v4/v6 address queries could fail on query id collisions +- spurious getaddrinfo/AI_ADDRCONFIG failures due to errno clobbering +- dns search domains ending in dot (including lone dot) broke lookups +- ipv6 servers in resolv.conf broke lookups on systems with v6 disabled +- systems with bindv6only failed to query both v4 and v6 nameservers +- res_mkquery mishandled consecutive final dots in name +- res_send could malfunction for very small answer buffer sizes +- resolver dns backend accepted answers with wrong (A vs AAAA) RR type +- getservbyport_r returned junk or ENOENT (vs ERANGE) on buffer size errors +- dns result parsing of malformed responses could process uninitialized data +- freopen didn't reset stream orientation (byte/wide) & encoding rule +- fwprintf didn't print most fields on open_wmemstream FILEs +- wide printf %lc ignored field width +- wide printf erroneously processed %n after encoding errors +- use of wide printf %9$ argument slot overflowed undersized buffer +- swprintf malfunctioned on nul character in output +- strverscmp ordered digit sequences vs nondigits incorrectly +- timer_create/SIGEV_THREAD failure leaked the thread +- semaphores were subject to missed-wake under certain usage patterns +- several possible rare deadlocks with lock handling at thread exit +- several possible rare deadlocks with aio and multithreaded fork +- dynamic linker relro processing was broken on archs w/variable pagesize +- async cancellation could run cancellation handlers in invalid context +- pthread_detach was wrongly a cancellation point in rare race code path +- use-after-close/double-close errors in mq_notify error paths +- mq_notify event thread wrongly ran with signals unmasked +- wcs{,n}cmp, wmemcmp returned wrong results when difference overflowed +- accept4, pipe2, and dup3 handled unknown flags wrong in fallback cases +- CPU_SETSIZE macro had wrong unit +- select fallback for pre-time64 kernels truncated timeout (vs clamping) + +arch-specific bugs fixed: +- x32 new socketcalls took fallback path due to pointer sign extension +- x32 wait4 didn't fill rusage structure (time64 regression) +- x32 semtimedop mismatched timespec ABI with kernel (time64 regression) +- sigaction signal mask was bogus on or1k, microblaze, mips, and riscv +- powerpc-sf longjmp asm clobbered value argument +- or1k poll function passed timeout to syscall in wrong form From 718f363bc2067b6487900eddc9180c84e7739f80 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 2 May 2023 11:45:28 -0400 Subject: [PATCH 217/297] move fallocate64 declaration under _LARGEFILE64_SOURCE feature test overlooked in commit 25e6fee27f4a293728dd15b659170e7b9c7db9bc, probably because the fallocate function itself is nonstandard and already under _GNU_SOURCE. --- include/fcntl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/fcntl.h b/include/fcntl.h index 515f255d..53f98a8b 100644 --- a/include/fcntl.h +++ b/include/fcntl.h @@ -184,7 +184,6 @@ struct f_owner_ex { #define SPLICE_F_MORE 4 #define SPLICE_F_GIFT 8 int fallocate(int, int, off_t, off_t); -#define fallocate64 fallocate int name_to_handle_at(int, const char *, struct file_handle *, int *, int); int open_by_handle_at(int, struct file_handle *, int); ssize_t readahead(int, off_t, size_t); @@ -207,6 +206,9 @@ ssize_t tee(int, int, size_t, unsigned); #define posix_fadvise64 posix_fadvise #define posix_fallocate64 posix_fallocate #define off64_t off_t +#if defined(_GNU_SOURCE) +#define fallocate64 fallocate +#endif #endif #ifdef __cplusplus From b90841e2583237a4132bbbd74752e0e9563660cd Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 21 May 2023 12:16:11 -0400 Subject: [PATCH 218/297] configure: replace -Os with equivalent based on -O2 aside from the documented differences, which are the contents of this patch, GCC's -Os also has hard-coded unwanted behaviors which are impossible to override, like refusing to strength-reduce division by a constant to multiplication, presumably because the div saves a couple bytes of code. for this reason, getting rid of -Os and switching to an equivalent default optimization profile based on -O2 has been a long-term goal. as follow-ups, it may make sense to evaluate which of these variations from -O2 actually do anything useful, and eliminate the ones which are not helpful or which throw away performance for insignificant size savings. but for now, I've replicated -Os as closely as possible to provide a baseline for such evaluation. --- configure | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 853bf05e..0b966ede 100755 --- a/configure +++ b/configure @@ -444,7 +444,20 @@ xno|x) printf "disabled\n" ; optimize=no ;; *) printf "custom\n" ;; esac -test "$optimize" = no || tryflag CFLAGS_AUTO -Os || tryflag CFLAGS_AUTO -O2 +if test "$optimize" = no ; then : +else +tryflag CFLAGS_AUTO -O2 +tryflag CFLAGS_AUTO -fno-align-jumps +tryflag CFLAGS_AUTO -fno-align-functions +tryflag CFLAGS_AUTO -fno-align-loops +tryflag CFLAGS_AUTO -fno-align-labels +tryflag CFLAGS_AUTO -fira-region=one +tryflag CFLAGS_AUTO -fira-hoist-pressure +tryflag CFLAGS_AUTO -freorder-blocks-algorithm=simple \ +|| tryflag CFLAGS_AUTO -fno-reorder-blocks +tryflag CFLAGS_AUTO -fno-prefetch-loop-arrays +tryflag CFLAGS_AUTO -fno-tree-ch +fi test "$optimize" = yes && optimize="internal,malloc,string" if fnmatch 'no|size' "$optimize" ; then : From 4653b98711f280270fa049654460610f587ba7b4 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Fri, 26 May 2023 19:34:14 +0300 Subject: [PATCH 219/297] mbrtowc: Fix wrong return value when n > UINT_MAX mbrtowc truncates n to unsigned int when storing its copy. If n > UINT_MAX and the locale is not POSIX, the function will return a wrong value greater than UINT_MAX on the success path. --- src/multibyte/mbrtowc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multibyte/mbrtowc.c b/src/multibyte/mbrtowc.c index c94819e7..7824997e 100644 --- a/src/multibyte/mbrtowc.c +++ b/src/multibyte/mbrtowc.c @@ -8,7 +8,7 @@ size_t mbrtowc(wchar_t *restrict wc, const char *restrict src, size_t n, mbstate static unsigned internal_state; unsigned c; const unsigned char *s = (const void *)src; - const unsigned N = n; + const size_t N = n; wchar_t dummy; if (!st) st = (void *)&internal_state; From 0c277ff156749628c678257f878d3a6edb5868de Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 1 Jun 2023 16:09:32 -0400 Subject: [PATCH 220/297] fix broken thread list unlocking after fork apparently Linux clears the registered exit futex address on fork. this means that, if after forking the child process becomes multithreaded and the original thread exits, the thread list will never be unlocked, and future attempts to use the thread list will deadlock. re-register the exit futex address after _Fork in the child to ensure that it's preserved. --- src/process/_Fork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/process/_Fork.c b/src/process/_Fork.c index fb0fdc2c..e7650863 100644 --- a/src/process/_Fork.c +++ b/src/process/_Fork.c @@ -22,7 +22,7 @@ pid_t _Fork(void) #endif if (!ret) { pthread_t self = __pthread_self(); - self->tid = __syscall(SYS_gettid); + self->tid = __syscall(SYS_set_tid_address, &__thread_list_lock); self->robust_list.off = 0; self->robust_list.pending = 0; self->next = self->prev = self; From fa4a8abd06a401822cc8ba4e352a219544c0118d Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 31 May 2023 12:04:06 -0400 Subject: [PATCH 221/297] fix public clone function to be safe and usable by applications the clone() function has been effectively unusable since it was added, due to producing a child process with inconsistent state. in particular, the child process's thread structure still contains the tid, thread list pointers, thread count, and robust list for the parent. this will cause malfunction in interfaces that attempt to use the tid or thread list, some of which are specified to be async-signal-safe. this patch attempts to make clone() consistent in a _Fork-like sense. as in _Fork, when the parent process is multi-threaded, the child process inherits an async-signal context where it cannot call AS-unsafe functions, but its context is now intended to be safe for calling AS-safe functions. making clone fork-like would also be a future option, if it turns out that this is what makes sense to applications, but it's not done at this time because the changes would be more invasive. in the case where the CLONE_VM flag is used, clone is only vfork-like, not _Fork-like. in particular, the child will see itself as having the parent's tid, and cannot safely call any libc functions but one of the exec family or _exit. handling of flags and variadic arguments is also changed so that arguments are only consumed with flags that indicate their presence, and so that flags which produce an inconsistent state are disallowed (reported as EINVAL). in particular, all libc functions carry a contract that they are only callable with ABI requirements met, which includes having a valid thread pointer to a thread structure that's unique within the process, and whose contents are opaque and only able to be setup internally by the implementation. the only way for an application to use flags that violate these requirements without executing any libc code is to perform the syscall from application-provided asm. --- src/internal/fork_impl.h | 2 ++ src/linux/clone.c | 56 +++++++++++++++++++++++++++++++++++----- src/process/_Fork.c | 26 ++++++++++++------- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/internal/fork_impl.h b/src/internal/fork_impl.h index 354e733b..f995fce2 100644 --- a/src/internal/fork_impl.h +++ b/src/internal/fork_impl.h @@ -17,3 +17,5 @@ extern hidden volatile int *const __vmlock_lockptr; hidden void __malloc_atfork(int); hidden void __ldso_atfork(int); hidden void __pthread_key_atfork(int); + +hidden void __post_Fork(int); diff --git a/src/linux/clone.c b/src/linux/clone.c index 8c1af7d3..257c1cec 100644 --- a/src/linux/clone.c +++ b/src/linux/clone.c @@ -4,18 +4,62 @@ #include #include "pthread_impl.h" #include "syscall.h" +#include "lock.h" +#include "fork_impl.h" + +struct clone_start_args { + int (*func)(void *); + void *arg; + sigset_t sigmask; +}; + +static int clone_start(void *arg) +{ + struct clone_start_args *csa = arg; + __post_Fork(0); + __restore_sigs(&csa->sigmask); + return csa->func(csa->arg); +} int clone(int (*func)(void *), void *stack, int flags, void *arg, ...) { + struct clone_start_args csa; va_list ap; - pid_t *ptid, *ctid; - void *tls; + pid_t *ptid = 0, *ctid = 0; + void *tls = 0; + + /* Flags that produce an invalid thread/TLS state are disallowed. */ + int badflags = CLONE_THREAD | CLONE_SETTLS | CLONE_CHILD_CLEARTID; + + if ((flags & badflags) || !stack) + return __syscall_ret(-EINVAL); va_start(ap, arg); - ptid = va_arg(ap, pid_t *); - tls = va_arg(ap, void *); - ctid = va_arg(ap, pid_t *); + 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 __syscall_ret(__clone(func, stack, flags, arg, ptid, tls, ctid)); + /* If CLONE_VM is used, it's impossible to give the child a consistent + * thread structure. In this case, the best we can do is assume the + * caller is content with an extremely restrictive execution context + * like the one vfork() would provide. */ + if (flags & CLONE_VM) return __syscall_ret( + __clone(func, stack, flags, arg, ptid, tls, ctid)); + + __block_all_sigs(&csa.sigmask); + LOCK(__abort_lock); + + /* Setup the a wrapper start function for the child process to do + * mimic _Fork in producing a consistent execution state. */ + csa.func = func; + csa.arg = arg; + int ret = __clone(clone_start, stack, flags, &csa, ptid, tls, ctid); + + __post_Fork(ret); + __restore_sigs(&csa.sigmask); + return __syscall_ret(ret); } diff --git a/src/process/_Fork.c b/src/process/_Fork.c index e7650863..9c07792d 100644 --- a/src/process/_Fork.c +++ b/src/process/_Fork.c @@ -5,21 +5,13 @@ #include "lock.h" #include "pthread_impl.h" #include "aio_impl.h" +#include "fork_impl.h" static void dummy(int x) { } weak_alias(dummy, __aio_atfork); -pid_t _Fork(void) +void __post_Fork(int ret) { - pid_t ret; - sigset_t set; - __block_all_sigs(&set); - LOCK(__abort_lock); -#ifdef SYS_fork - ret = __syscall(SYS_fork); -#else - ret = __syscall(SYS_clone, SIGCHLD, 0); -#endif if (!ret) { pthread_t self = __pthread_self(); self->tid = __syscall(SYS_set_tid_address, &__thread_list_lock); @@ -32,6 +24,20 @@ pid_t _Fork(void) } UNLOCK(__abort_lock); if (!ret) __aio_atfork(1); +} + +pid_t _Fork(void) +{ + pid_t ret; + sigset_t set; + __block_all_sigs(&set); + LOCK(__abort_lock); +#ifdef SYS_fork + ret = __syscall(SYS_fork); +#else + ret = __syscall(SYS_clone, SIGCHLD, 0); +#endif + __post_Fork(ret); __restore_sigs(&set); return __syscall_ret(ret); } From 3a23cd06b08054f81bf904c414e0d083a56248f2 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 12 Jun 2023 19:56:08 -0400 Subject: [PATCH 222/297] all printf variants: fix argument type handling for %c and %lc %c takes an argument of type int, not char, and %lc/%C takes an argument of type wint_t (unsigned), not int. for most cases, this makes no practical difference, but since wide printf variants convert narrow %c format specifiers via btowc, interpreting the promoted-to-int unsigned char value passed in as a (signed, on most archs) char causes 255 to get collapsed to EOF and interpreted as such by btowc. this is only relevant in the byte-based C locale, so prior to commit f22a9edaf8a6f2ca1d314d18b3785558279a5c03, there was no observable distinction in behavior. for UTF-8, all bytes which might be negative when interpreted as char are encoding errors when used with %c/btowc. --- src/stdio/vfprintf.c | 4 ++-- src/stdio/vfwprintf.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index a712d80f..c551ccf0 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -52,7 +52,7 @@ static const unsigned char states[]['z'-'A'+1] = { S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, - S('c') = CHAR, S('C') = INT, + S('c') = INT, S('C') = UINT, S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR, S('m') = NOARG, S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, @@ -62,7 +62,7 @@ static const unsigned char states[]['z'-'A'+1] = { S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG, S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, - S('c') = INT, S('s') = PTR, S('n') = PTR, + S('c') = UINT, S('s') = PTR, S('n') = PTR, S('l') = LLPRE, }, { /* 2: ll-prefixed */ S('d') = LLONG, S('i') = LLONG, diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c index 53697701..59d5471b 100644 --- a/src/stdio/vfwprintf.c +++ b/src/stdio/vfwprintf.c @@ -45,7 +45,7 @@ static const unsigned char states[]['z'-'A'+1] = { S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, - S('c') = CHAR, S('C') = INT, + S('c') = INT, S('C') = UINT, S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR, S('m') = NOARG, S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, @@ -55,7 +55,7 @@ static const unsigned char states[]['z'-'A'+1] = { S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG, S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, - S('c') = INT, S('s') = PTR, S('n') = PTR, + S('c') = UINT, S('s') = PTR, S('n') = PTR, S('l') = LLPRE, }, { /* 2: ll-prefixed */ S('d') = LLONG, S('i') = LLONG, From 40834f6c1e30cc25c608678c372db498a3d9dbc3 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 12 Jun 2023 20:04:22 -0400 Subject: [PATCH 223/297] printf core: fix gratuitous integer formatting buffer size the extra terms 3 and LDBL_MANT_DIG/4 are remnants of a proto-musl implementation of printf where the sign/prefix and floating point conversions were performed naively into this buffer. having them there obscures the actual intended buffer size (sufficient to hold between 2 and 3 octal digits per byte, rounded up to 3 for simplicity) and interferes with upcoming work to add C2x binary formats which would otherwise be stuck having to explain a similar fix to buffer size as part of an unrelated change. --- src/stdio/vfprintf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index c551ccf0..33019ff1 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -437,7 +437,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, unsigned st, ps; int cnt=0, l=0; size_t i; - char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4]; + char buf[sizeof(uintmax_t)*3]; const char *prefix; int t, pl; wchar_t wc[2], *ws; From a4ecaf89a9b88df76e8bf9f28e1cc6cb89e4bfa8 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 4 Jul 2023 23:11:17 -0400 Subject: [PATCH 224/297] dns stub resolver: increase buffer size to handle chained CNAMEs in the event of chained CNAMEs, the answer to a query will contain the entire CNAME chain, not just one CNAME record. previously, the answer buffer size had been chosen to admit a maximal-length CNAME, but only one. a moderate-length chain could fill the available 768 bytes leaving no room for an actual address answering the query. while the DNS RFCs do not specify any limit on the length of a CNAME chain, or any reasonable behavior is the chain exceeds the entire 64k possible message size, actual recursive servers have to impose a limit, and a such, for all practical purposes, chains longer than this limit are not usable. it turns out BIND has a hard-coded limit of 16, and Unbound has a default limit of 11. assuming the recursive server makes use of "compression" (pointers), each maximal-length CNAME record takes at most 268 bytes, and thus any chain up to length 16 fits in at most 4288 bytes. this patch increases the answer buffer size to preserve the original intent of having 512 bytes available for address answers, plus space needed for a maximal CNAME chain, for a total of 4800 bytes. the resulting size of 9600 bytes for two queries (A+AAAA) is still well within what is reasonable to place in automatic storage. --- src/network/lookup_name.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index 4281482e..35218185 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -109,7 +109,7 @@ struct dpc_ctx { #define RR_CNAME 5 #define RR_AAAA 28 -#define ABUF_SIZE 768 +#define ABUF_SIZE 4800 static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet, int plen) { From 383c7a4a5b74859a08ae3d10f1730b17bdd9bbac Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 6 Jul 2023 10:15:58 -0700 Subject: [PATCH 225/297] Update to emscripten 3.1.42 --- arch/emscripten/bits/alltypes.h | 4 +- arch/emscripten/bits/stat.h | 4 ++ arch/emscripten/bits/syscall.h | 3 - arch/emscripten/syscall_arch.h | 17 +++--- include/locale.h | 2 +- include/stddef.h | 2 +- include/stdio.h | 2 +- include/stdlib.h | 2 +- include/string.h | 2 +- include/time.h | 2 +- include/unistd.h | 6 +- include/wchar.h | 2 +- src/internal/atomic.h | 2 +- src/internal/dynlink.h | 14 +++-- src/internal/pthread_impl.h | 30 +++++++++- src/math/ceil.c | 2 + src/math/floor.c | 2 + src/math/rint.c | 2 + src/math/rintf.c | 2 + src/math/sqrt.c | 2 + src/math/sqrtf.c | 2 + src/misc/ioctl.c | 5 ++ src/sched/sched_yield.c | 4 +- src/signal/getitimer.c | 11 ++++ src/signal/setitimer.c | 88 +++++++++++++++++++++++++++++ src/temp/__randname.c | 5 ++ src/thread/pthread_cond_timedwait.c | 2 +- 27 files changed, 187 insertions(+), 34 deletions(-) diff --git a/arch/emscripten/bits/alltypes.h b/arch/emscripten/bits/alltypes.h index 1f7a6718..d56dedad 100644 --- a/arch/emscripten/bits/alltypes.h +++ b/arch/emscripten/bits/alltypes.h @@ -48,7 +48,7 @@ typedef int wchar_t; #endif #endif #if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t) -typedef unsigned wint_t; +typedef __WINT_TYPE__ wint_t; #define __DEFINED_wint_t #endif @@ -93,7 +93,7 @@ typedef struct { union { int __i[10]; volatile int __vi[10]; - unsigned __s[10]; + unsigned long __s[10]; } __u; #ifdef __EMSCRIPTEN__ // For canvas transfer implementation in Emscripten, use an extra control field diff --git a/arch/emscripten/bits/stat.h b/arch/emscripten/bits/stat.h index bb9314a5..bfa9a597 100644 --- a/arch/emscripten/bits/stat.h +++ b/arch/emscripten/bits/stat.h @@ -4,14 +4,18 @@ struct stat { dev_t st_dev; +#ifndef __EMSCRIPTEN__ int __st_dev_padding; long __st_ino_truncated; +#endif mode_t st_mode; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; dev_t st_rdev; +#ifndef __EMSCRIPTEN__ int __st_rdev_padding; +#endif off_t st_size; blksize_t st_blksize; blkcnt_t st_blocks; diff --git a/arch/emscripten/bits/syscall.h b/arch/emscripten/bits/syscall.h index f88e03e6..2522f9da 100644 --- a/arch/emscripten/bits/syscall.h +++ b/arch/emscripten/bits/syscall.h @@ -1,4 +1,3 @@ -#define SYS_link __syscall_link #define SYS_chdir __syscall_chdir #define SYS_chmod __syscall_chmod #define SYS_getpid __syscall_getpid @@ -20,8 +19,6 @@ #define SYS_fchmod __syscall_fchmod #define SYS_getpriority __syscall_getpriority #define SYS_setpriority __syscall_setpriority -#define SYS_setitimer __syscall_setitimer -#define SYS_getitimer __syscall_getitimer #define SYS_wait4 __syscall_wait4 #define SYS_setdomainname __syscall_setdomainname #define SYS_uname __syscall_uname diff --git a/arch/emscripten/syscall_arch.h b/arch/emscripten/syscall_arch.h index f398401a..b72e1f73 100644 --- a/arch/emscripten/syscall_arch.h +++ b/arch/emscripten/syscall_arch.h @@ -1,6 +1,6 @@ +#include #include #include -#include // Compile as if we can pass uint64 values directly to the // host. Binaryen will take care of splitting any i64 params @@ -12,7 +12,6 @@ extern "C" { #endif -int __syscall_link(intptr_t oldpath, intptr_t newpath); int __syscall_chdir(intptr_t path); int __syscall_mknod(intptr_t path, int mode, int dev); int __syscall_chmod(intptr_t path, int mode); @@ -38,8 +37,6 @@ int __syscall_fchmod(int fd, int mode); int __syscall_getpriority(int which, int who); int __syscall_setpriority(int which, int who, int prio); int __syscall_socketcall(int call, intptr_t args); -int __syscall_setitimer(int which, intptr_t new_value, intptr_t old_value); -int __syscall_getitimer(int which, intptr_t old_value); int __syscall_wait4(int pid, intptr_t wstatus, int options, int rusage); int __syscall_setdomainname(intptr_t name, size_t size); int __syscall_uname(intptr_t buf); @@ -58,9 +55,9 @@ int __syscall_mremap(intptr_t old_addr, size_t old_size, size_t new_size, int fl int __syscall_poll(intptr_t fds, int nfds, int timeout); int __syscall_getcwd(intptr_t buf, size_t size); int __syscall_ugetrlimit(int resource, intptr_t rlim); -intptr_t __syscall_mmap2(intptr_t addr, size_t len, int prot, int flags, int fd, size_t off); -int __syscall_truncate64(intptr_t path, uint64_t length); -int __syscall_ftruncate64(int fd, uint64_t length); +intptr_t __syscall_mmap2(intptr_t addr, size_t len, int prot, int flags, int fd, off_t offset); +int __syscall_truncate64(intptr_t path, off_t length); +int __syscall_ftruncate64(int fd, off_t length); int __syscall_stat64(intptr_t path, intptr_t buf); int __syscall_lstat64(intptr_t path, intptr_t buf); int __syscall_fstat64(int fd, intptr_t buf); @@ -84,7 +81,7 @@ int __syscall_getdents64(int fd, intptr_t dirp, size_t count); int __syscall_fcntl64(int fd, int cmd, ...); int __syscall_statfs64(intptr_t path, size_t size, intptr_t buf); int __syscall_fstatfs64(int fd, size_t size, intptr_t buf); -int __syscall_fadvise64(int fd, uint64_t offset, uint64_t length, int advice); +int __syscall_fadvise64(int fd, off_t offset, off_t length, int advice); int __syscall_openat(int dirfd, intptr_t path, int flags, ...); // mode is optional int __syscall_mkdirat(int dirfd, intptr_t path, int mode); int __syscall_mknodat(int dirfd, intptr_t path, int mode, int dev); @@ -99,7 +96,7 @@ int __syscall_fchmodat(int dirfd, intptr_t path, int mode, ...); int __syscall_faccessat(int dirfd, intptr_t path, int amode, int flags); int __syscall_pselect6(int nfds, intptr_t readfds, intptr_t writefds, intptr_t exceptfds, intptr_t timeout, intptr_t sigmaks); int __syscall_utimensat(int dirfd, intptr_t path, intptr_t times, int flags); -int __syscall_fallocate(int fd, int mode, uint64_t off, uint64_t len); +int __syscall_fallocate(int fd, int mode, off_t offset, off_t len); int __syscall_dup3(int fd, int suggestfd, int flags); int __syscall_pipe2(intptr_t fds, int flags); int __syscall_recvmmsg(int sockfd, intptr_t msgvec, size_t vlen, int flags, ...); @@ -107,7 +104,7 @@ int __syscall_prlimit64(int pid, int resource, intptr_t new_limit, intptr_t old_ int __syscall_sendmmsg(int sockfd, intptr_t msgvec, size_t vlen, int flags, ...); int __syscall_socket(int domain, int type, int protocol, int dummy1, int dummy2, int dummy3); int __syscall_socketpair(int domain, int type, int protocol, intptr_t fds, int dummy, int dummy2); -int __syscall_bind(int sockfd, intptr_t addr, size_t alen, int dummy, int dymmy2, int dummy3); +int __syscall_bind(int sockfd, intptr_t addr, size_t alen, int dummy, int dummy2, int dummy3); int __syscall_connect(int sockfd, intptr_t addr, size_t len, int dummy, int dummy2, int dummy3); int __syscall_listen(int sockfd, int backlock, int dummy1, int dummy2, int dummy3, int dummy4); int __syscall_accept4(int sockfd, intptr_t addr, intptr_t addrlen, int flags, int dummy1, int dummy2); diff --git a/include/locale.h b/include/locale.h index 11106fea..624547f6 100644 --- a/include/locale.h +++ b/include/locale.h @@ -7,7 +7,7 @@ extern "C" { #include -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && !defined(__EMSCRIPTEN__) #define NULL nullptr #elif defined(__cplusplus) #define NULL 0L diff --git a/include/stddef.h b/include/stddef.h index f25b8639..5fa18390 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -1,7 +1,7 @@ #ifndef _STDDEF_H #define _STDDEF_H -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && !defined(__EMSCRIPTEN__) #define NULL nullptr #elif defined(__cplusplus) #define NULL 0L diff --git a/include/stdio.h b/include/stdio.h index 06497e9d..37e745a5 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -29,7 +29,7 @@ extern "C" { #include -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && !defined(__EMSCRIPTEN__) #define NULL nullptr #elif defined(__cplusplus) #define NULL 0L diff --git a/include/stdlib.h b/include/stdlib.h index b507ca33..5e740526 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -7,7 +7,7 @@ extern "C" { #include -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && !defined(__EMSCRIPTEN__) #define NULL nullptr #elif defined(__cplusplus) #define NULL 0L diff --git a/include/string.h b/include/string.h index 43ad0942..d50eb941 100644 --- a/include/string.h +++ b/include/string.h @@ -7,7 +7,7 @@ extern "C" { #include -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && !defined(__EMSCRIPTEN__) #define NULL nullptr #elif defined(__cplusplus) #define NULL 0L diff --git a/include/time.h b/include/time.h index 3d948372..a91e1f76 100644 --- a/include/time.h +++ b/include/time.h @@ -7,7 +7,7 @@ extern "C" { #include -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && !defined(__EMSCRIPTEN__) #define NULL nullptr #elif defined(__cplusplus) #define NULL 0L diff --git a/include/unistd.h b/include/unistd.h index e0e80402..902f4281 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -27,7 +27,7 @@ extern "C" { #define SEEK_HOLE 4 #endif // EMSCRIPTEN -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && !defined(__EMSCRIPTEN__) #define NULL nullptr #elif defined(__cplusplus) #define NULL 0L @@ -258,7 +258,11 @@ pid_t gettid(void); #define _POSIX_VDISABLE 0 +#if defined(__EMSCRIPTEN__) && !defined(_REENTRANT) /* XXX Emscripten doesn't always support pthreads */ +#define _POSIX_THREADS -1 +#else #define _POSIX_THREADS _POSIX_VERSION +#endif #define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION #define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION #define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION diff --git a/include/wchar.h b/include/wchar.h index ed5d774d..18eee67c 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -38,7 +38,7 @@ extern "C" { #define WCHAR_MIN (-1-0x7fffffff+L'\0') #endif -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && !defined(__EMSCRIPTEN__) #define NULL nullptr #elif defined(__cplusplus) #define NULL 0L diff --git a/src/internal/atomic.h b/src/internal/atomic.h index 96c1552d..8f71c8cd 100644 --- a/src/internal/atomic.h +++ b/src/internal/atomic.h @@ -194,7 +194,7 @@ static inline void a_store(volatile int *p, int v) #ifndef a_barrier #define a_barrier a_barrier -static void a_barrier() +static inline void a_barrier() { volatile int tmp = 0; a_cas(&tmp, 0, 0); diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 23f852f4..a90658bb 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -13,12 +13,8 @@ #include struct dso { - struct dso *next, *prev; - - // For async mode - em_dlopen_callback onsuccess; - em_arg_callback_func onerror; - void* user_data; + // Pointer back to the dlevent in the event sequence which loaded this DSO. + struct dlevent* event; // Flags used to open the library. We need to cache these so that other // threads can mirror the open library state. @@ -33,6 +29,12 @@ struct dso { void* table_addr; size_t table_size; + // For DSO load events, where the DSO comes from a file on disc, this + // is a pointer the file data read in by the laoding thread and shared with + // others. + uint8_t* file_data; + size_t file_data_size; + // Flexible array; must be final element of struct char name[]; }; diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 8523938f..740fe212 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -10,8 +10,10 @@ #include "syscall.h" #include "atomic.h" #ifdef __EMSCRIPTEN__ -#include +#include "em_task_queue.h" +#include "thread_mailbox.h" #include "threading_internal.h" +#include #endif #include "futex.h" @@ -78,6 +80,30 @@ struct pthread { // The TLS base to use the main module TLS data. Secondary modules // still require dynamic allocation. void* tls_base; + // The lowest level of the proxying system. Other threads can enqueue + // messages on the mailbox and notify this thread to asynchronously + // process them once it returns to its event loop. When this thread is + // shut down, the mailbox is closed (see below) to prevent further + // messages from being enqueued and all the remaining queued messages + // are dequeued and their shutdown handlers are executed. This allows + // other threads waiting for their messages to be processed to be + // notified that their messages will not be processed after all. + em_task_queue* mailbox; + // To ensure that no other thread is concurrently enqueueing a message + // when this thread shuts down, maintain an atomic refcount. Enqueueing + // threads atomically increment the count from a nonzero number to + // acquire the mailbox and decrement the count when they finish. When + // this thread shuts down it will atomically decrement the count and + // wait until it reaches 0, at which point the mailbox is considered + // closed and no further messages will be enqueued. + _Atomic int mailbox_refcount; + // Whether the thread has executed a `waitAsync` on this pthread struct + // and can be notified of new mailbox messages via `Atomics.notify`. + // Otherwise the notification has to fall back to the postMessage path. + _Atomic int waiting_async; +#endif +#if _REENTRANT + _Atomic char sleeping; #endif }; @@ -225,7 +251,7 @@ extern hidden unsigned __default_guardsize; #ifdef __EMSCRIPTEN__ // Keep in sync with DEFAULT_PTHREAD_STACK_SIZE in settings.js -#define DEFAULT_STACK_SIZE (2*1024*1024) +#define DEFAULT_STACK_SIZE (64*1024) #else #define DEFAULT_STACK_SIZE 131072 #endif diff --git a/src/math/ceil.c b/src/math/ceil.c index cba7293b..93265657 100644 --- a/src/math/ceil.c +++ b/src/math/ceil.c @@ -1,11 +1,13 @@ #include "libm.h" +#ifndef __wasm__ #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON #endif static const double_t toint = 1/EPS; +#endif double ceil(double x) { diff --git a/src/math/floor.c b/src/math/floor.c index 0459dfba..179a9aca 100644 --- a/src/math/floor.c +++ b/src/math/floor.c @@ -1,11 +1,13 @@ #include "libm.h" +#ifndef __wasm__ #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON #endif static const double_t toint = 1/EPS; +#endif double floor(double x) { diff --git a/src/math/rint.c b/src/math/rint.c index 690f3e02..bd4c32f9 100644 --- a/src/math/rint.c +++ b/src/math/rint.c @@ -2,12 +2,14 @@ #include #include +#ifndef __wasm__ #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON #endif static const double_t toint = 1/EPS; +#endif double rint(double x) { diff --git a/src/math/rintf.c b/src/math/rintf.c index e393c88a..59401f2b 100644 --- a/src/math/rintf.c +++ b/src/math/rintf.c @@ -2,6 +2,7 @@ #include #include +#ifndef __wasm__ #if FLT_EVAL_METHOD==0 #define EPS FLT_EPSILON #elif FLT_EVAL_METHOD==1 @@ -10,6 +11,7 @@ #define EPS LDBL_EPSILON #endif static const float_t toint = 1/EPS; +#endif float rintf(float x) { diff --git a/src/math/sqrt.c b/src/math/sqrt.c index 2ce6e9ec..6854c983 100644 --- a/src/math/sqrt.c +++ b/src/math/sqrt.c @@ -5,6 +5,7 @@ #define FENV_SUPPORT 1 +#ifndef __wasm__ /* returns a*b*2^-32 - e, with error 0 <= e < 1. */ static inline uint32_t mul32(uint32_t a, uint32_t b) { @@ -20,6 +21,7 @@ static inline uint64_t mul64(uint64_t a, uint64_t b) uint64_t blo = b&0xffffffff; return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32); } +#endif double sqrt(double x) { diff --git a/src/math/sqrtf.c b/src/math/sqrtf.c index 6c90a2c2..fd747026 100644 --- a/src/math/sqrtf.c +++ b/src/math/sqrtf.c @@ -3,12 +3,14 @@ #include "libm.h" #include "sqrt_data.h" +#ifndef __wasm__ #define FENV_SUPPORT 1 static inline uint32_t mul32(uint32_t a, uint32_t b) { return (uint64_t)a*b >> 32; } +#endif /* see sqrt.c for more detailed comments. */ diff --git a/src/misc/ioctl.c b/src/misc/ioctl.c index 35804f02..0dd521ad 100644 --- a/src/misc/ioctl.c +++ b/src/misc/ioctl.c @@ -9,7 +9,12 @@ #include #include "syscall.h" +#ifdef __EMSCRIPTEN__ +// The upstream version below is UB in C2x and rejected by clang. +#define alignof(t) _Alignof(t) +#else #define alignof(t) offsetof(struct { char c; t x; }, x) +#endif #define W 1 #define R 2 diff --git a/src/sched/sched_yield.c b/src/sched/sched_yield.c index c9e6968f..7bd3846f 100644 --- a/src/sched/sched_yield.c +++ b/src/sched/sched_yield.c @@ -2,7 +2,9 @@ #include "syscall.h" #if __EMSCRIPTEN__ +#include #include +#include "threading_internal.h" #endif int sched_yield() @@ -11,7 +13,7 @@ int sched_yield() // SharedArrayBuffer and wasm threads do not support explicit yielding. // For now we at least call `emscripten_yield` which processes the event queue // (along with other essential tasks). - _emscripten_yield(); + _emscripten_yield(emscripten_get_now()); return 0; #else return syscall(SYS_sched_yield); diff --git a/src/signal/getitimer.c b/src/signal/getitimer.c index 36d1eb9d..251b2064 100644 --- a/src/signal/getitimer.c +++ b/src/signal/getitimer.c @@ -1,8 +1,18 @@ #include #include "syscall.h" +#ifdef __EMSCRIPTEN__ +#include +void __getitimer(int which, struct itimerval *old, double now); +#endif + int getitimer(int which, struct itimerval *old) { +#ifdef __EMSCRIPTEN__ + if (which > ITIMER_PROF) return EINVAL; + __getitimer(which, old, emscripten_get_now()); + return 0; +#else if (sizeof(time_t) > sizeof(long)) { long old32[4]; int r = __syscall(SYS_getitimer, which, old32); @@ -15,4 +25,5 @@ int getitimer(int which, struct itimerval *old) return __syscall_ret(r); } return syscall(SYS_getitimer, which, old); +#endif } diff --git a/src/signal/setitimer.c b/src/signal/setitimer.c index 0dfbeb4d..b15986a0 100644 --- a/src/signal/setitimer.c +++ b/src/signal/setitimer.c @@ -4,8 +4,95 @@ #define IS32BIT(x) !((x)+0x80000000ULL>>32) +#ifdef __EMSCRIPTEN__ +#include +#include +#include +#include + +#include "emscripten_internal.h" + +// Timeouts can either fire directly from the JS event loop (which calls +// `_emscripten_timeout`), or from `_emscripten_check_timers` (which is called +// from `_emscripten_yield`). In order to be able to check the timers here we +// cache the current timeout and interval for each the 3 types of timer +// (ITIMER_PROF/ITIMER_VIRTUAL/ITIMER_REAL). +static double current_timeout_ms[3]; +static double current_intervals_ms[3]; + +#define MAX(a,b) ((a)>(b)?(a):(b)) + +void __getitimer(int which, struct itimerval *old, double now) +{ + double remaining_ms = MAX(current_timeout_ms[which] - now, 0); + old->it_value.tv_sec = remaining_ms / 1000; + old->it_value.tv_usec = remaining_ms * 1000; + old->it_interval.tv_sec = current_intervals_ms[which] / 1000; + old->it_interval.tv_usec = current_intervals_ms[which] * 1000; +} + +void _emscripten_timeout(int which, double now) +{ + int signum = SIGALRM; + if (which == ITIMER_PROF) + signum = SIGPROF; + else if (which == ITIMER_VIRTUAL) + signum = SIGVTALRM; + double next_timeout = 0.0; + if (current_intervals_ms[which]) { + // If time went backwards, schedule the next timer as if it didn't. + now = __builtin_wasm_max_f64(now, current_timeout_ms[which]); + // The next alarm is due 'interval' ms after the previous one. + // If this alarm was delayed, that is sooner than 'interval' ms + // from now. The delay could even be so long that we missed the + // next alarm(s) entirely. Schedule the alarm for the next + // multiple of 'interval' ms from the original due time. + uint64_t intervals = + (uint64_t)(now - current_timeout_ms[which]) / + (uint64_t)current_intervals_ms[which] + + 1; + current_timeout_ms[which] += + intervals * current_intervals_ms[which]; + next_timeout = current_timeout_ms[which] - now; + } else { + current_timeout_ms[which] = 0; + } + _setitimer_js(which, next_timeout); + raise(signum); +} + +void _emscripten_check_timers(double now) +{ + for (int which = 0; which < 3; which++) { + if (current_timeout_ms[which]) { + // Only call out to JS to get the current time if it was not passed in + // *and* we have one or more timers set. + if (!now) + now = emscripten_get_now(); + if (now >= current_timeout_ms[which]) + _emscripten_timeout(which, now); + } + } +} +#endif + int setitimer(int which, const struct itimerval *restrict new, struct itimerval *restrict old) { +#ifdef __EMSCRIPTEN__ + if (which > ITIMER_PROF) return EINVAL; + double now = emscripten_get_now(); + if (old) { + __getitimer(which, old, now); + } + if (new->it_value.tv_sec || new->it_value.tv_usec) { + current_timeout_ms[which] = now + new->it_value.tv_sec * 1000 + new->it_value.tv_usec / 1000; + current_intervals_ms[which] = new->it_interval.tv_sec * 1000 + new->it_interval.tv_usec / 1000; + } else { + current_timeout_ms[which] = 0; + current_intervals_ms[which] = 0; + } + return _setitimer_js(which, new->it_value.tv_sec * 1000 + new->it_value.tv_usec / 1000); +#else if (sizeof(time_t) > sizeof(long)) { time_t is = new->it_interval.tv_sec, vs = new->it_value.tv_sec; long ius = new->it_interval.tv_usec, vus = new->it_value.tv_usec; @@ -23,4 +110,5 @@ int setitimer(int which, const struct itimerval *restrict new, struct itimerval return __syscall_ret(r); } return syscall(SYS_setitimer, which, new, old); +#endif } diff --git a/src/temp/__randname.c b/src/temp/__randname.c index 2bce37a0..f672ddb8 100644 --- a/src/temp/__randname.c +++ b/src/temp/__randname.c @@ -11,6 +11,11 @@ char *__randname(char *template) __clock_gettime(CLOCK_REALTIME, &ts); r = ts.tv_nsec*65537 ^ (uintptr_t)&ts / 16 + (uintptr_t)template; + + /* XXX EMSCRIPTEN: avoid repeating the same result when __clock_gettime does not change between calls. */ + static unsigned int counter = 0; + r += counter++; + for (i=0; i<6; i++, r>>=5) template[i] = 'A'+(r&15)+(r&16)*2; diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index 58212cdb..edd5a571 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -77,7 +77,7 @@ int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restri #ifdef __EMSCRIPTEN__ // TODO: Optimize this away in MINIMAL_RUNTIME. - if (pthread_self() == emscripten_main_browser_thread_id()) { + if (emscripten_is_main_browser_thread()) { emscripten_check_blocking_allowed(); } #endif From 83b858f83b658bd34eca5d8ad4d145f673ae7e5e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 17 Jul 2023 18:03:38 -0400 Subject: [PATCH 226/297] fix rejection of dns responses with pointers past 512 byte offset the __dns_parse code used by the stub resolver traditionally included code to reject label pointers to offsets past a 512 byte limit, despite never processing the label contents, only stepping over them. when commit 51d4669fb97782f6a66606da852b5afd49a08001 added support for tcp fallback, this limit was overlooked, and as a result, it was at least theoretically possible for some valid large answers to be rejected on account of these offsets. since the limit was never serving any useful purpose, just remove it. --- src/network/dns_parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/dns_parse.c b/src/network/dns_parse.c index 7f83e791..ea1ec126 100644 --- a/src/network/dns_parse.c +++ b/src/network/dns_parse.c @@ -15,13 +15,13 @@ int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, c if (qdcount+ancount > 64) return -1; while (qdcount--) { while (p-r < rlen && *p-1U < 127) p++; - if (p>r+rlen-6 || *p>193 || (*p==193 && p[1]>254)) + if (p>r+rlen-6) return -1; p += 5 + !!*p; } while (ancount--) { while (p-r < rlen && *p-1U < 127) p++; - if (p>r+rlen-12 || *p>193 || (*p==193 && p[1]>254)) + if (p>r+rlen-12) return -1; p += 1 + !!*p; len = p[8]*256 + p[9]; From 6d10102709df4bc966d2846c1c45cd667e5048e5 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 18 Aug 2023 23:16:00 +0200 Subject: [PATCH 227/297] math: fix ld80 acoshl(x) for x < 0 acosh(x) is nan for x < 1, but x < 0 cases were not handled specially and acoshl gave wrong result for some -0x1p32 < x < -2 values, e.g.: acoshl(-0x1p20) returned -inf, acoshl(-0x1.4p20) returned -0x1.db365758403aa9acp+0L, fixed by checking the sign bit and handling it specially. reported by Paul Zimmermann. --- src/math/acoshl.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/math/acoshl.c b/src/math/acoshl.c index 8d4b43f6..943cec17 100644 --- a/src/math/acoshl.c +++ b/src/math/acoshl.c @@ -10,14 +10,18 @@ long double acoshl(long double x) long double acoshl(long double x) { union ldshape u = {x}; - int e = u.i.se & 0x7fff; + int e = u.i.se; if (e < 0x3fff + 1) - /* |x| < 2, invalid if x < 1 or nan */ + /* 0 <= x < 2, invalid if x < 1 */ return log1pl(x-1 + sqrtl((x-1)*(x-1)+2*(x-1))); if (e < 0x3fff + 32) - /* |x| < 0x1p32 */ + /* 2 <= x < 0x1p32 */ return logl(2*x - 1/(x+sqrtl(x*x-1))); + if (e & 0x8000) + /* x < 0 or x = -0, invalid */ + return (x - x) / (x - x); + /* 0x1p32 <= x or nan */ return logl(x) + 0.693147180559945309417232121458176568L; } #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 From 39e43f0881b12d602ddcb8a9e9295456354b765b Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Fri, 18 Aug 2023 23:17:38 +0200 Subject: [PATCH 228/297] math: fix ld80 powl(x,huge) and powl(LDBL_MAX,small) powl used >= LDBL_MAX as infinity check, but LDBL_MAX is finite, so this can cause wrong results e.g. powl(LDBL_MAX, 0.5) returned inf or powl(2, LDBL_MAX) returned inf without raising overflow. huge y values (close to LDBL_MAX) could cause intermediate results to overflow (computing y * log2(x) with more than long double precision) and e.g. powl(0.5, 0x1p16380L) or powl(10, 0x1p16380L) returned nan. this is fixed by handling huge y early since that always overflows or underflows. reported by Paul Zimmermann against expl10 (which uses powl). --- src/math/powl.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/math/powl.c b/src/math/powl.c index 5b6da07b..6f64ea71 100644 --- a/src/math/powl.c +++ b/src/math/powl.c @@ -212,25 +212,33 @@ long double powl(long double x, long double y) } if (x == 1.0) return 1.0; /* 1**y = 1, even if y is nan */ - if (x == -1.0 && !isfinite(y)) - return 1.0; /* -1**inf = 1 */ if (y == 0.0) return 1.0; /* x**0 = 1, even if x is nan */ if (y == 1.0) return x; - if (y >= LDBL_MAX) { - if (x > 1.0 || x < -1.0) - return INFINITY; - if (x != 0.0) - return 0.0; - } - if (y <= -LDBL_MAX) { - if (x > 1.0 || x < -1.0) + /* if y*log2(x) < log2(LDBL_TRUE_MIN)-1 then x^y uflows to 0 + if y*log2(x) > -log2(LDBL_TRUE_MIN)+1 > LDBL_MAX_EXP then x^y oflows + if |x|!=1 then |log2(x)| > |log(x)| > LDBL_EPSILON/2 so + x^y oflows/uflows if |y|*LDBL_EPSILON/2 > -log2(LDBL_TRUE_MIN)+1 */ + if (fabsl(y) > 2*(-LDBL_MIN_EXP+LDBL_MANT_DIG+1)/LDBL_EPSILON) { + /* y is not an odd int */ + if (x == -1.0) + return 1.0; + if (y == INFINITY) { + if (x > 1.0 || x < -1.0) + return INFINITY; return 0.0; - if (x != 0.0 || y == -INFINITY) + } + if (y == -INFINITY) { + if (x > 1.0 || x < -1.0) + return 0.0; return INFINITY; + } + if ((x > 1.0 || x < -1.0) == (y > 0)) + return huge * huge; + return twom10000 * twom10000; } - if (x >= LDBL_MAX) { + if (x == INFINITY) { if (y > 0.0) return INFINITY; return 0.0; @@ -253,7 +261,7 @@ long double powl(long double x, long double y) yoddint = 1; } - if (x <= -LDBL_MAX) { + if (x == -INFINITY) { if (y > 0.0) { if (yoddint) return -INFINITY; From 7291c6c66a8d033bb487e6d8c8b003c8a7b6a550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Thu, 17 Aug 2023 22:05:14 +0200 Subject: [PATCH 229/297] statvfs: allocate spare for f_type This is the only missing part in struct statvfs. The LSB calls [f]statfs() deprecated, and its weird types are definitely off-putting. However, its use is required to get f_type. Instead, allocate one of the six spares to f_type, copied directly from struct statfs. This then becomes a small extension to the standard interface on Linux, instead of two different interfaces, one of which is quite odd due to being an ABI type, and there no longer is any reason to use statfs(). The underlying kernel type is a mess, but all architectures agree on u32 (or more) for the ABI, and all filesystem magicks are 32-bit integers. Since commit 6567db65f495cf7c11f5c1e60a3e54543d5a69bc (prior to 1.0.0), the spare slots have been zero-filled, so on all versions that may be reasonably be encountered in the wild, applications can rely on a nonzero f_type as indication that the new field has been filled in. --- include/sys/statvfs.h | 3 ++- src/stat/statvfs.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h index 57a6b806..71d9d1f9 100644 --- a/include/sys/statvfs.h +++ b/include/sys/statvfs.h @@ -23,7 +23,8 @@ struct statvfs { unsigned long f_fsid; #endif unsigned long f_flag, f_namemax; - int __reserved[6]; + unsigned int f_type; + int __reserved[5]; }; int statvfs (const char *__restrict, struct statvfs *__restrict); diff --git a/src/stat/statvfs.c b/src/stat/statvfs.c index bfbb5fee..bc12da8b 100644 --- a/src/stat/statvfs.c +++ b/src/stat/statvfs.c @@ -39,6 +39,7 @@ static void fixup(struct statvfs *out, const struct statfs *in) out->f_fsid = in->f_fsid.__val[0]; out->f_flag = in->f_flags; out->f_namemax = in->f_namelen; + out->f_type = in->f_type; } int statvfs(const char *restrict path, struct statvfs *restrict buf) From 79bdacff83a6bd5b70ff5ae5eb8b6de82c2f7c30 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 24 Aug 2023 12:54:51 -0400 Subject: [PATCH 230/297] glob: fix wrong return code when aborting before any matches when the result count was zero, glob was ignoring a possible GLOB_ABORTED error code and returning GLOB_NOMATCH. whether this happened could be nondeterministic and dependent on the order of dirent enumeration, in cases where multiple matches were present and only some produced errors. caught by Tor's test_util_glob. --- src/regex/glob.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/regex/glob.c b/src/regex/glob.c index a4906446..87bae084 100644 --- a/src/regex/glob.c +++ b/src/regex/glob.c @@ -265,7 +265,7 @@ int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, i if (append(&tail, pat, strlen(pat), 0)) return GLOB_NOSPACE; cnt++; - } else + } else if (!error) return GLOB_NOMATCH; } From 6be76895f6863100a311d474a42abdbb6466189d Mon Sep 17 00:00:00 2001 From: Violet Purcell Date: Sat, 4 Nov 2023 12:09:20 -0400 Subject: [PATCH 231/297] elf.h: add typedefs for Elf64_Relr and Elf32_Relr These were overlooked when DT_RELR was added in commit d32dadd60efb9d3b255351a3b532f8e4c3dd0db1, potentially breaking software that treats presence of the DT_RELR macro as implying they exist. --- include/elf.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/elf.h b/include/elf.h index 23f2c4bc..72d17c3a 100644 --- a/include/elf.h +++ b/include/elf.h @@ -558,6 +558,11 @@ typedef struct { +typedef Elf32_Word Elf32_Relr; +typedef Elf64_Xword Elf64_Relr; + + + #define ELF32_R_SYM(val) ((val) >> 8) #define ELF32_R_TYPE(val) ((val) & 0xff) #define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) From 725e17ed6dff4d0cd22487bb64470881e86a92e7 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 6 Nov 2023 08:26:19 -0500 Subject: [PATCH 232/297] remove non-prototype declaration of basename from string.h commit 37bb3cce4598c19288628e675eaf1cda6e96958f suppressed the declaration for C++, where it is wrongly interpreted as declaring the function as taking no arguments. with C23 removing non-prototype declarations, that problem is now also relevant to C. the non-prototype declaration for basename originates with commit 06aec8d7152dfb8360cb7ed9b3d7215ca0b0b500, where it was designed to avoid conflicts with programs which declare basename with the GNU signature taking const char *. that change was probably misguided, as it represents not only misaligned expectations with the caller, but also undefined behavior (calling a function that's been declared with the wrong type). we could opt to fix the declaration, but since glibc, with the gratuitously incompatible GNU-basename function, seems to be the only implementation that declares it in string.h, it seems better to just remove the declaration. this provides some warning if applications are being built expecting the GNU behavior but not getting it. if we declared it here, it would only produce a warning if the caller also declares it themselves (rare) or if the caller attempts to pass a const-qualified pointer. --- include/string.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/string.h b/include/string.h index db73d2a9..83e2b946 100644 --- a/include/string.h +++ b/include/string.h @@ -95,9 +95,6 @@ char *strchrnul(const char *, int); char *strcasestr(const char *, const char *); void *memrchr(const void *, int, size_t); void *mempcpy(void *, const void *, size_t); -#ifndef __cplusplus -char *basename(); -#endif #endif #ifdef __cplusplus From 5baf2d92d3ed82960c419cb6093fbcdd028dde11 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 6 Nov 2023 12:59:34 -0500 Subject: [PATCH 233/297] ldso: use __ehdr_start if available to locate its own ELF headers previously, the relative load address was used as the address at which to find the ELF headers. this only works if two conditions are met: ldso is linked to start at a virtual address of 0, and the linker is cooperative and includes the main ELF headers in a loadable segment. while in practice these are always met, modern linkers provide a __ehdr_start symbol pointing to the ELF headers, and can in principle use the reference to this symbol as an indication that they need to be mapped in a segment. this also should make it possible to link for a different starting virtual address, if that's ever desirable. --- ldso/dynlink.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index ceca3c98..bb02cd3c 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -157,6 +157,8 @@ static struct fdpic_dummy_loadmap app_dummy_loadmap; struct debug *_dl_debug_addr = &debug; +extern weak hidden char __ehdr_start[]; + extern hidden int __malloc_replaced; hidden void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0; @@ -1725,7 +1727,7 @@ hidden void __dls2(unsigned char *base, size_t *sp) } else { ldso.base = base; } - Ehdr *ehdr = (void *)ldso.base; + Ehdr *ehdr = __ehdr_start ? (void *)__ehdr_start : (void *)ldso.base; ldso.name = ldso.shortname = "libc.so"; ldso.phnum = ehdr->e_phnum; ldso.phdr = laddr(&ldso, ehdr->e_phoff); From 7f3a2925369c00abc33457400e33632e6dacb8ae Mon Sep 17 00:00:00 2001 From: Markus Wichmann Date: Tue, 31 Oct 2023 17:03:44 +0100 Subject: [PATCH 234/297] synccall: add separate exit_sem to fix thread release logic bug The code intends for the sem_post() in line 97 (now 98) to only unblock target threads waiting on line 29. But after the first thread is released, the next sem_post() might also unblock a thread waiting on line 36. That would cause the thread to return to the execution of user code before all threads are done, leading to user code being executed in a mixed-credentials environment. What's more, if this happens more than once, then the mass release on line 110 (now line 111) will cause multiple threads to execute the callback at the same time, and the callbacks are currently not written to cope with that situation. Adding another semaphore allows the caller to say explicitly which threads it wants to release. --- src/thread/synccall.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/thread/synccall.c b/src/thread/synccall.c index a6b177c0..38597254 100644 --- a/src/thread/synccall.c +++ b/src/thread/synccall.c @@ -11,7 +11,7 @@ weak_alias(dummy_0, __tl_unlock); static int target_tid; static void (*callback)(void *), *context; -static sem_t target_sem, caller_sem; +static sem_t target_sem, caller_sem, exit_sem; static void dummy(void *p) { @@ -33,7 +33,7 @@ static void handler(int sig) /* Inform caller we've complered the callback and wait * for the caller to release us to return. */ sem_post(&caller_sem); - sem_wait(&target_sem); + sem_wait(&exit_sem); /* Inform caller we are returning and state is destroyable. */ sem_post(&caller_sem); @@ -62,6 +62,7 @@ void __synccall(void (*func)(void *), void *ctx) sem_init(&target_sem, 0, 0); sem_init(&caller_sem, 0, 0); + sem_init(&exit_sem, 0, 0); if (!libc.threads_minus_1 || __syscall(SYS_gettid) != self->tid) goto single_threaded; @@ -107,12 +108,13 @@ void __synccall(void (*func)(void *), void *ctx) /* Only release the caught threads once all threads, including the * caller, have returned from the callback function. */ for (i=0; i Date: Thu, 2 Nov 2023 17:39:33 +0100 Subject: [PATCH 235/297] ensure valid setxid return value in an unexpected error case If __synccall() fails to capture all threads because tkill fails for some reason other than EAGAIN, then the callback given will never be executed, so nothing will ever overwrite the initial value. So that is the value that will be returned from the function. The previous setting of 1 is not a valid value for setuid() et al. to return. I chose -EAGAIN since I don't know the reason the synccall failed ahead of time, but EAGAIN is a specified error code for a possibly temporary failure in setuid(). --- src/unistd/setxid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unistd/setxid.c b/src/unistd/setxid.c index 487c1a16..a629ed4b 100644 --- a/src/unistd/setxid.c +++ b/src/unistd/setxid.c @@ -30,5 +30,5 @@ int __setxid(int nr, int id, int eid, int sid) * trigger the safety kill above. */ struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid, .ret = 1 }; __synccall(do_setxid, &c); - return __syscall_ret(c.ret); + return __syscall_ret(c.ret > 0 ? -EAGAIN : c.ret); } From c5459df18879dad8f5388480d588edbcbd1b7eb2 Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Wed, 1 Nov 2023 19:37:08 -0400 Subject: [PATCH 236/297] timer_create: volatile static -> static volatile C11 6.11.5p1: > The placement of a storage-class specifier other than at the > beginning of the declaration specifiers in a declaration is an > obsolescent feature. gcc also warns about this. --- src/time/timer_create.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time/timer_create.c b/src/time/timer_create.c index cd32c945..9216b3ab 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -61,7 +61,7 @@ static void *start(void *arg) int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict res) { - volatile static int init = 0; + static volatile int init = 0; pthread_t td; pthread_attr_t attr; int r; From 2d84486a08c57d00b647586b7cbe2dcec2728e81 Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Wed, 1 Nov 2023 19:37:44 -0400 Subject: [PATCH 237/297] __year_to_secs: fix dangling pointer The lifetime of the compound literal ends after the "if" statement's implicit block. gcc also warns about this. --- src/time/__year_to_secs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/time/__year_to_secs.c b/src/time/__year_to_secs.c index 2824ec6d..b42f5a6d 100644 --- a/src/time/__year_to_secs.c +++ b/src/time/__year_to_secs.c @@ -10,9 +10,9 @@ long long __year_to_secs(long long year, int *is_leap) return 31536000*(y-70) + 86400*leaps; } - int cycles, centuries, leaps, rem; + int cycles, centuries, leaps, rem, dummy; - if (!is_leap) is_leap = &(int){0}; + if (!is_leap) is_leap = &dummy; cycles = (year-100) / 400; rem = (year-100) % 400; if (rem < 0) { From 2265a4c9b0825306794eeb0812c783692313d972 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Sat, 7 Oct 2023 21:02:18 +0300 Subject: [PATCH 238/297] pass AT_NO_AUTOMOUNT when emulating fstatat via statx AT_NO_AUTOMOUNT is implied for stat/lstat/fstatat syscalls since Linux 3.1 (commit b6c8069d3577481390b3f24a8434ad72a3235594). However, this is not the case for statx syscall, which defaults to automounting, so this flag must be passed explicitly when statx is used to implement stat-like functions. This change affects only arches which use 32-bit seconds in struct kstat, as well as out-of-tree/future ports to arches which lack SYS_fstatat. --- src/stat/fstatat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index 04506375..9eed063b 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -36,6 +36,7 @@ static int fstatat_statx(int fd, const char *restrict path, struct stat *restric { struct statx stx; + flag |= AT_NO_AUTOMOUNT; int ret = __syscall(SYS_statx, fd, path, flag, 0x7ff, &stx); if (ret) return ret; From 8c086e767468cc11c6d58d6a92d8511c2bd12024 Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Wed, 4 Oct 2023 21:29:43 +0200 Subject: [PATCH 239/297] remove arbitrary limit from dns result parsing The name resolution would abort when getting more than 63 records per request, due to what seems to be a left-over from the original code. This check was non-breaking but spurious prior to TCP fallback support, since any 512-byte packet with more than 63 records was necessarily malformed. But now, it wrongly rejects valid results. Reported by Daniel Stefanik in Alpine Linux aports issue 15320. --- src/network/dns_parse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/network/dns_parse.c b/src/network/dns_parse.c index ea1ec126..09813112 100644 --- a/src/network/dns_parse.c +++ b/src/network/dns_parse.c @@ -12,7 +12,6 @@ int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, c p = r+12; qdcount = r[4]*256 + r[5]; ancount = r[6]*256 + r[7]; - if (qdcount+ancount > 64) return -1; while (qdcount--) { while (p-r < rlen && *p-1U < 127) p++; if (p>r+rlen-6) From 7b6a6516e133a4154022de4d15b3d5bc800ab3ad Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 6 Nov 2023 13:59:06 -0500 Subject: [PATCH 240/297] byte-based printf family: emit a nul byte for %lc with argument zero this is contrary to the spec as written, which requires %lc to behave as if it were %ls on a 2-wchar_t buffer containing the argument and zero. however, apparently no other implementations conform to the spec as written, and in response to Austin Group issue #1647, WG14 chose to align with existing practice and have %lc produce output for this case. --- src/stdio/vfprintf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 33019ff1..497c5e19 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -588,6 +588,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, } p = MAX(p, z-a + !arg.i); break; + narrow_c: case 'c': *(a=z-(p=1))=arg.i; fl &= ~ZERO_PAD; @@ -602,6 +603,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, fl &= ~ZERO_PAD; break; case 'C': + if (!arg.i) goto narrow_c; wc[0] = arg.i; wc[1] = 0; arg.p = wc; From 039d3c34f2e3578a8b7ada42f89213b844aa7a4e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 6 Nov 2023 21:48:02 -0500 Subject: [PATCH 241/297] ldso: convert TLSDESC_BACKWARDS from "#ifdef" to "if" logic this style is preferred because it allows the code to be compile-checked even on archs where it is not used. --- arch/arm/reloc.h | 2 +- ldso/dynlink.c | 10 +++++----- src/internal/dynlink.h | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/arm/reloc.h b/arch/arm/reloc.h index d091d2ad..d98eb8af 100644 --- a/arch/arm/reloc.h +++ b/arch/arm/reloc.h @@ -26,7 +26,7 @@ #define REL_TPOFF R_ARM_TLS_TPOFF32 #define REL_TLSDESC R_ARM_TLS_DESC -#define TLSDESC_BACKWARDS +#define TLSDESC_BACKWARDS 1 #define CRTJMP(pc,sp) __asm__ __volatile__( \ "mov sp,%1 ; bx %0" : : "r"(pc), "r"(sp) : "memory" ) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index bb02cd3c..6ba51b0a 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -542,13 +542,13 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + addend; #endif } -#ifdef TLSDESC_BACKWARDS /* Some archs (32-bit ARM at least) invert the order of * the descriptor members. Fix them up here. */ - size_t tmp = reloc_addr[0]; - reloc_addr[0] = reloc_addr[1]; - reloc_addr[1] = tmp; -#endif + if (TLSDESC_BACKWARDS) { + size_t tmp = reloc_addr[0]; + reloc_addr[0] = reloc_addr[1]; + reloc_addr[1] = tmp; + } break; default: error("Error relocating %s: unsupported relocation type %d", diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 06f41d09..40c743e2 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -73,6 +73,10 @@ struct fdpic_dummy_loadmap { #define DL_NOMMU_SUPPORT 0 #endif +#ifndef TLSDESC_BACKWARDS +#define TLSDESC_BACKWARDS 0 +#endif + #if !DL_FDPIC #define IS_RELATIVE(x,s) ( \ (R_TYPE(x) == REL_RELATIVE) || \ From e17b9d74740df413fae2502c0010591c7998c40d Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 6 Nov 2023 21:50:37 -0500 Subject: [PATCH 242/297] ldso: fix TLSDESC addend processing on archs with backwards descriptors presently this only affects 32-bit arm. despite correctly reversing the function pointer and argument fields based on the TLSDESC_BACKWARDS macro, we did not read the addend from the swapped-order argument field, so nonzero addends were lost, producing wrong runtime addresses for TLS objects needing an addend. based on report and patch by Rui Ueyama. --- ldso/dynlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 6ba51b0a..324aa859 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -517,7 +517,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri break; #endif case REL_TLSDESC: - if (stride<3) addend = reloc_addr[1]; + if (stride<3) addend = reloc_addr[!TLSDESC_BACKWARDS]; if (def.dso->tls_id > static_tls_cnt) { struct td_index *new = malloc(sizeof *new); if (!new) { From ee1d39bc1573c1ae49ee6b658938b56bbef95a6c Mon Sep 17 00:00:00 2001 From: q66 Date: Thu, 9 Nov 2023 20:48:44 +0100 Subject: [PATCH 243/297] mntent: unescape octal sequences As entries in mtab are delimited by spaces, whitespace characters are escaped as octal sequences. When reading them out, we have to unescape these sequences to get the proper string. --- src/misc/mntent.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/misc/mntent.c b/src/misc/mntent.c index d404fbe3..e9393883 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -20,6 +20,42 @@ int endmntent(FILE *f) return 1; } +static char *unescape_ent(char *beg) +{ + char *dest = beg; + const char *src = beg; + while (*src) { + const char *val; + unsigned char cval = 0; + if (*src != '\\') { + *dest++ = *src++; + continue; + } + if (src[1] == '\\') { + ++src; + *dest++ = *src++; + continue; + } + val = src + 1; + for (int i = 0; i < 3; ++i) { + if (*val >= '0' && *val <= '7') { + cval <<= 3; + cval += *val++ - '0'; + } else { + break; + } + } + if (cval) { + *dest++ = cval; + src = val; + } else { + *dest++ = *src++; + } + } + *dest = 0; + return beg; +} + struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen) { int n[8], use_internal = (linebuf == SENTINEL); @@ -55,10 +91,10 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle linebuf[n[5]] = 0; linebuf[n[7]] = 0; - mnt->mnt_fsname = linebuf+n[0]; - mnt->mnt_dir = linebuf+n[2]; - mnt->mnt_type = linebuf+n[4]; - mnt->mnt_opts = linebuf+n[6]; + mnt->mnt_fsname = unescape_ent(linebuf+n[0]); + mnt->mnt_dir = unescape_ent(linebuf+n[2]); + mnt->mnt_type = unescape_ent(linebuf+n[4]); + mnt->mnt_opts = unescape_ent(linebuf+n[6]); return mnt; } From f314e133929b6379eccc632bef32eaebb66a7335 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 16 Nov 2023 12:55:21 -0500 Subject: [PATCH 244/297] mntent: fields are delimited only by tabs or spaces, not general whitespace this matters because the kernel-provided mtab only escapes tabs, spaces, newlines, and backslashes. it leaves carriage returns, form feeds, and vertical tabs literal. --- src/misc/mntent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc/mntent.c b/src/misc/mntent.c index e9393883..78bf0cd0 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -81,7 +81,7 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle len = strlen(linebuf); if (len > INT_MAX) continue; for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len; - sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", + sscanf(linebuf, " %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %d %d", n, n+1, n+2, n+3, n+4, n+5, n+6, n+7, &mnt->mnt_freq, &mnt->mnt_passno); } while (linebuf[n[0]] == '#' || n[1]==len); From f47a5d400b8ffa26cfc5b345dbff52fec94ac7f3 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 21 Nov 2023 16:33:15 -0500 Subject: [PATCH 245/297] strftime: don't attempt to parse field width without seeing a digit strtoul will consume leading whitespace or sign characters, which are not valid in this context, thereby accepting invalid field specifiers. so, avoid calling it unless there is a number to parse as the width. --- src/time/strftime.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/time/strftime.c b/src/time/strftime.c index cc53d536..ef590903 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include "locale_impl.h" @@ -233,7 +234,7 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st pad = 0; if (*f == '-' || *f == '_' || *f == '0') pad = *f++; if ((plus = (*f == '+'))) f++; - width = strtoul(f, &p, 10); + width = isdigit(*f) ? strtoul(f, &p, 10) : 0; if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') { if (!width && p!=f) width = 1; } else { From 11fb383275d20f5f94c00425bd888a02ecbd218e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 17 Jan 2024 18:11:58 -0500 Subject: [PATCH 246/297] remove INT_MAX limit on the n argument to snprintf/swprintf this was a POSIX requirement that was always in conflict with ISO C, which specified a well-defined behavior for snprintf and swprintf so long as the actual number of bytes/characters produced did not exceed INT_MAX. I originally raised this conflict for snprintf with the Austin Group as tracker issue 761, which was never resolved. it was later reported again as issue 1219, and as a result the conflicting requirement has been removed. the corresponding issue with swprintf does not seem to have been addressed, but as the same reasoning applies to it, I am removing the limitation on n for swprintf as well. --- src/stdio/vsnprintf.c | 5 ----- src/stdio/vswprintf.c | 3 --- 2 files changed, 8 deletions(-) diff --git a/src/stdio/vsnprintf.c b/src/stdio/vsnprintf.c index b3510a63..409b9c85 100644 --- a/src/stdio/vsnprintf.c +++ b/src/stdio/vsnprintf.c @@ -45,11 +45,6 @@ int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) .cookie = &c, }; - if (n > INT_MAX) { - errno = EOVERFLOW; - return -1; - } - *c.s = 0; return vfprintf(&f, fmt, ap); } diff --git a/src/stdio/vswprintf.c b/src/stdio/vswprintf.c index fc223cf2..5e9a4dad 100644 --- a/src/stdio/vswprintf.c +++ b/src/stdio/vswprintf.c @@ -51,9 +51,6 @@ int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, va_lis if (!n) { return -1; - } else if (n > INT_MAX) { - errno = EOVERFLOW; - return -1; } r = vfwprintf(&f, fmt, ap); sw_write(&f, 0, 0); From 07af01816d65b49a901cd784db69a030a6213e03 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 21 Jan 2024 17:18:36 -0500 Subject: [PATCH 247/297] move ppoll from src/linux to src/select reflecting future standardization the ppoll function has been accepted as a future part of the standard as the outcome of Austin Group tracker issue 1263. move the source file to reflect this. --- src/{linux => select}/ppoll.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{linux => select}/ppoll.c (100%) diff --git a/src/linux/ppoll.c b/src/select/ppoll.c similarity index 100% rename from src/linux/ppoll.c rename to src/select/ppoll.c From f247462b0831cbf163e976ee9a909748c674b88b Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 21 Jan 2024 17:22:50 -0500 Subject: [PATCH 248/297] expose ppoll in default feature profile the ppoll function has been accepted as a future part of the standard as the outcome of Austin Group tracker issue 1263. at some point it should be exposed unconditionally, but for now, expose it in the default feature profile. --- include/poll.h | 4 ++-- src/select/ppoll.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/poll.h b/include/poll.h index 472e4b84..bf9cb99a 100644 --- a/include/poll.h +++ b/include/poll.h @@ -36,7 +36,7 @@ struct pollfd { int poll (struct pollfd *, nfds_t, int); -#ifdef _GNU_SOURCE +#ifdef _BSD_SOURCE #define __NEED_time_t #define __NEED_struct_timespec #define __NEED_sigset_t @@ -45,7 +45,7 @@ int ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *); #endif #if _REDIR_TIME64 -#ifdef _GNU_SOURCE +#ifdef _BSD_SOURCE __REDIR(ppoll, __ppoll_time64); #endif #endif diff --git a/src/select/ppoll.c b/src/select/ppoll.c index e614600a..9a0bf929 100644 --- a/src/select/ppoll.c +++ b/src/select/ppoll.c @@ -1,4 +1,4 @@ -#define _GNU_SOURCE +#define _BSD_SOURCE #include #include #include From 81cced6ebeb4419a78a8892ec7d7e28f5582d24a Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 25 Jan 2024 12:02:34 -0500 Subject: [PATCH 249/297] add preadv2 and pwritev2 syscall wrappers, flag value macros --- include/sys/uio.h | 7 +++++++ src/linux/preadv2.c | 17 +++++++++++++++++ src/linux/pwritev2.c | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 src/linux/preadv2.c create mode 100644 src/linux/pwritev2.c diff --git a/include/sys/uio.h b/include/sys/uio.h index 90e5939e..8b5e3de7 100644 --- a/include/sys/uio.h +++ b/include/sys/uio.h @@ -39,6 +39,13 @@ ssize_t pwritev (int, const struct iovec *, int, off_t); #ifdef _GNU_SOURCE ssize_t process_vm_writev(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long); ssize_t process_vm_readv(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long); +ssize_t preadv2 (int, const struct iovec *, int, off_t, int); +ssize_t pwritev2 (int, const struct iovec *, int, off_t, int); +#define RWF_HIPRI 0x00000001 +#define RWF_DSYNC 0x00000002 +#define RWF_SYNC 0x00000004 +#define RWF_NOWAIT 0x00000008 +#define RWF_APPEND 0x00000010 #endif #ifdef __cplusplus diff --git a/src/linux/preadv2.c b/src/linux/preadv2.c new file mode 100644 index 00000000..5e7ab70f --- /dev/null +++ b/src/linux/preadv2.c @@ -0,0 +1,17 @@ +#define _GNU_SOURCE +#include +#include +#include "syscall.h" + +ssize_t preadv2(int fd, const struct iovec *iov, int count, off_t ofs, int flags) +{ +#ifdef SYS_preadv + if (!flags) { + if (ofs==-1) return readv(fd, iov, count); + return syscall_cp(SYS_preadv, fd, iov, count, + (long)(ofs), (long)(ofs>>32)); + } +#endif + return syscall_cp(SYS_preadv2, fd, iov, count, + (long)(ofs), (long)(ofs>>32), flags); +} diff --git a/src/linux/pwritev2.c b/src/linux/pwritev2.c new file mode 100644 index 00000000..ece90d7c --- /dev/null +++ b/src/linux/pwritev2.c @@ -0,0 +1,17 @@ +#define _GNU_SOURCE +#include +#include +#include "syscall.h" + +ssize_t pwritev2(int fd, const struct iovec *iov, int count, off_t ofs, int flags) +{ +#ifdef SYS_pwritev + if (!flags) { + if (ofs==-1) return writev(fd, iov, count); + return syscall_cp(SYS_pwritev, fd, iov, count, + (long)(ofs), (long)(ofs>>32)); + } +#endif + return syscall_cp(SYS_pwritev2, fd, iov, count, + (long)(ofs), (long)(ofs>>32), flags); +} From 25c4123629aabbadba6c4190b4f1b5e213ab9e5b Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 26 Jan 2024 15:55:37 -0800 Subject: [PATCH 250/297] elf.h: update RISC-V relocation types Note: Some relocation types were only used by binutils and accidentally exposed to previous versions of psABI. One of the values has been reused by GOT32_PCREL. --- include/elf.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/include/elf.h b/include/elf.h index 72d17c3a..ad3519ad 100644 --- a/include/elf.h +++ b/include/elf.h @@ -3254,6 +3254,7 @@ enum #define R_RISCV_TLS_DTPREL64 9 #define R_RISCV_TLS_TPREL32 10 #define R_RISCV_TLS_TPREL64 11 +#define R_RISCV_TLSDESC 12 #define R_RISCV_BRANCH 16 #define R_RISCV_JAL 17 @@ -3280,16 +3281,11 @@ enum #define R_RISCV_SUB16 38 #define R_RISCV_SUB32 39 #define R_RISCV_SUB64 40 -#define R_RISCV_GNU_VTINHERIT 41 -#define R_RISCV_GNU_VTENTRY 42 +#define R_RISCV_GOT32_PCREL 41 #define R_RISCV_ALIGN 43 #define R_RISCV_RVC_BRANCH 44 #define R_RISCV_RVC_JUMP 45 #define R_RISCV_RVC_LUI 46 -#define R_RISCV_GPREL_I 47 -#define R_RISCV_GPREL_S 48 -#define R_RISCV_TPREL_I 49 -#define R_RISCV_TPREL_S 50 #define R_RISCV_RELAX 51 #define R_RISCV_SUB6 52 #define R_RISCV_SET6 53 @@ -3297,6 +3293,14 @@ enum #define R_RISCV_SET16 55 #define R_RISCV_SET32 56 #define R_RISCV_32_PCREL 57 +#define R_RISCV_IRELATIVE 58 +#define R_RISCV_PLT32 59 +#define R_RISCV_SET_ULEB128 60 +#define R_RISCV_SUB_ULEB128 61 +#define R_RISCV_TLSDESC_HI20 62 +#define R_RISCV_TLSDESC_LOAD_LO12 63 +#define R_RISCV_TLSDESC_ADD_LO12 64 +#define R_RISCV_TLSDESC_CALL 65 #ifdef __cplusplus } From 15aa7abd344745675f2df3eb5ea09fa36cfecfa4 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 2 Feb 2024 15:25:32 -0800 Subject: [PATCH 251/297] elf.h: add NT_RISCV_CSR and NT_RISCV_VECTOR constants See Linux commit 9300f00439743c4a34d735e1a27118eb68a1504e ("RISC-V: Add ptrace support for vectors"). --- include/elf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/elf.h b/include/elf.h index ad3519ad..d1ad978e 100644 --- a/include/elf.h +++ b/include/elf.h @@ -703,6 +703,8 @@ typedef struct { #define NT_MIPS_DSP 0x800 #define NT_MIPS_FP_MODE 0x801 #define NT_MIPS_MSA 0x802 +#define NT_RISCV_CSR 0x900 +#define NT_RISCV_VECTOR 0x901 #define NT_VERSION 1 From bd3138b74a06dd764508f399d1b58cb9d6c35c1f Mon Sep 17 00:00:00 2001 From: gns Date: Thu, 25 Jan 2024 23:59:52 +0800 Subject: [PATCH 252/297] riscv: correct symbol version of __vdso_flush_icache Previously, __riscv_flush_icache would not work correctly as __vdso_flush_icache had a wrong symbol version. Fix this by correcting symbol version. Fixes: 0a48860c27a8 ("add riscv64 architecture support") --- src/linux/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/cache.c b/src/linux/cache.c index 0eb051c2..45024309 100644 --- a/src/linux/cache.c +++ b/src/linux/cache.c @@ -21,7 +21,7 @@ weak_alias(__cachectl, cachectl); #ifdef SYS_riscv_flush_icache #define VDSO_FLUSH_ICACHE_SYM "__vdso_flush_icache" -#define VDSO_FLUSH_ICACHE_VER "LINUX_4.5" +#define VDSO_FLUSH_ICACHE_VER "LINUX_4.15" static void *volatile vdso_func; From 0e330722c353e71ec9d1518d77278c09f39a1c55 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 29 Jan 2024 09:05:32 -0500 Subject: [PATCH 253/297] sqrtl: fix invalid use of a non-constant-expression as static initializer having these constants be static was unnecessary, so just remove the static. this error should have been caught by compilers, but recent versions of both gcc and clang accept these as "other forms of constant expressions" which the C standard allows. --- src/math/sqrtl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/math/sqrtl.c b/src/math/sqrtl.c index 1b9f19c7..a231b3f2 100644 --- a/src/math/sqrtl.c +++ b/src/math/sqrtl.c @@ -205,7 +205,7 @@ long double sqrtl(long double x) top = (top + 0x3fff) >> 1; /* r ~ 1/sqrt(m) */ - static const uint64_t three = 0xc0000000; + const uint64_t three = 0xc0000000; uint64_t r, s, d, u, i; i = (ix.hi >> 42) % 128; r = (uint32_t)__rsqrt_tab[i] << 16; @@ -227,7 +227,7 @@ long double sqrtl(long double x) r = mul64(u, r) << 1; /* |r sqrt(m) - 1| < 0x1.c001p-59, switch to 128bit */ - static const u128 threel = {.hi=three<<32, .lo=0}; + const u128 threel = {.hi=three<<32, .lo=0}; u128 rl, sl, dl, ul; rl.hi = r; rl.lo = 0; From 2e1bb87af24e3cb053bb3d5f4bb6e2e72f79c44a Mon Sep 17 00:00:00 2001 From: Tim Cuthbertson Date: Sat, 3 Feb 2024 19:55:23 -0500 Subject: [PATCH 254/297] install.sh: avoid creating symlinks with restricted permissions Linux and most systems do not have symlink permissions, but some systems, including MacOS, do, and creation of the symlink with umask set to 0777 makes the symlink inaccessible on such systems. clear umask when making a symlink so that the behavior is uniform. --- tools/install.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/install.sh b/tools/install.sh index d913b60b..855a8ca2 100755 --- a/tools/install.sh +++ b/tools/install.sh @@ -48,7 +48,9 @@ trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP umask 077 if test "$symlink" ; then +umask 000 ln -s "$1" "$tmp" +umask 077 else cat < "$1" > "$tmp" chmod "$mode" "$tmp" From 407aea628af8c81d9e3f5a068568f2217db71bba Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 3 Feb 2024 19:59:26 -0500 Subject: [PATCH 255/297] riscv: add TLSDESC support --- arch/riscv64/reloc.h | 1 + src/ldso/riscv64/tlsdesc.s | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/ldso/riscv64/tlsdesc.s diff --git a/arch/riscv64/reloc.h b/arch/riscv64/reloc.h index 1ca13811..7c7c0611 100644 --- a/arch/riscv64/reloc.h +++ b/arch/riscv64/reloc.h @@ -17,6 +17,7 @@ #define REL_DTPMOD R_RISCV_TLS_DTPMOD64 #define REL_DTPOFF R_RISCV_TLS_DTPREL64 #define REL_TPOFF R_RISCV_TLS_TPREL64 +#define REL_TLSDESC R_RISCV_TLSDESC #define CRTJMP(pc,sp) __asm__ __volatile__( \ "mv sp, %1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" ) diff --git a/src/ldso/riscv64/tlsdesc.s b/src/ldso/riscv64/tlsdesc.s new file mode 100644 index 00000000..bef8b322 --- /dev/null +++ b/src/ldso/riscv64/tlsdesc.s @@ -0,0 +1,32 @@ +.text +.global __tlsdesc_static +.hidden __tlsdesc_static +.type __tlsdesc_static,%function +__tlsdesc_static: + ld a0,8(a0) + jr t0 + +.global __tlsdesc_dynamic +.hidden __tlsdesc_dynamic +.type __tlsdesc_dynamic,%function +__tlsdesc_dynamic: + add sp,sp,-16 + sd t1,(sp) + sd t2,8(sp) + + ld t2,-8(tp) # t2=dtv + + ld a0,8(a0) # a0=&{modidx,off} + ld t1,8(a0) # t1=off + ld a0,(a0) # a0=modidx + sll a0,a0,3 # a0=8*modidx + + add a0,a0,t2 # a0=dtv+8*modidx + ld a0,(a0) # a0=dtv[modidx] + add a0,a0,t1 # a0=dtv[modidx]+off + sub a0,a0,tp # a0=dtv[modidx]+off-tp + + ld t1,(sp) + ld t2,8(sp) + add sp,sp,16 + jr t0 From 8b7048680731707d135ea231f81eb3eaf52378ee Mon Sep 17 00:00:00 2001 From: Jules Maselbas Date: Thu, 25 Jan 2024 15:14:40 +0100 Subject: [PATCH 256/297] stdc-predef.h: prevent redefining __STDC_UTF_{16,32}__ macros Undefine any previous __STDC_UTF_{16,32}__ macros before defining them to prenvent any warnings of redefining macros. This happens as a result of some compiler versions defining the macros themselves. --- include/stdc-predef.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/stdc-predef.h b/include/stdc-predef.h index af1a2799..5ccd884d 100644 --- a/include/stdc-predef.h +++ b/include/stdc-predef.h @@ -7,7 +7,10 @@ #define __STDC_IEC_559__ 1 #endif +#undef __STDC_UTF_16__ #define __STDC_UTF_16__ 1 + +#undef __STDC_UTF_32__ #define __STDC_UTF_32__ 1 #endif From 39838619bb8b65a8897abcfda8c17ad6de0115d8 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 7 Feb 2024 16:08:11 -0500 Subject: [PATCH 257/297] syslog: use C locale for timestamp generation depending on contents of the LC_TIME locale, log messages could be malformatted (especially if the ABMON strings contain non-alphabetic characters) or the subsequent code could invoke undefined behavior, via passing a timebuf[] with unspecified contents to snprintf, if the translated ABMON string did not fit in the 16-byte timebuf. this does not appear to be a security-relevant bug, as locale loading functionality is intentionally not available to set*id programs -- the MUSL_LOCPATH environment variable is ignored when libc.secure is true, and custom locales are not loadable without it. --- src/misc/syslog.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/misc/syslog.c b/src/misc/syslog.c index 7dc0c1be..710202f9 100644 --- a/src/misc/syslog.c +++ b/src/misc/syslog.c @@ -11,6 +11,7 @@ #include #include "lock.h" #include "fork_impl.h" +#include "locale_impl.h" static volatile int lock[1]; static char log_ident[32]; @@ -99,7 +100,7 @@ static void _vsyslog(int priority, const char *message, va_list ap) now = time(NULL); gmtime_r(&now, &tm); - strftime(timebuf, sizeof timebuf, "%b %e %T", &tm); + strftime_l(timebuf, sizeof timebuf, "%b %e %T", &tm, C_LOCALE); pid = (log_opt & LOG_PID) ? getpid() : 0; l = snprintf(buf, sizeof buf, "<%d>%s %n%s%s%.0d%s: ", From cf91e9b3937dc354b702c8ac1b6135bd818154ba Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 8 Feb 2024 14:44:00 -0500 Subject: [PATCH 258/297] fix erroneous feature test macro check for ppoll commit f247462b0831cbf163e976ee9a909748c674b88b incorrectly hid ppoll in the presence of _GNU_SOURCE due to an oversight that defining _BSD_SOURCE does not implicitly define _GNU_SOURCE. at present, headers still have to explicitly check for each feature profile level; this may be changed at some point in the future via features.h, but has not been changed yet. --- include/poll.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/poll.h b/include/poll.h index bf9cb99a..272dc34a 100644 --- a/include/poll.h +++ b/include/poll.h @@ -36,7 +36,7 @@ struct pollfd { int poll (struct pollfd *, nfds_t, int); -#ifdef _BSD_SOURCE +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #define __NEED_time_t #define __NEED_struct_timespec #define __NEED_sigset_t @@ -45,7 +45,7 @@ int ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *); #endif #if _REDIR_TIME64 -#ifdef _BSD_SOURCE +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) __REDIR(ppoll, __ppoll_time64); #endif #endif From 4a16ddf53e7c634169d0a649782f8a724611f263 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 12 Feb 2024 17:35:48 -0500 Subject: [PATCH 259/297] strftime: fix breakage in last change (uninitialized pointer access) commit f47a5d400b8ffa26cfc5b345dbff52fec94ac7f3 overlooked that strtoul was responsible for setting p to a const-laundered copy of the format string pointer f, even in the case where there was no number to parse. by making the call conditional on isdigit, that copy was lost. the logic here is a mess and should be cleaned up, but for now, this seems to be the least invasive change that undoes the breakage. --- src/time/strftime.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/time/strftime.c b/src/time/strftime.c index ef590903..c40246db 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -234,7 +234,12 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st pad = 0; if (*f == '-' || *f == '_' || *f == '0') pad = *f++; if ((plus = (*f == '+'))) f++; - width = isdigit(*f) ? strtoul(f, &p, 10) : 0; + if (isdigit(*f)) { + width = strtoul(f, &p, 10); + } else { + width = 0; + p = (void *)f; + } if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') { if (!width && p!=f) width = 1; } else { From 522bd54edaa2fa404fd428f8ad0bcb0f0bec5639 Mon Sep 17 00:00:00 2001 From: Hongliang Wang Date: Tue, 26 Sep 2023 09:12:01 +0800 Subject: [PATCH 260/297] add loongarch64 port Author: Xiaojuan Zhai Author: Meidan Li Author: Guoqi Chen Author: Xiaolin Zhao Author: Fan peng Author: Jiantao Shan Author: Xuhui Qiang Author: Jingyun Hua Author: Liu xue Author: Hongliang Wang --- arch/loongarch64/atomic_arch.h | 53 ++++ arch/loongarch64/bits/alltypes.h.in | 18 ++ arch/loongarch64/bits/fenv.h | 20 ++ arch/loongarch64/bits/float.h | 16 ++ arch/loongarch64/bits/posix.h | 2 + arch/loongarch64/bits/ptrace.h | 4 + arch/loongarch64/bits/reg.h | 2 + arch/loongarch64/bits/setjmp.h | 1 + arch/loongarch64/bits/signal.h | 90 ++++++ arch/loongarch64/bits/stat.h | 18 ++ arch/loongarch64/bits/stdint.h | 20 ++ arch/loongarch64/bits/syscall.h.in | 303 +++++++++++++++++++++ arch/loongarch64/bits/user.h | 5 + arch/loongarch64/crt_arch.h | 13 + arch/loongarch64/pthread_arch.h | 11 + arch/loongarch64/reloc.h | 29 ++ arch/loongarch64/syscall_arch.h | 137 ++++++++++ configure | 14 + include/elf.h | 104 ++++++- src/fenv/loongarch64/fenv.S | 78 ++++++ src/ldso/loongarch64/dlsym.s | 7 + src/setjmp/loongarch64/longjmp.S | 32 +++ src/setjmp/loongarch64/setjmp.S | 34 +++ src/signal/loongarch64/restore.s | 10 + src/signal/loongarch64/sigsetjmp.s | 25 ++ src/thread/loongarch64/__set_thread_area.s | 7 + src/thread/loongarch64/__unmapself.s | 7 + src/thread/loongarch64/clone.s | 28 ++ src/thread/loongarch64/syscall_cp.s | 29 ++ 29 files changed, 1116 insertions(+), 1 deletion(-) create mode 100644 arch/loongarch64/atomic_arch.h create mode 100644 arch/loongarch64/bits/alltypes.h.in create mode 100644 arch/loongarch64/bits/fenv.h create mode 100644 arch/loongarch64/bits/float.h create mode 100644 arch/loongarch64/bits/posix.h create mode 100644 arch/loongarch64/bits/ptrace.h create mode 100644 arch/loongarch64/bits/reg.h create mode 100644 arch/loongarch64/bits/setjmp.h create mode 100644 arch/loongarch64/bits/signal.h create mode 100644 arch/loongarch64/bits/stat.h create mode 100644 arch/loongarch64/bits/stdint.h create mode 100644 arch/loongarch64/bits/syscall.h.in create mode 100644 arch/loongarch64/bits/user.h create mode 100644 arch/loongarch64/crt_arch.h create mode 100644 arch/loongarch64/pthread_arch.h create mode 100644 arch/loongarch64/reloc.h create mode 100644 arch/loongarch64/syscall_arch.h create mode 100644 src/fenv/loongarch64/fenv.S create mode 100644 src/ldso/loongarch64/dlsym.s create mode 100644 src/setjmp/loongarch64/longjmp.S create mode 100644 src/setjmp/loongarch64/setjmp.S create mode 100644 src/signal/loongarch64/restore.s create mode 100644 src/signal/loongarch64/sigsetjmp.s create mode 100644 src/thread/loongarch64/__set_thread_area.s create mode 100644 src/thread/loongarch64/__unmapself.s create mode 100644 src/thread/loongarch64/clone.s create mode 100644 src/thread/loongarch64/syscall_cp.s diff --git a/arch/loongarch64/atomic_arch.h b/arch/loongarch64/atomic_arch.h new file mode 100644 index 00000000..2225d027 --- /dev/null +++ b/arch/loongarch64/atomic_arch.h @@ -0,0 +1,53 @@ +#define a_ll a_ll +static inline int a_ll(volatile int *p) +{ + int v; + __asm__ __volatile__ ( + "ll.w %0, %1" + : "=r"(v) + : "ZC"(*p)); + return v; +} + +#define a_sc a_sc +static inline int a_sc(volatile int *p, int v) +{ + int r; + __asm__ __volatile__ ( + "sc.w %0, %1" + : "=r"(r), "=ZC"(*p) + : "0"(v) : "memory"); + return r; +} + +#define a_ll_p a_ll_p +static inline void *a_ll_p(volatile void *p) +{ + void *v; + __asm__ __volatile__ ( + "ll.d %0, %1" + : "=r"(v) + : "ZC"(*(void *volatile *)p)); + return v; +} + +#define a_sc_p a_sc_p +static inline int a_sc_p(volatile void *p, void *v) +{ + long r; + __asm__ __volatile__ ( + "sc.d %0, %1" + : "=r"(r), "=ZC"(*(void *volatile *)p) + : "0"(v) + : "memory"); + return r; +} + +#define a_barrier a_barrier +static inline void a_barrier() +{ + __asm__ __volatile__ ("dbar 0" : : : "memory"); +} + +#define a_pre_llsc a_barrier +#define a_post_llsc a_barrier diff --git a/arch/loongarch64/bits/alltypes.h.in b/arch/loongarch64/bits/alltypes.h.in new file mode 100644 index 00000000..d1807aca --- /dev/null +++ b/arch/loongarch64/bits/alltypes.h.in @@ -0,0 +1,18 @@ +#define _Addr long +#define _Int64 long +#define _Reg long + +#define __BYTE_ORDER 1234 +#define __LONG_MAX 0x7fffffffffffffffL + +#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; + +TYPEDEF unsigned nlink_t; +TYPEDEF int blksize_t; diff --git a/arch/loongarch64/bits/fenv.h b/arch/loongarch64/bits/fenv.h new file mode 100644 index 00000000..264cafb5 --- /dev/null +++ b/arch/loongarch64/bits/fenv.h @@ -0,0 +1,20 @@ +#define FE_INEXACT 0x010000 +#define FE_UNDERFLOW 0x020000 +#define FE_OVERFLOW 0x040000 +#define FE_DIVBYZERO 0x080000 +#define FE_INVALID 0x100000 + +#define FE_ALL_EXCEPT 0x1F0000 + +#define FE_TONEAREST 0x000 +#define FE_TOWARDZERO 0x100 +#define FE_UPWARD 0x200 +#define FE_DOWNWARD 0x300 + +typedef unsigned fexcept_t; + +typedef struct { + unsigned __cw; +} fenv_t; + +#define FE_DFL_ENV ((const fenv_t *) -1) diff --git a/arch/loongarch64/bits/float.h b/arch/loongarch64/bits/float.h new file mode 100644 index 00000000..719c7908 --- /dev/null +++ b/arch/loongarch64/bits/float.h @@ -0,0 +1,16 @@ +#define FLT_EVAL_METHOD 0 + +#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/loongarch64/bits/posix.h b/arch/loongarch64/bits/posix.h new file mode 100644 index 00000000..8068ce98 --- /dev/null +++ b/arch/loongarch64/bits/posix.h @@ -0,0 +1,2 @@ +#define _POSIX_V6_LP64_OFF64 1 +#define _POSIX_V7_LP64_OFF64 1 diff --git a/arch/loongarch64/bits/ptrace.h b/arch/loongarch64/bits/ptrace.h new file mode 100644 index 00000000..dce2fa51 --- /dev/null +++ b/arch/loongarch64/bits/ptrace.h @@ -0,0 +1,4 @@ +#define PTRACE_GET_THREAD_AREA 25 +#define PTRACE_SET_THREAD_AREA 26 +#define PTRACE_GET_WATCH_REGS 0xd0 +#define PTRACE_SET_WATCH_REGS 0xd1 diff --git a/arch/loongarch64/bits/reg.h b/arch/loongarch64/bits/reg.h new file mode 100644 index 00000000..2633f39d --- /dev/null +++ b/arch/loongarch64/bits/reg.h @@ -0,0 +1,2 @@ +#undef __WORDSIZE +#define __WORDSIZE 64 diff --git a/arch/loongarch64/bits/setjmp.h b/arch/loongarch64/bits/setjmp.h new file mode 100644 index 00000000..3b15e87b --- /dev/null +++ b/arch/loongarch64/bits/setjmp.h @@ -0,0 +1 @@ +typedef unsigned long __jmp_buf[23]; diff --git a/arch/loongarch64/bits/signal.h b/arch/loongarch64/bits/signal.h new file mode 100644 index 00000000..8e0e605c --- /dev/null +++ b/arch/loongarch64/bits/signal.h @@ -0,0 +1,90 @@ +#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 4096 +#define SIGSTKSZ 16384 +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +typedef unsigned long greg_t, gregset_t[32]; + +struct sigcontext { + unsigned long sc_pc; + unsigned long sc_regs[32]; + unsigned sc_flags; + unsigned long sc_extcontext[] __attribute__((__aligned__(16))); +}; +#endif + +typedef struct { + unsigned long __pc; + unsigned long __gregs[32]; + unsigned __flags; + unsigned long __extcontext[] __attribute__((__aligned__(16))); +} mcontext_t; + +struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +}; + +typedef struct __ucontext +{ + unsigned long uc_flags; + struct __ucontext *uc_link; + stack_t uc_stack; + sigset_t uc_sigmask; + long __uc_pad; + mcontext_t uc_mcontext; +} ucontext_t; + +#define __uc_flags uc_flags + +#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 + +#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 SIGIO +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED SIGSYS + +#define _NSIG 65 diff --git a/arch/loongarch64/bits/stat.h b/arch/loongarch64/bits/stat.h new file mode 100644 index 00000000..b7f4221b --- /dev/null +++ b/arch/loongarch64/bits/stat.h @@ -0,0 +1,18 @@ +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; + unsigned long __pad; + off_t st_size; + blksize_t st_blksize; + int __pad2; + blkcnt_t st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned __unused[2]; +}; diff --git a/arch/loongarch64/bits/stdint.h b/arch/loongarch64/bits/stdint.h new file mode 100644 index 00000000..1bb147f2 --- /dev/null +++ b/arch/loongarch64/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 INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX +#define SIZE_MAX UINT64_MAX diff --git a/arch/loongarch64/bits/syscall.h.in b/arch/loongarch64/bits/syscall.h.in new file mode 100644 index 00000000..0980e533 --- /dev/null +++ b/arch/loongarch64/bits/syscall.h.in @@ -0,0 +1,303 @@ +#define __NR_io_setup 0 +#define __NR_io_destroy 1 +#define __NR_io_submit 2 +#define __NR_io_cancel 3 +#define __NR_io_getevents 4 +#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 __NR3264_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 __NR3264_statfs 43 +#define __NR3264_fstatfs 44 +#define __NR3264_truncate 45 +#define __NR3264_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 __NR3264_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 __NR3264_sendfile 71 +#define __NR_pselect6 72 +#define __NR_ppoll 73 +#define __NR_signalfd4 74 +#define __NR_vmsplice 75 +#define __NR_splice 76 +#define __NR_tee 77 +#define __NR_readlinkat 78 +#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_timerfd_settime 86 +#define __NR_timerfd_gettime 87 +#define __NR_utimensat 88 +#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_futex 98 +#define __NR_set_robust_list 99 +#define __NR_get_robust_list 100 +#define __NR_nanosleep 101 +#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_gettime 108 +#define __NR_timer_getoverrun 109 +#define __NR_timer_settime 110 +#define __NR_timer_delete 111 +#define __NR_clock_settime 112 +#define __NR_clock_gettime 113 +#define __NR_clock_getres 114 +#define __NR_clock_nanosleep 115 +#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_sched_rr_get_interval 127 +#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_sigtimedwait 137 +#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_getrlimit 163 +#define __NR_setrlimit 164 +#define __NR_getrusage 165 +#define __NR_umask 166 +#define __NR_prctl 167 +#define __NR_getcpu 168 +#define __NR_gettimeofday 169 +#define __NR_settimeofday 170 +#define __NR_adjtimex 171 +#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_timedsend 182 +#define __NR_mq_timedreceive 183 +#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_semtimedop 192 +#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 __NR3264_mmap 222 +#define __NR3264_fadvise64 223 +#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 +#define __NR_rt_tgsigqueueinfo 240 +#define __NR_perf_event_open 241 +#define __NR_accept4 242 +#define __NR_recvmmsg 243 +#define __NR_arch_specific_syscall 244 +#define __NR_wait4 260 +#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_clock_adjtime 266 +#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_io_pgetevents 292 +#define __NR_rseq 293 +#define __NR_kexec_file_load 294 +#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_fcntl __NR3264_fcntl +#define __NR_statfs __NR3264_statfs +#define __NR_fstatfs __NR3264_fstatfs +#define __NR_truncate __NR3264_truncate +#define __NR_ftruncate __NR3264_ftruncate +#define __NR_lseek __NR3264_lseek +#define __NR_sendfile __NR3264_sendfile +#define __NR_mmap __NR3264_mmap +#define __NR_fadvise64 __NR3264_fadvise64 diff --git a/arch/loongarch64/bits/user.h b/arch/loongarch64/bits/user.h new file mode 100644 index 00000000..5a71d132 --- /dev/null +++ b/arch/loongarch64/bits/user.h @@ -0,0 +1,5 @@ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG]; +typedef double elf_fpreg_t, elf_fpregset_t[ELF_NFPREG]; diff --git a/arch/loongarch64/crt_arch.h b/arch/loongarch64/crt_arch.h new file mode 100644 index 00000000..e0760d9e --- /dev/null +++ b/arch/loongarch64/crt_arch.h @@ -0,0 +1,13 @@ +__asm__( +".text \n" +".global " START "\n" +".type " START ", @function\n" +START ":\n" +" move $fp, $zero\n" +" move $a0, $sp\n" +".weak _DYNAMIC\n" +".hidden _DYNAMIC\n" +" la.local $a1, _DYNAMIC\n" +" bstrins.d $sp, $zero, 3, 0\n" +" b " START "_c\n" +); diff --git a/arch/loongarch64/pthread_arch.h b/arch/loongarch64/pthread_arch.h new file mode 100644 index 00000000..365f6ca8 --- /dev/null +++ b/arch/loongarch64/pthread_arch.h @@ -0,0 +1,11 @@ +static inline uintptr_t __get_tp() +{ + register uintptr_t tp __asm__("tp"); + __asm__ ("" : "=r" (tp) ); + return tp; +} + +#define TLS_ABOVE_TP +#define GAP_ABOVE_TP 0 +#define DTP_OFFSET 0 +#define MC_PC __pc diff --git a/arch/loongarch64/reloc.h b/arch/loongarch64/reloc.h new file mode 100644 index 00000000..61eaca9e --- /dev/null +++ b/arch/loongarch64/reloc.h @@ -0,0 +1,29 @@ +#ifdef __loongarch_soft_float +#define FP_SUFFIX "-sf" +#elif defined __loongarch_single_float +#define FP_SUFFIX "-sp" +#else +#define FP_SUFFIX "" +#endif + +#define LDSO_ARCH "loongarch64" FP_SUFFIX + +#define TPOFF_K 0 + +#define REL_PLT R_LARCH_JUMP_SLOT +#define REL_COPY R_LARCH_COPY +#define REL_DTPMOD R_LARCH_TLS_DTPMOD64 +#define REL_DTPOFF R_LARCH_TLS_DTPREL64 +#define REL_TPOFF R_LARCH_TLS_TPREL64 +#define REL_RELATIVE R_LARCH_RELATIVE +#define REL_SYMBOLIC R_LARCH_64 + +#define CRTJMP(pc,sp) __asm__ __volatile__( \ + "move $sp, %1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" ) + +#define GETFUNCSYM(fp, sym, got) __asm__ ( \ + ".hidden " #sym "\n" \ + ".align 8 \n" \ + " la.local $t1, "#sym" \n" \ + " move %0, $t1 \n" \ + : "=r"(*(fp)) : : "memory" ) diff --git a/arch/loongarch64/syscall_arch.h b/arch/loongarch64/syscall_arch.h new file mode 100644 index 00000000..4d5e1885 --- /dev/null +++ b/arch/loongarch64/syscall_arch.h @@ -0,0 +1,137 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define SYSCALL_CLOBBERLIST \ + "$t0", "$t1", "$t2", "$t3", \ + "$t4", "$t5", "$t6", "$t7", "$t8", "memory" + +static inline long __syscall0(long n) +{ + register long a7 __asm__("$a7") = n; + register long a0 __asm__("$a0"); + + __asm__ __volatile__ ( + "syscall 0" + : "=r"(a0) + : "r"(a7) + : SYSCALL_CLOBBERLIST); + return a0; +} + +static inline long __syscall1(long n, long a) +{ + register long a7 __asm__("$a7") = n; + register long a0 __asm__("$a0") = a; + + __asm__ __volatile__ ( + "syscall 0" + : "+r"(a0) + : "r"(a7) + : SYSCALL_CLOBBERLIST); + return a0; +} + +static inline long __syscall2(long n, long a, long b) +{ + register long a7 __asm__("$a7") = n; + register long a0 __asm__("$a0") = a; + register long a1 __asm__("$a1") = b; + + __asm__ __volatile__ ( + "syscall 0" + : "+r"(a0) + : "r"(a7), "r"(a1) + : SYSCALL_CLOBBERLIST); + return a0; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long a7 __asm__("$a7") = n; + register long a0 __asm__("$a0") = a; + register long a1 __asm__("$a1") = b; + register long a2 __asm__("$a2") = c; + + __asm__ __volatile__ ( + "syscall 0" + : "+r"(a0) + : "r"(a7), "r"(a1), "r"(a2) + : SYSCALL_CLOBBERLIST); + return a0; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long a7 __asm__("$a7") = n; + register long a0 __asm__("$a0") = a; + register long a1 __asm__("$a1") = b; + register long a2 __asm__("$a2") = c; + register long a3 __asm__("$a3") = d; + + __asm__ __volatile__ ( + "syscall 0" + : "+r"(a0) + : "r"(a7), "r"(a1), "r"(a2), "r"(a3) + : SYSCALL_CLOBBERLIST); + return a0; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long a7 __asm__("$a7") = n; + register long a0 __asm__("$a0") = a; + register long a1 __asm__("$a1") = b; + register long a2 __asm__("$a2") = c; + register long a3 __asm__("$a3") = d; + register long a4 __asm__("$a4") = e; + + __asm__ __volatile__ ( + "syscall 0" + : "+r"(a0) + : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4) + : SYSCALL_CLOBBERLIST); + return a0; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long a7 __asm__("$a7") = n; + register long a0 __asm__("$a0") = a; + register long a1 __asm__("$a1") = b; + register long a2 __asm__("$a2") = c; + register long a3 __asm__("$a3") = d; + register long a4 __asm__("$a4") = e; + register long a5 __asm__("$a5") = f; + + __asm__ __volatile__ ( + "syscall 0" + : "+r"(a0) + : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5) + : SYSCALL_CLOBBERLIST); + return a0; +} + +static inline long __syscall7(long n, long a, long b, long c, long d, long e, long f, long g) +{ + register long a7 __asm__("$a7") = n; + register long a0 __asm__("$a0") = a; + register long a1 __asm__("$a1") = b; + register long a2 __asm__("$a2") = c; + register long a3 __asm__("$a3") = d; + register long a4 __asm__("$a4") = e; + register long a5 __asm__("$a5") = f; + register long a6 __asm__("$a6") = g; + + __asm__ __volatile__ ( + "syscall 0" + : "+r"(a0) + : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6) + : SYSCALL_CLOBBERLIST); + return a0; +} + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__vdso_clock_gettime" +#define VDSO_CGT_VER "LINUX_5.10" + +#define IPC_64 0 diff --git a/configure b/configure index 0b966ede..940b3eaf 100755 --- a/configure +++ b/configure @@ -328,6 +328,7 @@ i?86*) ARCH=i386 ;; x86_64-x32*|x32*|x86_64*x32) ARCH=x32 ;; x86_64-nt64*) ARCH=nt64 ;; x86_64*) ARCH=x86_64 ;; +loongarch64*) ARCH=loongarch64 ;; m68k*) ARCH=m68k ;; mips64*|mipsisa64*) ARCH=mips64 ;; mips*) ARCH=mips ;; @@ -671,6 +672,19 @@ if test "$ARCH" = "aarch64" ; then trycppif __AARCH64EB__ "$t" && SUBARCH=${SUBARCH}_be fi +if test "$ARCH" = "loongarch64" ; then +trycppif __loongarch_soft_float "$t" && SUBARCH=${SUBARCH}-sf +trycppif __loongarch_single_float "$t" && SUBARCH=${SUBARCH}-sp +printf "checking whether assembler support FCSRs... " +echo "__asm__(\"movfcsr2gr \$t0,\$fcsr0\");" > "$tmpc" +if $CC -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then +printf "yes\n" +else +printf "no\n" +CFLAGS_AUTO="$CFLAGS_AUTO -DBROKEN_LOONGARCH_FCSR_ASM" +fi +fi + if test "$ARCH" = "m68k" ; then if trycppif "__HAVE_68881__" ; then : ; elif trycppif "__mcffpu__" ; then SUBARCH="-fp64" diff --git a/include/elf.h b/include/elf.h index d1ad978e..3d5e13e4 100644 --- a/include/elf.h +++ b/include/elf.h @@ -315,7 +315,8 @@ typedef struct { #define EM_RISCV 243 #define EM_BPF 247 #define EM_CSKY 252 -#define EM_NUM 253 +#define EM_LOONGARCH 258 +#define EM_NUM 259 #define EM_ALPHA 0x9026 @@ -706,6 +707,11 @@ typedef struct { #define NT_RISCV_CSR 0x900 #define NT_RISCV_VECTOR 0x901 #define NT_VERSION 1 +#define NT_LOONGARCH_CPUCFG 0xa00 +#define NT_LOONGARCH_CSR 0xa01 +#define NT_LOONGARCH_LSX 0xa02 +#define NT_LOONGARCH_LASX 0xa03 +#define NT_LOONGARCH_LBT 0xa04 @@ -3304,6 +3310,102 @@ enum #define R_RISCV_TLSDESC_ADD_LO12 64 #define R_RISCV_TLSDESC_CALL 65 +#define EF_LARCH_ABI_MODIFIER_MASK 0x07 +#define EF_LARCH_ABI_SOFT_FLOAT 0x01 +#define EF_LARCH_ABI_SINGLE_FLOAT 0x02 +#define EF_LARCH_ABI_DOUBLE_FLOAT 0x03 +#define EF_LARCH_OBJABI_V1 0x40 + +#define R_LARCH_NONE 0 +#define R_LARCH_32 1 +#define R_LARCH_64 2 +#define R_LARCH_RELATIVE 3 +#define R_LARCH_COPY 4 +#define R_LARCH_JUMP_SLOT 5 +#define R_LARCH_TLS_DTPMOD32 6 +#define R_LARCH_TLS_DTPMOD64 7 +#define R_LARCH_TLS_DTPREL32 8 +#define R_LARCH_TLS_DTPREL64 9 +#define R_LARCH_TLS_TPREL32 10 +#define R_LARCH_TLS_TPREL64 11 +#define R_LARCH_IRELATIVE 12 +#define R_LARCH_MARK_LA 20 +#define R_LARCH_MARK_PCREL 21 +#define R_LARCH_SOP_PUSH_PCREL 22 +#define R_LARCH_SOP_PUSH_ABSOLUTE 23 +#define R_LARCH_SOP_PUSH_DUP 24 +#define R_LARCH_SOP_PUSH_GPREL 25 +#define R_LARCH_SOP_PUSH_TLS_TPREL 26 +#define R_LARCH_SOP_PUSH_TLS_GOT 27 +#define R_LARCH_SOP_PUSH_TLS_GD 28 +#define R_LARCH_SOP_PUSH_PLT_PCREL 29 +#define R_LARCH_SOP_ASSERT 30 +#define R_LARCH_SOP_NOT 31 +#define R_LARCH_SOP_SUB 32 +#define R_LARCH_SOP_SL 33 +#define R_LARCH_SOP_SR 34 +#define R_LARCH_SOP_ADD 35 +#define R_LARCH_SOP_AND 36 +#define R_LARCH_SOP_IF_ELSE 37 +#define R_LARCH_SOP_POP_32_S_10_5 38 +#define R_LARCH_SOP_POP_32_U_10_12 39 +#define R_LARCH_SOP_POP_32_S_10_12 40 +#define R_LARCH_SOP_POP_32_S_10_16 41 +#define R_LARCH_SOP_POP_32_S_10_16_S2 42 +#define R_LARCH_SOP_POP_32_S_5_20 43 +#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 +#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 +#define R_LARCH_SOP_POP_32_U 46 +#define R_LARCH_ADD8 47 +#define R_LARCH_ADD16 48 +#define R_LARCH_ADD24 49 +#define R_LARCH_ADD32 50 +#define R_LARCH_ADD64 51 +#define R_LARCH_SUB8 52 +#define R_LARCH_SUB16 53 +#define R_LARCH_SUB24 54 +#define R_LARCH_SUB32 55 +#define R_LARCH_SUB64 56 +#define R_LARCH_GNU_VTINHERIT 57 +#define R_LARCH_GNU_VTENTRY 58 +#define R_LARCH_B16 64 +#define R_LARCH_B21 65 +#define R_LARCH_B26 66 +#define R_LARCH_ABS_HI20 67 +#define R_LARCH_ABS_LO12 68 +#define R_LARCH_ABS64_LO20 69 +#define R_LARCH_ABS64_HI12 70 +#define R_LARCH_PCALA_HI20 71 +#define R_LARCH_PCALA_LO12 72 +#define R_LARCH_PCALA64_LO20 73 +#define R_LARCH_PCALA64_HI12 74 +#define R_LARCH_GOT_PC_HI20 75 +#define R_LARCH_GOT_PC_LO12 76 +#define R_LARCH_GOT64_PC_LO20 77 +#define R_LARCH_GOT64_PC_HI12 78 +#define R_LARCH_GOT_HI20 79 +#define R_LARCH_GOT_LO12 80 +#define R_LARCH_GOT64_LO20 81 +#define R_LARCH_GOT64_HI12 82 +#define R_LARCH_TLS_LE_HI20 83 +#define R_LARCH_TLS_LE_LO12 84 +#define R_LARCH_TLS_LE64_LO20 85 +#define R_LARCH_TLS_LE64_HI12 86 +#define R_LARCH_TLS_IE_PC_HI20 87 +#define R_LARCH_TLS_IE_PC_LO12 88 +#define R_LARCH_TLS_IE64_PC_LO20 89 +#define R_LARCH_TLS_IE64_PC_HI12 90 +#define R_LARCH_TLS_IE_HI20 91 +#define R_LARCH_TLS_IE_LO12 92 +#define R_LARCH_TLS_IE64_LO20 93 +#define R_LARCH_TLS_IE64_HI12 94 +#define R_LARCH_TLS_LD_PC_HI20 95 +#define R_LARCH_TLS_LD_HI20 96 +#define R_LARCH_TLS_GD_PC_HI20 97 +#define R_LARCH_TLS_GD_HI20 98 +#define R_LARCH_32_PCREL 99 +#define R_LARCH_RELAX 100 + #ifdef __cplusplus } #endif diff --git a/src/fenv/loongarch64/fenv.S b/src/fenv/loongarch64/fenv.S new file mode 100644 index 00000000..9c38599e --- /dev/null +++ b/src/fenv/loongarch64/fenv.S @@ -0,0 +1,78 @@ +#ifndef __loongarch_soft_float + +#ifdef BROKEN_LOONGARCH_FCSR_ASM +#define FCSR $r0 +#else +#define FCSR $fcsr0 +#endif + +.global feclearexcept +.type feclearexcept,@function +feclearexcept: + li.w $t0, 0x1f0000 + and $a0, $a0, $t0 + movfcsr2gr $t1, FCSR + andn $t1, $t1, $a0 + movgr2fcsr FCSR, $t1 + li.w $a0, 0 + jr $ra + +.global feraiseexcept +.type feraiseexcept,@function +feraiseexcept: + li.w $t0, 0x1f0000 + and $a0, $a0, $t0 + movfcsr2gr $t1, FCSR + or $t1, $t1, $a0 + movgr2fcsr FCSR, $t1 + li.w $a0, 0 + jr $ra + +.global fetestexcept +.type fetestexcept,@function +fetestexcept: + li.w $t0, 0x1f0000 + and $a0, $a0, $t0 + movfcsr2gr $t1, FCSR + and $a0, $t1, $a0 + jr $ra + +.global fegetround +.type fegetround,@function +fegetround: + movfcsr2gr $t0, FCSR + andi $a0, $t0, 0x300 + jr $ra + +.global __fesetround +.hidden __fesetround +.type __fesetround,@function +__fesetround: + li.w $t0, 0x300 + and $a0, $a0, $t0 + movfcsr2gr $t1, FCSR + andn $t1, $t1, $t0 + or $t1, $t1, $a0 + movgr2fcsr FCSR, $t1 + li.w $a0, 0 + jr $ra + +.global fegetenv +.type fegetenv,@function +fegetenv: + movfcsr2gr $t0, FCSR + st.w $t0, $a0, 0 + li.w $a0, 0 + jr $ra + +.global fesetenv +.type fesetenv,@function +fesetenv: + addi.d $t0, $a0, 1 + beq $t0, $r0, 1f + ld.w $t0, $a0, 0 +1: movgr2fcsr FCSR, $t0 + li.w $a0, 0 + jr $ra + +#endif diff --git a/src/ldso/loongarch64/dlsym.s b/src/ldso/loongarch64/dlsym.s new file mode 100644 index 00000000..26fabcdb --- /dev/null +++ b/src/ldso/loongarch64/dlsym.s @@ -0,0 +1,7 @@ +.global dlsym +.hidden __dlsym +.type dlsym,@function +dlsym: + move $a2, $ra + la.global $t0, __dlsym + jr $t0 diff --git a/src/setjmp/loongarch64/longjmp.S b/src/setjmp/loongarch64/longjmp.S new file mode 100644 index 00000000..896d2e26 --- /dev/null +++ b/src/setjmp/loongarch64/longjmp.S @@ -0,0 +1,32 @@ +.global _longjmp +.global longjmp +.type _longjmp,@function +.type longjmp,@function +_longjmp: +longjmp: + ld.d $ra, $a0, 0 + ld.d $sp, $a0, 8 + ld.d $r21,$a0, 16 + ld.d $fp, $a0, 24 + ld.d $s0, $a0, 32 + ld.d $s1, $a0, 40 + ld.d $s2, $a0, 48 + ld.d $s3, $a0, 56 + ld.d $s4, $a0, 64 + ld.d $s5, $a0, 72 + ld.d $s6, $a0, 80 + ld.d $s7, $a0, 88 + ld.d $s8, $a0, 96 +#ifndef __loongarch_soft_float + fld.d $fs0, $a0, 104 + fld.d $fs1, $a0, 112 + fld.d $fs2, $a0, 120 + fld.d $fs3, $a0, 128 + fld.d $fs4, $a0, 136 + fld.d $fs5, $a0, 144 + fld.d $fs6, $a0, 152 + fld.d $fs7, $a0, 160 +#endif + sltui $a0, $a1, 1 + add.d $a0, $a0, $a1 + jr $ra diff --git a/src/setjmp/loongarch64/setjmp.S b/src/setjmp/loongarch64/setjmp.S new file mode 100644 index 00000000..d158a3d2 --- /dev/null +++ b/src/setjmp/loongarch64/setjmp.S @@ -0,0 +1,34 @@ +.global __setjmp +.global _setjmp +.global setjmp +.type __setjmp,@function +.type _setjmp,@function +.type setjmp,@function +__setjmp: +_setjmp: +setjmp: + st.d $ra, $a0, 0 + st.d $sp, $a0, 8 + st.d $r21,$a0, 16 + st.d $fp, $a0, 24 + st.d $s0, $a0, 32 + st.d $s1, $a0, 40 + st.d $s2, $a0, 48 + st.d $s3, $a0, 56 + st.d $s4, $a0, 64 + st.d $s5, $a0, 72 + st.d $s6, $a0, 80 + st.d $s7, $a0, 88 + st.d $s8, $a0, 96 +#ifndef __loongarch_soft_float + fst.d $fs0, $a0, 104 + fst.d $fs1, $a0, 112 + fst.d $fs2, $a0, 120 + fst.d $fs3, $a0, 128 + fst.d $fs4, $a0, 136 + fst.d $fs5, $a0, 144 + fst.d $fs6, $a0, 152 + fst.d $fs7, $a0, 160 +#endif + move $a0, $zero + jr $ra diff --git a/src/signal/loongarch64/restore.s b/src/signal/loongarch64/restore.s new file mode 100644 index 00000000..d90a8ebb --- /dev/null +++ b/src/signal/loongarch64/restore.s @@ -0,0 +1,10 @@ +.global __restore_rt +.global __restore +.hidden __restore_rt +.hidden __restore +.type __restore_rt,@function +.type __restore,@function +__restore_rt: +__restore: + li.w $a7, 139 + syscall 0 diff --git a/src/signal/loongarch64/sigsetjmp.s b/src/signal/loongarch64/sigsetjmp.s new file mode 100644 index 00000000..9c0e3ae2 --- /dev/null +++ b/src/signal/loongarch64/sigsetjmp.s @@ -0,0 +1,25 @@ +.global sigsetjmp +.global __sigsetjmp +.type sigsetjmp,@function +.type __sigsetjmp,@function +sigsetjmp: +__sigsetjmp: + beq $a1, $zero, 1f + st.d $ra, $a0, 184 + st.d $s0, $a0, 200 #184+8+8 + move $s0, $a0 + + la.global $t0, setjmp + jirl $ra, $t0, 0 + + move $a1, $a0 # Return from 'setjmp' or 'longjmp' + move $a0, $s0 + ld.d $ra, $a0, 184 + ld.d $s0, $a0, 200 #184+8+8 + +.hidden __sigsetjmp_tail + la.global $t0, __sigsetjmp_tail + jr $t0 +1: + la.global $t0, setjmp + jr $t0 diff --git a/src/thread/loongarch64/__set_thread_area.s b/src/thread/loongarch64/__set_thread_area.s new file mode 100644 index 00000000..021307fc --- /dev/null +++ b/src/thread/loongarch64/__set_thread_area.s @@ -0,0 +1,7 @@ +.global __set_thread_area +.hidden __set_thread_area +.type __set_thread_area,@function +__set_thread_area: + move $tp, $a0 + move $a0, $zero + jr $ra diff --git a/src/thread/loongarch64/__unmapself.s b/src/thread/loongarch64/__unmapself.s new file mode 100644 index 00000000..719ad056 --- /dev/null +++ b/src/thread/loongarch64/__unmapself.s @@ -0,0 +1,7 @@ +.global __unmapself +.type __unmapself, @function +__unmapself: + li.d $a7, 215 # call munmap + syscall 0 + li.d $a7, 93 # call exit + syscall 0 diff --git a/src/thread/loongarch64/clone.s b/src/thread/loongarch64/clone.s new file mode 100644 index 00000000..e971ab4b --- /dev/null +++ b/src/thread/loongarch64/clone.s @@ -0,0 +1,28 @@ +#__clone(func, stack, flags, arg, ptid, tls, ctid) +# a0, a1, a2, a3, a4, a5, a6 +# sys_clone(flags, stack, ptid, ctid, tls) +# a0, a1, a2, a3, a4 + +.global __clone +.hidden __clone +.type __clone,@function +__clone: + # Save function pointer and argument pointer on new thread stack + addi.d $a1, $a1, -16 + st.d $a0, $a1, 0 # save function pointer + st.d $a3, $a1, 8 # save argument pointer + or $a0, $a2, $zero + or $a2, $a4, $zero + or $a3, $a6, $zero + or $a4, $a5, $zero + ori $a7, $zero, 220 + syscall 0 # call clone + + beqz $a0, 1f # whether child process + jirl $zero, $ra, 0 # parent process return +1: + ld.d $t8, $sp, 0 # function pointer + ld.d $a0, $sp, 8 # argument pointer + jirl $ra, $t8, 0 # call the user's function + ori $a7, $zero, 93 + syscall 0 # child process exit diff --git a/src/thread/loongarch64/syscall_cp.s b/src/thread/loongarch64/syscall_cp.s new file mode 100644 index 00000000..c057a97b --- /dev/null +++ b/src/thread/loongarch64/syscall_cp.s @@ -0,0 +1,29 @@ +.global __cp_begin +.hidden __cp_begin +.global __cp_end +.hidden __cp_end +.global __cp_cancel +.hidden __cp_cancel +.hidden __cancel +.global __syscall_cp_asm +.hidden __syscall_cp_asm +.type __syscall_cp_asm,@function + +__syscall_cp_asm: +__cp_begin: + ld.w $a0, $a0, 0 + bnez $a0, __cp_cancel + move $t8, $a1 # reserve system call number + move $a0, $a2 + move $a1, $a3 + move $a2, $a4 + move $a3, $a5 + move $a4, $a6 + move $a5, $a7 + move $a7, $t8 + syscall 0 +__cp_end: + jr $ra +__cp_cancel: + la.local $t8, __cancel + jr $t8 From 7020e85fd768be02e7f5971f1707229407cfa1e4 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 17 Feb 2024 20:36:42 -0500 Subject: [PATCH 261/297] sh: fix sigsetjmp corrupting call-saved register r8 due to incorrect base address register when attempting to reload the saved value of r8, the caller's value of r8 was not preserved. --- src/signal/sh/sigsetjmp.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/signal/sh/sigsetjmp.s b/src/signal/sh/sigsetjmp.s index 1e2270be..f0f604e2 100644 --- a/src/signal/sh/sigsetjmp.s +++ b/src/signal/sh/sigsetjmp.s @@ -27,7 +27,7 @@ __sigsetjmp: mov.l 3f, r0 4: braf r0 - mov.l @(4+8,r4), r8 + mov.l @(4+8,r6), r8 9: mov.l 5f, r0 6: braf r0 From 19563e1850808af216b1b84263bb7e83cccce506 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 22 Feb 2024 18:50:34 -0500 Subject: [PATCH 262/297] add framework to support archs without a native wait4 syscall this commit should make no codegen change for existing archs, but is a prerequisite for new archs including riscv32. the wait4 emulation backend provides both cancellable and non-cancellable variants because waitpid is required to be a cancellation point, but all of our other uses are not, and most of them cannot be. based on patch by Stefan O'Rear. --- src/internal/emulate_wait4.c | 55 ++++++++++++++++++++++++++++++++++++ src/internal/syscall.h | 12 ++++++++ src/linux/wait4.c | 2 +- src/process/waitpid.c | 2 +- src/stdio/pclose.c | 2 +- src/unistd/faccessat.c | 2 +- 6 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 src/internal/emulate_wait4.c diff --git a/src/internal/emulate_wait4.c b/src/internal/emulate_wait4.c new file mode 100644 index 00000000..f6303412 --- /dev/null +++ b/src/internal/emulate_wait4.c @@ -0,0 +1,55 @@ +#include +#include "syscall.h" + +#ifndef SYS_wait4 +hidden long __emulate_wait4(int pid, int *status, int options, void *kru, int cp) +{ + idtype_t t; + int r; + siginfo_t info; + + info.si_pid = 0; + if (pid < -1) { + t = P_PGID; + pid = -pid; + } else if (pid == -1) { + t = P_ALL; + } else if (pid == 0) { + t = P_PGID; + } else { + t = P_PID; + } + + if (cp) r = __syscall_cp(SYS_waitid, t, pid, &info, options|WEXITED, kru); + else r = __syscall(SYS_waitid, t, pid, &info, options|WEXITED, kru); + + if (r<0) return r; + + if (info.si_pid && status) { + int sw=0; + switch (info.si_code) { + case CLD_CONTINUED: + sw = 0xffff; + break; + case CLD_DUMPED: + sw = info.si_status&0x7f | 0x80; + break; + case CLD_EXITED: + sw = (info.si_status&0xff) << 8; + break; + case CLD_KILLED: + sw = info.si_status&0x7f; + break; + case CLD_STOPPED: + case CLD_TRAPPED: + /* see ptrace(2); the high bits of si_status can contain */ + /* PTRACE_EVENT_ values which must be preserved */ + sw = (info.si_status << 8) + 0x7f; + break; + } + *status = sw; + } + + return info.si_pid; +} +#endif diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 4a446157..33d981f9 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -391,6 +391,18 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, #define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__) #define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__)) +#ifdef SYS_wait4 +#define __sys_wait4(a,b,c,d) __syscall(SYS_wait4,a,b,c,d) +#define __sys_wait4_cp(a,b,c,d) __syscall_cp(SYS_wait4,a,b,c,d) +#else +hidden long __emulate_wait4(int, int *, int, void *, int); +#define __sys_wait4(a,b,c,d) __emulate_wait4(a,b,c,d,0) +#define __sys_wait4_cp(a,b,c,d) __emulate_wait4(a,b,c,d,1) +#endif + +#define sys_wait4(a,b,c,d) __syscall_ret(__sys_wait4(a,b,c,d)) +#define sys_wait4_cp(a,b,c,d) __syscall_ret(__sys_wait4_cp(a,b,c,d)) + hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned); hidden void *__vdsosym(const char *, const char *); diff --git a/src/linux/wait4.c b/src/linux/wait4.c index ff2e3e66..fb08c0d0 100644 --- a/src/linux/wait4.c +++ b/src/linux/wait4.c @@ -26,7 +26,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru) } #endif char *dest = ru ? (char *)&ru->ru_maxrss - 4*sizeof(long) : 0; - r = __syscall(SYS_wait4, pid, status, options, dest); + r = __sys_wait4(pid, status, options, dest); if (r>0 && ru && sizeof(time_t) > sizeof(long)) { long kru[4]; memcpy(kru, dest, 4*sizeof(long)); diff --git a/src/process/waitpid.c b/src/process/waitpid.c index 1b65bf05..80231862 100644 --- a/src/process/waitpid.c +++ b/src/process/waitpid.c @@ -3,5 +3,5 @@ pid_t waitpid(pid_t pid, int *status, int options) { - return syscall_cp(SYS_wait4, pid, status, options, 0); + return sys_wait4_cp(pid, status, options, 0); } diff --git a/src/stdio/pclose.c b/src/stdio/pclose.c index 080a4262..c64da405 100644 --- a/src/stdio/pclose.c +++ b/src/stdio/pclose.c @@ -7,7 +7,7 @@ int pclose(FILE *f) int status, r; pid_t pid = f->pipe_pid; fclose(f); - while ((r=__syscall(SYS_wait4, pid, &status, 0, 0)) == -EINTR); + while ((r=__sys_wait4(pid, &status, 0, 0)) == -EINTR); if (r<0) return __syscall_ret(r); return status; } diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c index 557503eb..43052dd7 100644 --- a/src/unistd/faccessat.c +++ b/src/unistd/faccessat.c @@ -53,7 +53,7 @@ int faccessat(int fd, const char *filename, int amode, int flag) if (pid<0 || __syscall(SYS_read, p[0], &ret, sizeof ret) != sizeof(ret)) ret = -EBUSY; __syscall(SYS_close, p[0]); - __syscall(SYS_wait4, pid, &status, __WCLONE, 0); + __sys_wait4(pid, &status, __WCLONE, 0); __restore_sigs(&set); From a526314c8057eeecbdbd6965b1620cfe3ae6e8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sun, 18 Feb 2024 03:26:43 +0100 Subject: [PATCH 263/297] bits/syscall.h: add memfd_secret from linux v5.14 see linux commit 7bb7f2ac24a028b20fca466b9633847b289b156a arch, mm: wire up memfd_secret system call where relevant linux commit 1507f51255c9ff07d75909a84e7c0d7f3c4b2f49 mm: introduce memfd_secret system call to create "secret" memory areas linux commit b633896314c0f78f2b4eb7b19a530d68f2a35445 tools headers UAPI: Sync s390 syscall table file that wires up the memfd_secret syscall --- arch/i386/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 4 files changed, 4 insertions(+) diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index 46ffe1d9..8baf6de7 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -436,4 +436,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_memfd_secret 447 diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index dfc38479..58697e5b 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -362,4 +362,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_memfd_secret 447 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index 5d22fa17..b3b07eef 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -308,6 +308,7 @@ #define __NR_landlock_create_ruleset (0x40000000 + 444) #define __NR_landlock_add_rule (0x40000000 + 445) #define __NR_landlock_restrict_self (0x40000000 + 446) +#define __NR_memfd_secret (0x40000000 + 447) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index c3882de7..a81aa94a 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -355,4 +355,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_memfd_secret 447 From e9751279479edc63af2c15b54a85cbe0374ca8b7 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 22 Feb 2024 19:21:31 -0500 Subject: [PATCH 264/297] bits/syscall.h: add process_mrelease from linux v5.15 see linux commit 884a7e5964e06ed93c7771c0d7cf19c09a8946f1 mm: introduce process_mrelease system call linux commit dce49103962840dd61423d7627748d6c558d58c5 mm: wire up syscall process_mrelease --- arch/aarch64/bits/syscall.h.in | 1 + arch/arm/bits/syscall.h.in | 1 + arch/i386/bits/syscall.h.in | 1 + arch/m68k/bits/syscall.h.in | 1 + arch/microblaze/bits/syscall.h.in | 1 + arch/mips/bits/syscall.h.in | 1 + arch/mips64/bits/syscall.h.in | 1 + arch/mipsn32/bits/syscall.h.in | 1 + arch/or1k/bits/syscall.h.in | 1 + arch/powerpc/bits/syscall.h.in | 1 + arch/powerpc64/bits/syscall.h.in | 1 + arch/riscv64/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/sh/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 16 files changed, 16 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index 5f420e61..1d0435db 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -299,4 +299,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_process_mrelease 448 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index 048fdea7..1445cbf7 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -399,6 +399,7 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_process_mrelease 448 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index 8baf6de7..d8df69ec 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -437,4 +437,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_memfd_secret 447 +#define __NR_process_mrelease 448 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index a0c63323..f0ae301a 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -416,3 +416,4 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_process_mrelease 448 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index 931d7919..a98089bf 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -437,4 +437,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_process_mrelease 448 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index 63e3503a..697e8aa0 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -418,4 +418,5 @@ #define __NR_landlock_create_ruleset 4444 #define __NR_landlock_add_rule 4445 #define __NR_landlock_restrict_self 4446 +#define __NR_process_mrelease 4448 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index b89965d1..eabb3e4a 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -348,4 +348,5 @@ #define __NR_landlock_create_ruleset 5444 #define __NR_landlock_add_rule 5445 #define __NR_landlock_restrict_self 5446 +#define __NR_process_mrelease 5448 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index bb2d04a8..80aee609 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -372,4 +372,5 @@ #define __NR_landlock_create_ruleset 6444 #define __NR_landlock_add_rule 6445 #define __NR_landlock_restrict_self 6446 +#define __NR_process_mrelease 6448 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index 2b5f2052..6ea7f72a 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -321,4 +321,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_process_mrelease 448 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index b1605a58..f31dd743 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -425,4 +425,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_process_mrelease 448 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index b3a8fba0..7149ea62 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -397,4 +397,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_process_mrelease 448 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index b534afe8..8fc3158a 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -299,6 +299,7 @@ #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_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index 58697e5b..cc239a11 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -363,4 +363,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_memfd_secret 447 +#define __NR_process_mrelease 448 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index ff14f54d..b752f83d 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -409,4 +409,5 @@ #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 +#define __NR_process_mrelease 448 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index b3b07eef..6b0e3c3a 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -309,6 +309,7 @@ #define __NR_landlock_add_rule (0x40000000 + 445) #define __NR_landlock_restrict_self (0x40000000 + 446) #define __NR_memfd_secret (0x40000000 + 447) +#define __NR_process_mrelease (0x40000000 + 448) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index a81aa94a..647c427b 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -356,4 +356,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_memfd_secret 447 +#define __NR_process_mrelease 448 From b2c4c3d590a338b574bbbb691963995e6541ae75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sun, 18 Feb 2024 03:26:45 +0100 Subject: [PATCH 265/297] bits/syscall.h: add futex_waitv from linux v5.16 see linux commit 039c0ec9bb77446d7ada7f55f90af9299b28ca49 futex,x86: Wire up sys_futex_waitv() linux commit ea7c45fde5aa3e761aaddb7902a31a95cb120e7b futex,arm: Wire up sys_futex_waitv() linux commit b3ff2881ba18b852f79f5476d7631940071f1adb MIPS: syscalls: Wire up futex_waitv syscall linux commit 6c122360cf2f4c5a856fcbd79b4485b7baec942a s390: wire up sys_futex_waitv system call linux commit a0eb2da92b715d0c97b96b09979689ea09faefe6 futex: Wireup futex_waitv syscall --- arch/aarch64/bits/syscall.h.in | 1 + arch/arm/bits/syscall.h.in | 1 + arch/i386/bits/syscall.h.in | 1 + arch/m68k/bits/syscall.h.in | 1 + arch/microblaze/bits/syscall.h.in | 1 + arch/mips/bits/syscall.h.in | 1 + arch/mips64/bits/syscall.h.in | 1 + arch/mipsn32/bits/syscall.h.in | 1 + arch/or1k/bits/syscall.h.in | 1 + arch/powerpc/bits/syscall.h.in | 1 + arch/powerpc64/bits/syscall.h.in | 1 + arch/riscv64/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/sh/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 16 files changed, 16 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index 1d0435db..7641d6a0 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -300,4 +300,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index 1445cbf7..6dafff15 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -400,6 +400,7 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index d8df69ec..907b5641 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -438,4 +438,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_memfd_secret 447 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index f0ae301a..a253aea5 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -417,3 +417,4 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index a98089bf..dcc835a3 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -438,4 +438,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index 697e8aa0..bbed0c1b 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -419,4 +419,5 @@ #define __NR_landlock_add_rule 4445 #define __NR_landlock_restrict_self 4446 #define __NR_process_mrelease 4448 +#define __NR_futex_waitv 4449 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index eabb3e4a..06562072 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -349,4 +349,5 @@ #define __NR_landlock_add_rule 5445 #define __NR_landlock_restrict_self 5446 #define __NR_process_mrelease 5448 +#define __NR_futex_waitv 5449 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index 80aee609..21476c7b 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -373,4 +373,5 @@ #define __NR_landlock_add_rule 6445 #define __NR_landlock_restrict_self 6446 #define __NR_process_mrelease 6448 +#define __NR_futex_waitv 6449 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index 6ea7f72a..bc55def0 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -322,4 +322,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index f31dd743..22f84f1e 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -426,4 +426,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index 7149ea62..3cdc9331 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -398,4 +398,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index 8fc3158a..1b13a477 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -300,6 +300,7 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index cc239a11..0de01875 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -364,4 +364,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_memfd_secret 447 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index b752f83d..1169a1bd 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -410,4 +410,5 @@ #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index 6b0e3c3a..5390db02 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -310,6 +310,7 @@ #define __NR_landlock_restrict_self (0x40000000 + 446) #define __NR_memfd_secret (0x40000000 + 447) #define __NR_process_mrelease (0x40000000 + 448) +#define __NR_futex_waitv (0x40000000 + 449) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index 647c427b..f566d52d 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -357,4 +357,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_memfd_secret 447 #define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 From 33e8c469a9ebd1ffa2eab415d39bb586dc73454c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sun, 18 Feb 2024 03:26:46 +0100 Subject: [PATCH 266/297] bits/syscall.h: add set_mempolicy_home_node from linux v5.17 see linux commit c6018b4b254971863bd0ad36bb5e7d0fa0f0ddb0 mm/mempolicy: add set_mempolicy_home_node syscall linux commit 21b084fdf2a49ca1634e8e360e9ab6f9ff0dee11 mm/mempolicy: wire up syscall set_mempolicy_home_node --- arch/aarch64/bits/syscall.h.in | 1 + arch/arm/bits/syscall.h.in | 1 + arch/i386/bits/syscall.h.in | 1 + arch/m68k/bits/syscall.h.in | 1 + arch/microblaze/bits/syscall.h.in | 1 + arch/mips/bits/syscall.h.in | 1 + arch/mips64/bits/syscall.h.in | 1 + arch/mipsn32/bits/syscall.h.in | 1 + arch/or1k/bits/syscall.h.in | 1 + arch/powerpc/bits/syscall.h.in | 1 + arch/powerpc64/bits/syscall.h.in | 1 + arch/riscv64/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/sh/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 16 files changed, 16 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index 7641d6a0..35a95454 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -301,4 +301,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index 6dafff15..9f025e70 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -401,6 +401,7 @@ #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index 907b5641..a2c40786 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -439,4 +439,5 @@ #define __NR_memfd_secret 447 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index a253aea5..dd6cfb82 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -418,3 +418,4 @@ #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index dcc835a3..2d2f6507 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -439,4 +439,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index bbed0c1b..6f69f92e 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -420,4 +420,5 @@ #define __NR_landlock_restrict_self 4446 #define __NR_process_mrelease 4448 #define __NR_futex_waitv 4449 +#define __NR_set_mempolicy_home_node 4450 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index 06562072..117a49e7 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -350,4 +350,5 @@ #define __NR_landlock_restrict_self 5446 #define __NR_process_mrelease 5448 #define __NR_futex_waitv 5449 +#define __NR_set_mempolicy_home_node 5450 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index 21476c7b..07c1b5d9 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -374,4 +374,5 @@ #define __NR_landlock_restrict_self 6446 #define __NR_process_mrelease 6448 #define __NR_futex_waitv 6449 +#define __NR_set_mempolicy_home_node 6450 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index bc55def0..5b98bc8b 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -323,4 +323,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index 22f84f1e..38124a86 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -427,4 +427,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index 3cdc9331..7afa1c69 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -399,4 +399,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index 1b13a477..4baa0fcc 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -301,6 +301,7 @@ #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_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index 0de01875..e0425f54 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -365,4 +365,5 @@ #define __NR_memfd_secret 447 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index 1169a1bd..3b2d375b 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -411,4 +411,5 @@ #define __NR_landlock_restrict_self 446 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index 5390db02..8a2cf7b0 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -311,6 +311,7 @@ #define __NR_memfd_secret (0x40000000 + 447) #define __NR_process_mrelease (0x40000000 + 448) #define __NR_futex_waitv (0x40000000 + 449) +#define __NR_set_mempolicy_home_node (0x40000000 + 450) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index f566d52d..439b2bfa 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -358,4 +358,5 @@ #define __NR_memfd_secret 447 #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 From dd690c490951443ce5b96594c9c44cb6177daac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sun, 18 Feb 2024 03:26:47 +0100 Subject: [PATCH 267/297] bits/syscall.h: add cachestat from linux v6.4 see linux commit cf264e1329fb0307e044f7675849f9f38b44c11a cachestat: implement cachestat syscall linux commit 946e697c69ffeeefdd84dad90eac307284df46be cachestat: wire up cachestat for other architectures --- arch/aarch64/bits/syscall.h.in | 1 + arch/arm/bits/syscall.h.in | 1 + arch/i386/bits/syscall.h.in | 1 + arch/m68k/bits/syscall.h.in | 1 + arch/microblaze/bits/syscall.h.in | 1 + arch/mips/bits/syscall.h.in | 1 + arch/mips64/bits/syscall.h.in | 1 + arch/mipsn32/bits/syscall.h.in | 1 + arch/or1k/bits/syscall.h.in | 1 + arch/powerpc/bits/syscall.h.in | 1 + arch/powerpc64/bits/syscall.h.in | 1 + arch/riscv64/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/sh/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 16 files changed, 16 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index 35a95454..04207254 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -302,4 +302,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index 9f025e70..a71118f1 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -402,6 +402,7 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index a2c40786..f11dbac3 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -440,4 +440,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index dd6cfb82..c3c2dc14 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -419,3 +419,4 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index 2d2f6507..8e160f98 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -440,4 +440,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index 6f69f92e..f776df31 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -421,4 +421,5 @@ #define __NR_process_mrelease 4448 #define __NR_futex_waitv 4449 #define __NR_set_mempolicy_home_node 4450 +#define __NR_cachestat 4451 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index 117a49e7..36d79ad9 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -351,4 +351,5 @@ #define __NR_process_mrelease 5448 #define __NR_futex_waitv 5449 #define __NR_set_mempolicy_home_node 5450 +#define __NR_cachestat 5451 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index 07c1b5d9..63dafa58 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -375,4 +375,5 @@ #define __NR_process_mrelease 6448 #define __NR_futex_waitv 6449 #define __NR_set_mempolicy_home_node 6450 +#define __NR_cachestat 6451 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index 5b98bc8b..12bf9255 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -324,4 +324,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index 38124a86..30ae8dd4 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -428,4 +428,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index 7afa1c69..cb8162cc 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -400,4 +400,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index 4baa0fcc..f4901758 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -302,6 +302,7 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index e0425f54..21577df5 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -366,4 +366,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index 3b2d375b..02c37ec1 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -412,4 +412,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index 8a2cf7b0..d239c587 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -312,6 +312,7 @@ #define __NR_process_mrelease (0x40000000 + 448) #define __NR_futex_waitv (0x40000000 + 449) #define __NR_set_mempolicy_home_node (0x40000000 + 450) +#define __NR_cachestat (0x40000000 + 451) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index 439b2bfa..0067d33b 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -359,4 +359,5 @@ #define __NR_process_mrelease 448 #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 From fb9d976cc2ae510d2c3c763ed7db9bdb5269e38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sun, 18 Feb 2024 03:26:48 +0100 Subject: [PATCH 268/297] remove flag argument from fchmodat syscall linux's does not have the flag argument for fchmodat syscall. --- src/stat/fchmodat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c index bc581050..41db0c46 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -5,7 +5,7 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) { - if (!flag) return syscall(SYS_fchmodat, fd, path, mode, flag); + if (!flag) return syscall(SYS_fchmodat, fd, path, mode); if (flag != AT_SYMLINK_NOFOLLOW) return __syscall_ret(-EINVAL); From 3d5c9fe39ff6ceb0730d44122fd2c4cd58b4e358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sun, 18 Feb 2024 03:26:49 +0100 Subject: [PATCH 269/297] bits/syscall.h: add __NR_fchmodat2 from linux v6.6 the linux fchmodat syscall lacks a flag argument that is necessary to implement the posix api, see linux commit 09da082b07bbae1c11d9560c8502800039aebcea fs: Add fchmodat2() linux commit 78252deb023cf0879256fcfbafe37022c390762b arch: Register fchmodat2, usually as syscall 452 --- arch/aarch64/bits/syscall.h.in | 1 + arch/arm/bits/syscall.h.in | 1 + arch/i386/bits/syscall.h.in | 1 + arch/m68k/bits/syscall.h.in | 1 + arch/microblaze/bits/syscall.h.in | 1 + arch/mips/bits/syscall.h.in | 1 + arch/mips64/bits/syscall.h.in | 1 + arch/mipsn32/bits/syscall.h.in | 1 + arch/or1k/bits/syscall.h.in | 1 + arch/powerpc/bits/syscall.h.in | 1 + arch/powerpc64/bits/syscall.h.in | 1 + arch/riscv64/bits/syscall.h.in | 1 + arch/s390x/bits/syscall.h.in | 1 + arch/sh/bits/syscall.h.in | 1 + arch/x32/bits/syscall.h.in | 1 + arch/x86_64/bits/syscall.h.in | 1 + 16 files changed, 16 insertions(+) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index 04207254..ea5a152a 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -303,4 +303,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index a71118f1..157b304d 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -403,6 +403,7 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index f11dbac3..55e91cc4 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -441,4 +441,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index c3c2dc14..5cd84602 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -420,3 +420,4 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index 8e160f98..40860e6d 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -441,4 +441,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index f776df31..55e35742 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -422,4 +422,5 @@ #define __NR_futex_waitv 4449 #define __NR_set_mempolicy_home_node 4450 #define __NR_cachestat 4451 +#define __NR_fchmodat2 4452 diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index 36d79ad9..50cec45a 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -352,4 +352,5 @@ #define __NR_futex_waitv 5449 #define __NR_set_mempolicy_home_node 5450 #define __NR_cachestat 5451 +#define __NR_fchmodat2 5452 diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index 63dafa58..9a4bd301 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -376,4 +376,5 @@ #define __NR_futex_waitv 6449 #define __NR_set_mempolicy_home_node 6450 #define __NR_cachestat 6451 +#define __NR_fchmodat2 6452 diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index 12bf9255..00812bf8 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -325,4 +325,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index 30ae8dd4..ea95f3ed 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -429,4 +429,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index cb8162cc..43551079 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -401,4 +401,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index f4901758..e362bd0e 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -303,6 +303,7 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index 21577df5..e60711a6 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -367,4 +367,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index 02c37ec1..915a79cd 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -413,4 +413,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index d239c587..1d065eea 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -313,6 +313,7 @@ #define __NR_futex_waitv (0x40000000 + 449) #define __NR_set_mempolicy_home_node (0x40000000 + 450) #define __NR_cachestat (0x40000000 + 451) +#define __NR_fchmodat2 (0x40000000 + 452) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index 0067d33b..6543bbba 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -360,4 +360,5 @@ #define __NR_futex_waitv 449 #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 +#define __NR_fchmodat2 452 From d0ed307e6f79476bda12e531f7d30378a6167b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sun, 18 Feb 2024 03:26:50 +0100 Subject: [PATCH 270/297] use new SYS_fchmodat2 syscall to implement fchmodat with flags commit 0dc4824479e357a3e23a02d35527e23fca920343 worked around for lack of flags argument in syscall for fchmodat. linux 6.6 introduced a new syscall, SYS_fchmodat2, fixing this deficiency. use it if any flags are passed, and fallback to the old strategy on ENOSYS. continue using the old syscall when there are no flags. this is the exact same strategy used when SYS_faccessat2 was used to implement faccessat with flags. --- src/stat/fchmodat.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c index 41db0c46..92c9d1b0 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -7,11 +7,14 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) { if (!flag) return syscall(SYS_fchmodat, fd, path, mode); + int ret = __syscall(SYS_fchmodat2, fd, path, mode, flag); + if (ret != -ENOSYS) return __syscall_ret(ret); + if (flag != AT_SYMLINK_NOFOLLOW) return __syscall_ret(-EINVAL); struct stat st; - int ret, fd2; + int fd2; char proc[15+3*sizeof(int)]; if (fstatat(fd, path, &st, flag)) From b817541f1cfd38e4b81257b3215e276ea9d0fc61 Mon Sep 17 00:00:00 2001 From: Duncan Bellamy Date: Wed, 31 Aug 2022 20:07:34 +0100 Subject: [PATCH 271/297] add statx interface using syscall, fallback to fstatat --- include/sys/stat.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++ src/linux/statx.c | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/linux/statx.c diff --git a/include/sys/stat.h b/include/sys/stat.h index e6d0049c..6690192d 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -18,6 +18,13 @@ extern "C" { #define __NEED_blkcnt_t #define __NEED_struct_timespec +#ifdef _GNU_SOURCE +#define __NEED_int64_t +#define __NEED_uint64_t +#define __NEED_uint32_t +#define __NEED_uint16_t +#endif + #include #include @@ -98,6 +105,54 @@ int lchmod(const char *, mode_t); #define S_IEXEC S_IXUSR #endif +#if defined(_GNU_SOURCE) +#define STATX_TYPE 1U +#define STATX_MODE 2U +#define STATX_NLINK 4U +#define STATX_UID 8U +#define STATX_GID 0x10U +#define STATX_ATIME 0x20U +#define STATX_MTIME 0x40U +#define STATX_CTIME 0x80U +#define STATX_INO 0x100U +#define STATX_SIZE 0x200U +#define STATX_BLOCKS 0x400U +#define STATX_BASIC_STATS 0x7ffU +#define STATX_BTIME 0x800U +#define STATX_ALL 0xfffU + +struct statx_timestamp { + int64_t tv_sec; + uint32_t tv_nsec, __pad; +}; + +struct statx { + uint32_t stx_mask; + uint32_t stx_blksize; + uint64_t stx_attributes; + uint32_t stx_nlink; + uint32_t stx_uid; + uint32_t stx_gid; + uint16_t stx_mode; + uint16_t __pad0[1]; + uint64_t stx_ino; + uint64_t stx_size; + uint64_t stx_blocks; + uint64_t stx_attributes_mask; + struct statx_timestamp stx_atime; + struct statx_timestamp stx_btime; + struct statx_timestamp stx_ctime; + struct statx_timestamp stx_mtime; + uint32_t stx_rdev_major; + uint32_t stx_rdev_minor; + uint32_t stx_dev_major; + uint32_t stx_dev_minor; + uint64_t __pad1[14]; +}; + +int statx(int, const char *__restrict, int, unsigned, struct statx *__restrict); +#endif + #if defined(_LARGEFILE64_SOURCE) #define stat64 stat #define fstat64 fstat diff --git a/src/linux/statx.c b/src/linux/statx.c new file mode 100644 index 00000000..4616bff4 --- /dev/null +++ b/src/linux/statx.c @@ -0,0 +1,42 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct statx *restrict stx) +{ + int ret = __syscall(SYS_statx, dirfd, path, flags, mask, stx); + +#ifndef SYS_fstatat + return __syscall_ret(ret); +#endif + + if (ret != -ENOSYS) return __syscall_ret(ret); + + struct stat st; + ret = fstatat(dirfd, path, &st, flags); + if (ret) return ret; + + stx->stx_dev_major = major(st.st_dev); + stx->stx_dev_minor = minor(st.st_dev); + stx->stx_ino = st.st_ino; + stx->stx_mode = st.st_mode; + stx->stx_nlink = st.st_nlink; + stx->stx_uid = st.st_uid; + stx->stx_gid = st.st_gid; + stx->stx_size = st.st_size; + stx->stx_blksize = st.st_blksize; + stx->stx_blocks = st.st_blocks; + stx->stx_atime.tv_sec = st.st_atim.tv_sec; + stx->stx_atime.tv_nsec = st.st_atim.tv_nsec; + stx->stx_mtime.tv_sec = st.st_mtim.tv_sec; + stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec; + stx->stx_ctime.tv_sec = st.st_ctim.tv_sec; + stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec; + stx->stx_btime = (struct statx_timestamp){.tv_sec=0, .tv_nsec=0}; + stx->stx_mask = STATX_BASIC_STATS; + + return 0; +} From 69670e3bb3f78f9a1d172c9e263ca1b95f8196db Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 25 Feb 2024 15:10:26 -0500 Subject: [PATCH 272/297] sh dlsym: fix passing of return address for RTLD_NEXT use this code dates back to the original commit of the sh port, with no real clue as to how the bug was introduced. it looks like it was written to assume the return address was pushed to the stack like on x86, rather than arriving in the pr special register. --- src/ldso/sh/dlsym.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ldso/sh/dlsym.s b/src/ldso/sh/dlsym.s index 11a6fff5..34f3c35c 100644 --- a/src/ldso/sh/dlsym.s +++ b/src/ldso/sh/dlsym.s @@ -5,7 +5,7 @@ dlsym: mov.l L1, r0 1: braf r0 - mov.l @r15, r6 + sts pr, r6 .align 2 L1: .long __dlsym@PLT-(1b+4-.) From 2c887f24da36fa30eccd72e50d91222828fa526e Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 05:23:40 -0400 Subject: [PATCH 273/297] riscv: fall back to syscall __riscv_flush_icache Matches glibc behavior and fixes a case where we could fall off the function without returning a value. --- src/linux/cache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/linux/cache.c b/src/linux/cache.c index 45024309..e76f7812 100644 --- a/src/linux/cache.c +++ b/src/linux/cache.c @@ -45,6 +45,7 @@ int __riscv_flush_icache(void *start, void *end, unsigned long int flags) if (!r) return r; if (r != -ENOSYS) return __syscall_ret(r); } + return syscall(SYS_riscv_flush_icache, start, end, flags); } weak_alias(__riscv_flush_icache, riscv_flush_icache); #endif From a7239cbc1bc4144eb34e0b85f71769f0acda58dd Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 26 Feb 2024 09:37:44 -0500 Subject: [PATCH 274/297] switch __STDC_UTF_{16,32}__ macro definitions from #undef to #ifndef originally, compilers did not provide these macros and we had to provide them ourselves. this meant we were redefining them, which was technically invalid unless the token sequence of the original definition matched exactly. the original patch proposed by Jules Maselbas to fix this made the definitions conditional on them not already being defined; however I suggested using #undef to avoid any possibly-wrong definitions already in place and ensure that the definitions are 1. the version adopted as commit 8b7048680731707d135ea231f81eb3eaf52378ee made this change. unfortunately, gcc is loud about not liking #undef of any __STDC_* macro name, and while warnings are suppressed in the system include path, there is apparently no way to suppress this warning if the system include dir has also been provided via -I. while normally we don't go out of our way to satisfy warnings over style in the public headers, in this case, it seems to be a matter of disagreement over contract of which part of "the implementation" is entitled to define or undefine macros belonging to the implementation, and it's quite reasonable to conclude that the compiler may reject attempts to undefine them. this commit reverts to the originally-submitted version of the patch making the definitions conditional. --- include/stdc-predef.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/stdc-predef.h b/include/stdc-predef.h index 5ccd884d..642bad2d 100644 --- a/include/stdc-predef.h +++ b/include/stdc-predef.h @@ -7,10 +7,12 @@ #define __STDC_IEC_559__ 1 #endif -#undef __STDC_UTF_16__ +#if !defined(__STDC_UTF_16__) #define __STDC_UTF_16__ 1 +#endif -#undef __STDC_UTF_32__ +#if !defined(__STDC_UTF_32__) #define __STDC_UTF_32__ 1 +#endif #endif From f2c9350543c5cd51a43288248370a41784d89e55 Mon Sep 17 00:00:00 2001 From: wanghongliang Date: Mon, 26 Feb 2024 02:37:08 +0800 Subject: [PATCH 275/297] add loongarch64 signal.h register index macros --- arch/loongarch64/bits/signal.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/loongarch64/bits/signal.h b/arch/loongarch64/bits/signal.h index 8e0e605c..5a9ed8c9 100644 --- a/arch/loongarch64/bits/signal.h +++ b/arch/loongarch64/bits/signal.h @@ -6,6 +6,17 @@ #define SIGSTKSZ 16384 #endif +#if defined(_GNU_SOURCE) +#define LARCH_NGREG 32 +#define LARCH_REG_RA 1 +#define LARCH_REG_SP 3 +#define LARCH_REG_S0 23 +#define LARCH_REG_S1 24 +#define LARCH_REG_A0 4 +#define LARCH_REG_S2 25 +#define LARCH_REG_NARGS 8 +#endif + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) typedef unsigned long greg_t, gregset_t[32]; From ec325b3828772b5b75ea90f8544f5548c80ff087 Mon Sep 17 00:00:00 2001 From: Hongliang Wang Date: Mon, 26 Feb 2024 16:04:26 +0800 Subject: [PATCH 276/297] add loongarch64 user.h structs; adjust elf_fpreg_t and ELF_NFPREG user_regs_struct and user_fp_struct were missing from the initial commit of the port. the union type for elf_fpreg_t and the new value of ELF_NFPREG are made consistent with glibc. --- arch/loongarch64/bits/user.h | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/arch/loongarch64/bits/user.h b/arch/loongarch64/bits/user.h index 5a71d132..fd9b7b22 100644 --- a/arch/loongarch64/bits/user.h +++ b/arch/loongarch64/bits/user.h @@ -1,5 +1,24 @@ #define ELF_NGREG 45 -#define ELF_NFPREG 33 +#define ELF_NFPREG 34 + +struct user_regs_struct { + unsigned long regs[32]; + unsigned long orig_a0; + unsigned long csr_era; + unsigned long csr_badv; + unsigned long reserved[10]; +}; + +struct user_fp_struct { + unsigned long fpr[32]; + unsigned long fcc; + unsigned int fcsr; +}; typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG]; -typedef double elf_fpreg_t, elf_fpregset_t[ELF_NFPREG]; + +typedef union { + double d; + float f; +} elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; From 80e3b09823a1d718664bc13704f3f7c19038a19e Mon Sep 17 00:00:00 2001 From: wanghongliang Date: Mon, 26 Feb 2024 02:12:28 +0800 Subject: [PATCH 277/297] loongarch64 __clone: align stack pointer mod 16 According to LoongArch ABI Specs, stack need to be 16 align to improve performance and compiler layout of stack frames. --- src/thread/loongarch64/clone.s | 1 + 1 file changed, 1 insertion(+) diff --git a/src/thread/loongarch64/clone.s b/src/thread/loongarch64/clone.s index e971ab4b..a165b365 100644 --- a/src/thread/loongarch64/clone.s +++ b/src/thread/loongarch64/clone.s @@ -7,6 +7,7 @@ .hidden __clone .type __clone,@function __clone: + bstrins.d $a1, $zero, 3, 0 #stack to 16 align # Save function pointer and argument pointer on new thread stack addi.d $a1, $a1, -16 st.d $a0, $a1, 0 # save function pointer From d3a61059c04bd82329707324fac0d48e191edbf4 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Thu, 29 Feb 2024 14:13:18 +0300 Subject: [PATCH 278/297] posix_spawn: fix child spinning on write to a broken pipe A child process created by posix_spawn reports errors to its parent via a pipe, retrying infinitely on any write error to prevent falsely reporting success. If the (original) parent dies before write is attempted, there is nobody to report to, but the child will remain stuck in the write loop forever if SIGPIPE is blocked or ignored. Fix this by not retrying write if it fails with EPIPE. --- src/process/posix_spawn.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c index 728551b3..8294598b 100644 --- a/src/process/posix_spawn.c +++ b/src/process/posix_spawn.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "syscall.h" #include "lock.h" @@ -156,7 +157,11 @@ static int child(void *args_vp) fail: /* Since sizeof errno < PIPE_BUF, the write is atomic. */ ret = -ret; - if (ret) while (__syscall(SYS_write, p, &ret, sizeof ret) < 0); + if (ret) { + int r; + do r = __syscall(SYS_write, p, &ret, sizeof ret); + while (r<0 && r!=-EPIPE); + } _exit(127); } From 5c653ccaa1383db0c310abf66d5b6806e83ac18f Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Mon, 8 May 2023 19:03:46 +0300 Subject: [PATCH 279/297] getnameinfo: fix calling __dns_parse with potentially too large rlen __res_send returns the full answer length even if it didn't fit the buffer, but __dns_parse expects the length of the filled part of the buffer. This is analogous to commit 77327ed064bd57b0e1865cd0e0364057ff4a53b4, which fixed the only other __dns_parse call site. --- src/network/getnameinfo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c index 7abe0fa9..133c15b3 100644 --- a/src/network/getnameinfo.c +++ b/src/network/getnameinfo.c @@ -162,8 +162,10 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, query[3] = 0; /* don't need AD flag */ int rlen = __res_send(query, qlen, reply, sizeof reply); buf[0] = 0; - if (rlen > 0) + if (rlen > 0) { + if (rlen > sizeof reply) rlen = sizeof reply; __dns_parse(reply, rlen, dns_parse_callback, buf); + } } if (!*buf) { if (flags & NI_NAMEREQD) return EAI_NONAME; From 01d9fe4d9f7cce7a6dbaece0e2e405a2e3279244 Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 05:40:29 -0400 Subject: [PATCH 280/297] riscv32: add arch headers These are mostly copied from riscv64. _Addr and _Reg had to become int to match compiler-controlled parts of the ABI (result type of sizeof, etc.). There is no kernel stat struct; the userspace stat matches glibc in the sizes and offsets of all fields (including glibc's __dev_t __pad1). The jump buffer is 12 words larger to account for 12 saved double-precision floats; additionally it should be 64-bit aligned to save doubles. The syscall list was significantly revised by deleting all time32 and pre-statx syscalls, and renaming several syscalls that have different names depending on __BITS_PER_LONG, notably mmap2 and _llseek. futex was added as an alias to futex_time64 since it is widely used by software which does not pass time arguments. --- arch/riscv32/atomic_arch.h | 21 +++ arch/riscv32/bits/alltypes.h.in | 18 ++ arch/riscv32/bits/fenv.h | 17 ++ arch/riscv32/bits/float.h | 16 ++ arch/riscv32/bits/posix.h | 2 + arch/riscv32/bits/reg.h | 2 + arch/riscv32/bits/setjmp.h | 1 + arch/riscv32/bits/signal.h | 118 +++++++++++++ arch/riscv32/bits/stat.h | 18 ++ arch/riscv32/bits/stdint.h | 20 +++ arch/riscv32/bits/syscall.h.in | 286 ++++++++++++++++++++++++++++++++ arch/riscv32/bits/user.h | 6 + arch/riscv32/crt_arch.h | 19 +++ arch/riscv32/kstat.h | 0 arch/riscv32/pthread_arch.h | 13 ++ arch/riscv32/reloc.h | 22 +++ arch/riscv32/syscall_arch.h | 80 +++++++++ 17 files changed, 659 insertions(+) create mode 100644 arch/riscv32/atomic_arch.h create mode 100644 arch/riscv32/bits/alltypes.h.in create mode 100644 arch/riscv32/bits/fenv.h create mode 100644 arch/riscv32/bits/float.h create mode 100644 arch/riscv32/bits/posix.h create mode 100644 arch/riscv32/bits/reg.h create mode 100644 arch/riscv32/bits/setjmp.h create mode 100644 arch/riscv32/bits/signal.h create mode 100644 arch/riscv32/bits/stat.h create mode 100644 arch/riscv32/bits/stdint.h create mode 100644 arch/riscv32/bits/syscall.h.in create mode 100644 arch/riscv32/bits/user.h create mode 100644 arch/riscv32/crt_arch.h create mode 100644 arch/riscv32/kstat.h create mode 100644 arch/riscv32/pthread_arch.h create mode 100644 arch/riscv32/reloc.h create mode 100644 arch/riscv32/syscall_arch.h diff --git a/arch/riscv32/atomic_arch.h b/arch/riscv32/atomic_arch.h new file mode 100644 index 00000000..4d418f63 --- /dev/null +++ b/arch/riscv32/atomic_arch.h @@ -0,0 +1,21 @@ +#define a_barrier a_barrier +static inline void a_barrier() +{ + __asm__ __volatile__ ("fence rw,rw" : : : "memory"); +} + +#define a_cas a_cas +static inline int a_cas(volatile int *p, int t, int s) +{ + int old, tmp; + __asm__ __volatile__ ( + "\n1: lr.w.aqrl %0, (%2)\n" + " bne %0, %3, 1f\n" + " sc.w.aqrl %1, %4, (%2)\n" + " bnez %1, 1b\n" + "1:" + : "=&r"(old), "=&r"(tmp) + : "r"(p), "r"((long)t), "r"((long)s) + : "memory"); + return old; +} diff --git a/arch/riscv32/bits/alltypes.h.in b/arch/riscv32/bits/alltypes.h.in new file mode 100644 index 00000000..e2b6129e --- /dev/null +++ b/arch/riscv32/bits/alltypes.h.in @@ -0,0 +1,18 @@ +#define _Addr int +#define _Int64 long long +#define _Reg int + +#define __BYTE_ORDER 1234 +#define __LONG_MAX 0x7fffffffL + +#ifndef __cplusplus +TYPEDEF int wchar_t; +#endif + +TYPEDEF int blksize_t; +TYPEDEF unsigned int nlink_t; + +TYPEDEF float float_t; +TYPEDEF double double_t; + +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; diff --git a/arch/riscv32/bits/fenv.h b/arch/riscv32/bits/fenv.h new file mode 100644 index 00000000..806ec40f --- /dev/null +++ b/arch/riscv32/bits/fenv.h @@ -0,0 +1,17 @@ +#define FE_INVALID 16 +#define FE_DIVBYZERO 8 +#define FE_OVERFLOW 4 +#define FE_UNDERFLOW 2 +#define FE_INEXACT 1 + +#define FE_ALL_EXCEPT 31 + +#define FE_TONEAREST 0 +#define FE_DOWNWARD 2 +#define FE_UPWARD 3 +#define FE_TOWARDZERO 1 + +typedef unsigned int fexcept_t; +typedef unsigned int fenv_t; + +#define FE_DFL_ENV ((const fenv_t *) -1) diff --git a/arch/riscv32/bits/float.h b/arch/riscv32/bits/float.h new file mode 100644 index 00000000..719c7908 --- /dev/null +++ b/arch/riscv32/bits/float.h @@ -0,0 +1,16 @@ +#define FLT_EVAL_METHOD 0 + +#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/riscv32/bits/posix.h b/arch/riscv32/bits/posix.h new file mode 100644 index 00000000..8897d37d --- /dev/null +++ b/arch/riscv32/bits/posix.h @@ -0,0 +1,2 @@ +#define _POSIX_V6_ILP32_OFFBIG 1 +#define _POSIX_V7_ILP32_OFFBIG 1 diff --git a/arch/riscv32/bits/reg.h b/arch/riscv32/bits/reg.h new file mode 100644 index 00000000..0192a293 --- /dev/null +++ b/arch/riscv32/bits/reg.h @@ -0,0 +1,2 @@ +#undef __WORDSIZE +#define __WORDSIZE 32 diff --git a/arch/riscv32/bits/setjmp.h b/arch/riscv32/bits/setjmp.h new file mode 100644 index 00000000..51e96276 --- /dev/null +++ b/arch/riscv32/bits/setjmp.h @@ -0,0 +1 @@ +typedef unsigned long long __jmp_buf[19]; diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h new file mode 100644 index 00000000..287367db --- /dev/null +++ b/arch/riscv32/bits/signal.h @@ -0,0 +1,118 @@ +#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 + +typedef unsigned long __riscv_mc_gp_state[32]; + +struct __riscv_mc_f_ext_state { + unsigned int __f[32]; + unsigned int __fcsr; +}; + +struct __riscv_mc_d_ext_state { + unsigned long long __f[32]; + unsigned int __fcsr; +}; + +struct __riscv_mc_q_ext_state { + unsigned long long __f[64] __attribute__((aligned(16))); + unsigned int __fcsr; + unsigned int __reserved[3]; +}; + +union __riscv_mc_fp_state { + struct __riscv_mc_f_ext_state __f; + struct __riscv_mc_d_ext_state __d; + struct __riscv_mc_q_ext_state __q; +}; + +typedef struct mcontext_t { + __riscv_mc_gp_state __gregs; + union __riscv_mc_fp_state __fpregs; +} mcontext_t; + +#if defined(_GNU_SOURCE) +#define REG_PC 0 +#define REG_RA 1 +#define REG_SP 2 +#define REG_TP 4 +#define REG_S0 8 +#define REG_A0 10 +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +typedef unsigned long greg_t; +typedef unsigned long gregset_t[32]; +typedef union __riscv_mc_fp_state fpregset_t; +struct sigcontext { + gregset_t gregs; + fpregset_t fpregs; +}; +#endif + +struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +}; + +typedef struct __ucontext +{ + unsigned long uc_flags; + struct __ucontext *uc_link; + stack_t uc_stack; + sigset_t uc_sigmask; + 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 SIGIO +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED SIGSYS + +#define _NSIG 65 diff --git a/arch/riscv32/bits/stat.h b/arch/riscv32/bits/stat.h new file mode 100644 index 00000000..f6d9e864 --- /dev/null +++ b/arch/riscv32/bits/stat.h @@ -0,0 +1,18 @@ +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; + unsigned long long __pad; + off_t st_size; + blksize_t st_blksize; + int __pad2; + blkcnt_t st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned __unused[2]; +}; diff --git a/arch/riscv32/bits/stdint.h b/arch/riscv32/bits/stdint.h new file mode 100644 index 00000000..d1b27121 --- /dev/null +++ b/arch/riscv32/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/riscv32/bits/syscall.h.in b/arch/riscv32/bits/syscall.h.in new file mode 100644 index 00000000..852d2aaa --- /dev/null +++ b/arch/riscv32/bits/syscall.h.in @@ -0,0 +1,286 @@ +#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_fcntl64 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_truncate64 45 +#define __NR_ftruncate64 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__llseek 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_sendfile64 71 +#define __NR_signalfd4 74 +#define __NR_vmsplice 75 +#define __NR_splice 76 +#define __NR_tee 77 +#define __NR_readlinkat 78 +#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_nanosleep 101 +#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_64 223 +#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 +#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_futex __NR_futex_time64 + +#define __NR_sysriscv __NR_arch_specific_syscall +#define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/riscv32/bits/user.h b/arch/riscv32/bits/user.h new file mode 100644 index 00000000..0d37de0b --- /dev/null +++ b/arch/riscv32/bits/user.h @@ -0,0 +1,6 @@ +#include + +#define ELF_NGREG 32 +#define ELF_NFPREG 33 +typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG]; +typedef union __riscv_mc_fp_state elf_fpregset_t; diff --git a/arch/riscv32/crt_arch.h b/arch/riscv32/crt_arch.h new file mode 100644 index 00000000..6b93fcfd --- /dev/null +++ b/arch/riscv32/crt_arch.h @@ -0,0 +1,19 @@ +__asm__( +".section .sdata,\"aw\"\n" +".text\n" +".global " START "\n" +".type " START ",%function\n" +START ":\n" +".weak __global_pointer$\n" +".hidden __global_pointer$\n" +".option push\n" +".option norelax\n\t" +"lla gp, __global_pointer$\n" +".option pop\n\t" +"mv a0, sp\n" +".weak _DYNAMIC\n" +".hidden _DYNAMIC\n\t" +"lla a1, _DYNAMIC\n\t" +"andi sp, sp, -16\n\t" +"tail " START "_c" +); diff --git a/arch/riscv32/kstat.h b/arch/riscv32/kstat.h new file mode 100644 index 00000000..e69de29b diff --git a/arch/riscv32/pthread_arch.h b/arch/riscv32/pthread_arch.h new file mode 100644 index 00000000..a20d7fba --- /dev/null +++ b/arch/riscv32/pthread_arch.h @@ -0,0 +1,13 @@ +static inline uintptr_t __get_tp() +{ + uintptr_t tp; + __asm__ __volatile__("mv %0, tp" : "=r"(tp)); + return tp; +} + +#define TLS_ABOVE_TP +#define GAP_ABOVE_TP 0 + +#define DTP_OFFSET 0x800 + +#define MC_PC __gregs[0] diff --git a/arch/riscv32/reloc.h b/arch/riscv32/reloc.h new file mode 100644 index 00000000..59d15f17 --- /dev/null +++ b/arch/riscv32/reloc.h @@ -0,0 +1,22 @@ +#if defined __riscv_float_abi_soft +#define RISCV_FP_SUFFIX "-sf" +#elif defined __riscv_float_abi_single +#define RISCV_FP_SUFFIX "-sp" +#elif defined __riscv_float_abi_double +#define RISCV_FP_SUFFIX "" +#endif + +#define LDSO_ARCH "riscv32" RISCV_FP_SUFFIX + +#define TPOFF_K 0 + +#define REL_SYMBOLIC R_RISCV_32 +#define REL_PLT R_RISCV_JUMP_SLOT +#define REL_RELATIVE R_RISCV_RELATIVE +#define REL_COPY R_RISCV_COPY +#define REL_DTPMOD R_RISCV_TLS_DTPMOD32 +#define REL_DTPOFF R_RISCV_TLS_DTPREL32 +#define REL_TPOFF R_RISCV_TLS_TPREL32 + +#define CRTJMP(pc,sp) __asm__ __volatile__( \ + "mv sp, %1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" ) diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h new file mode 100644 index 00000000..c507f15f --- /dev/null +++ b/arch/riscv32/syscall_arch.h @@ -0,0 +1,80 @@ +#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)) + +#define __asm_syscall(...) \ + __asm__ __volatile__ ("ecall\n\t" \ + : "=r"(a0) : __VA_ARGS__ : "memory"); \ + return a0; \ + +static inline long __syscall0(long n) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0"); + __asm_syscall("r"(a7)) +} + +static inline long __syscall1(long n, long a) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + __asm_syscall("r"(a7), "0"(a0)) +} + +static inline long __syscall2(long n, long a, long b) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + __asm_syscall("r"(a7), "0"(a0), "r"(a1)) +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2)) +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3)) +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + register long a4 __asm__("a4") = e; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4)) +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + register long a4 __asm__("a4") = e; + register long a5 __asm__("a5") = f; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)) +} + +#define VDSO_USEFUL +/* We don't have a clock_gettime function. +#define VDSO_CGT_SYM "__vdso_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6" */ + +#define IPC_64 0 From b4f7b2ca350ccaa6f58ecec72ac46b7aef22d1c3 Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 05:45:44 -0400 Subject: [PATCH 281/297] riscv32: add fenv and math These are identical to riscv64. --- src/fenv/riscv32/fenv-sf.c | 3 ++ src/fenv/riscv32/fenv.S | 56 ++++++++++++++++++++++++++++++++++++ src/math/riscv32/copysign.c | 15 ++++++++++ src/math/riscv32/copysignf.c | 15 ++++++++++ src/math/riscv32/fabs.c | 15 ++++++++++ src/math/riscv32/fabsf.c | 15 ++++++++++ src/math/riscv32/fma.c | 15 ++++++++++ src/math/riscv32/fmaf.c | 15 ++++++++++ src/math/riscv32/fmax.c | 15 ++++++++++ src/math/riscv32/fmaxf.c | 15 ++++++++++ src/math/riscv32/fmin.c | 15 ++++++++++ src/math/riscv32/fminf.c | 15 ++++++++++ src/math/riscv32/sqrt.c | 15 ++++++++++ src/math/riscv32/sqrtf.c | 15 ++++++++++ 14 files changed, 239 insertions(+) create mode 100644 src/fenv/riscv32/fenv-sf.c create mode 100644 src/fenv/riscv32/fenv.S create mode 100644 src/math/riscv32/copysign.c create mode 100644 src/math/riscv32/copysignf.c create mode 100644 src/math/riscv32/fabs.c create mode 100644 src/math/riscv32/fabsf.c create mode 100644 src/math/riscv32/fma.c create mode 100644 src/math/riscv32/fmaf.c create mode 100644 src/math/riscv32/fmax.c create mode 100644 src/math/riscv32/fmaxf.c create mode 100644 src/math/riscv32/fmin.c create mode 100644 src/math/riscv32/fminf.c create mode 100644 src/math/riscv32/sqrt.c create mode 100644 src/math/riscv32/sqrtf.c diff --git a/src/fenv/riscv32/fenv-sf.c b/src/fenv/riscv32/fenv-sf.c new file mode 100644 index 00000000..ecd3cb5c --- /dev/null +++ b/src/fenv/riscv32/fenv-sf.c @@ -0,0 +1,3 @@ +#ifndef __riscv_flen +#include "../fenv.c" +#endif diff --git a/src/fenv/riscv32/fenv.S b/src/fenv/riscv32/fenv.S new file mode 100644 index 00000000..0ea78bf9 --- /dev/null +++ b/src/fenv/riscv32/fenv.S @@ -0,0 +1,56 @@ +#ifdef __riscv_flen + +.global feclearexcept +.type feclearexcept, %function +feclearexcept: + csrc fflags, a0 + li a0, 0 + ret + +.global feraiseexcept +.type feraiseexcept, %function +feraiseexcept: + csrs fflags, a0 + li a0, 0 + ret + +.global fetestexcept +.type fetestexcept, %function +fetestexcept: + frflags t0 + and a0, t0, a0 + ret + +.global fegetround +.type fegetround, %function +fegetround: + frrm a0 + ret + +.global __fesetround +.type __fesetround, %function +__fesetround: + fsrm t0, a0 + li a0, 0 + ret + +.global fegetenv +.type fegetenv, %function +fegetenv: + frcsr t0 + sw t0, 0(a0) + li a0, 0 + ret + +.global fesetenv +.type fesetenv, %function +fesetenv: + li t2, -1 + li t1, 0 + beq a0, t2, 1f + lw t1, 0(a0) +1: fscsr t1 + li a0, 0 + ret + +#endif diff --git a/src/math/riscv32/copysign.c b/src/math/riscv32/copysign.c new file mode 100644 index 00000000..c7854178 --- /dev/null +++ b/src/math/riscv32/copysign.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 64 + +double copysign(double x, double y) +{ + __asm__ ("fsgnj.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y)); + return x; +} + +#else + +#include "../copysign.c" + +#endif diff --git a/src/math/riscv32/copysignf.c b/src/math/riscv32/copysignf.c new file mode 100644 index 00000000..a125611a --- /dev/null +++ b/src/math/riscv32/copysignf.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 32 + +float copysignf(float x, float y) +{ + __asm__ ("fsgnj.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y)); + return x; +} + +#else + +#include "../copysignf.c" + +#endif diff --git a/src/math/riscv32/fabs.c b/src/math/riscv32/fabs.c new file mode 100644 index 00000000..5290b6f0 --- /dev/null +++ b/src/math/riscv32/fabs.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 64 + +double fabs(double x) +{ + __asm__ ("fabs.d %0, %1" : "=f"(x) : "f"(x)); + return x; +} + +#else + +#include "../fabs.c" + +#endif diff --git a/src/math/riscv32/fabsf.c b/src/math/riscv32/fabsf.c new file mode 100644 index 00000000..f5032e35 --- /dev/null +++ b/src/math/riscv32/fabsf.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 32 + +float fabsf(float x) +{ + __asm__ ("fabs.s %0, %1" : "=f"(x) : "f"(x)); + return x; +} + +#else + +#include "../fabsf.c" + +#endif diff --git a/src/math/riscv32/fma.c b/src/math/riscv32/fma.c new file mode 100644 index 00000000..99b05713 --- /dev/null +++ b/src/math/riscv32/fma.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 64 + +double fma(double x, double y, double z) +{ + __asm__ ("fmadd.d %0, %1, %2, %3" : "=f"(x) : "f"(x), "f"(y), "f"(z)); + return x; +} + +#else + +#include "../fma.c" + +#endif diff --git a/src/math/riscv32/fmaf.c b/src/math/riscv32/fmaf.c new file mode 100644 index 00000000..f9dc47ed --- /dev/null +++ b/src/math/riscv32/fmaf.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 32 + +float fmaf(float x, float y, float z) +{ + __asm__ ("fmadd.s %0, %1, %2, %3" : "=f"(x) : "f"(x), "f"(y), "f"(z)); + return x; +} + +#else + +#include "../fmaf.c" + +#endif diff --git a/src/math/riscv32/fmax.c b/src/math/riscv32/fmax.c new file mode 100644 index 00000000..023709cd --- /dev/null +++ b/src/math/riscv32/fmax.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 64 + +double fmax(double x, double y) +{ + __asm__ ("fmax.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y)); + return x; +} + +#else + +#include "../fmax.c" + +#endif diff --git a/src/math/riscv32/fmaxf.c b/src/math/riscv32/fmaxf.c new file mode 100644 index 00000000..863d2bd1 --- /dev/null +++ b/src/math/riscv32/fmaxf.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 32 + +float fmaxf(float x, float y) +{ + __asm__ ("fmax.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y)); + return x; +} + +#else + +#include "../fmaxf.c" + +#endif diff --git a/src/math/riscv32/fmin.c b/src/math/riscv32/fmin.c new file mode 100644 index 00000000..a4e3b067 --- /dev/null +++ b/src/math/riscv32/fmin.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 64 + +double fmin(double x, double y) +{ + __asm__ ("fmin.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y)); + return x; +} + +#else + +#include "../fmin.c" + +#endif diff --git a/src/math/riscv32/fminf.c b/src/math/riscv32/fminf.c new file mode 100644 index 00000000..32156e80 --- /dev/null +++ b/src/math/riscv32/fminf.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 32 + +float fminf(float x, float y) +{ + __asm__ ("fmin.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y)); + return x; +} + +#else + +#include "../fminf.c" + +#endif diff --git a/src/math/riscv32/sqrt.c b/src/math/riscv32/sqrt.c new file mode 100644 index 00000000..867a504c --- /dev/null +++ b/src/math/riscv32/sqrt.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 64 + +double sqrt(double x) +{ + __asm__ ("fsqrt.d %0, %1" : "=f"(x) : "f"(x)); + return x; +} + +#else + +#include "../sqrt.c" + +#endif diff --git a/src/math/riscv32/sqrtf.c b/src/math/riscv32/sqrtf.c new file mode 100644 index 00000000..610c2cf8 --- /dev/null +++ b/src/math/riscv32/sqrtf.c @@ -0,0 +1,15 @@ +#include + +#if __riscv_flen >= 32 + +float sqrtf(float x) +{ + __asm__ ("fsqrt.s %0, %1" : "=f"(x) : "f"(x)); + return x; +} + +#else + +#include "../sqrtf.c" + +#endif From 11eee89e14ca7ea2ccc02385c3ab7875fb572d46 Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 05:46:33 -0400 Subject: [PATCH 282/297] riscv32: add dlsym Identical to riscv64. --- src/ldso/riscv32/dlsym.s | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/ldso/riscv32/dlsym.s diff --git a/src/ldso/riscv32/dlsym.s b/src/ldso/riscv32/dlsym.s new file mode 100644 index 00000000..2bafd72d --- /dev/null +++ b/src/ldso/riscv32/dlsym.s @@ -0,0 +1,6 @@ +.global dlsym +.hidden __dlsym +.type dlsym, %function +dlsym: + mv a2, ra + tail __dlsym From c34a8eedff904b7f3d8479bbec0be534e7a01fbb Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 05:54:44 -0400 Subject: [PATCH 283/297] riscv32: add setjmp/longjmp and sigreturn Largely copied from riscv64 but required recalculation of offsets. --- src/setjmp/riscv32/longjmp.S | 42 ++++++++++++++++++++++++++++++++++ src/setjmp/riscv32/setjmp.S | 41 +++++++++++++++++++++++++++++++++ src/signal/riscv32/restore.s | 8 +++++++ src/signal/riscv32/sigsetjmp.s | 23 +++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 src/setjmp/riscv32/longjmp.S create mode 100644 src/setjmp/riscv32/setjmp.S create mode 100644 src/signal/riscv32/restore.s create mode 100644 src/signal/riscv32/sigsetjmp.s diff --git a/src/setjmp/riscv32/longjmp.S b/src/setjmp/riscv32/longjmp.S new file mode 100644 index 00000000..f9cb3318 --- /dev/null +++ b/src/setjmp/riscv32/longjmp.S @@ -0,0 +1,42 @@ +.global __longjmp +.global _longjmp +.global longjmp +.type __longjmp, %function +.type _longjmp, %function +.type longjmp, %function +__longjmp: +_longjmp: +longjmp: + lw s0, 0(a0) + lw s1, 4(a0) + lw s2, 8(a0) + lw s3, 12(a0) + lw s4, 16(a0) + lw s5, 20(a0) + lw s6, 24(a0) + lw s7, 28(a0) + lw s8, 32(a0) + lw s9, 36(a0) + lw s10, 40(a0) + lw s11, 44(a0) + lw sp, 48(a0) + lw ra, 52(a0) + +#ifndef __riscv_float_abi_soft + fld fs0, 56(a0) + fld fs1, 64(a0) + fld fs2, 72(a0) + fld fs3, 80(a0) + fld fs4, 88(a0) + fld fs5, 96(a0) + fld fs6, 104(a0) + fld fs7, 112(a0) + fld fs8, 120(a0) + fld fs9, 128(a0) + fld fs10, 136(a0) + fld fs11, 144(a0) +#endif + + seqz a0, a1 + add a0, a0, a1 + ret diff --git a/src/setjmp/riscv32/setjmp.S b/src/setjmp/riscv32/setjmp.S new file mode 100644 index 00000000..8a75cf55 --- /dev/null +++ b/src/setjmp/riscv32/setjmp.S @@ -0,0 +1,41 @@ +.global __setjmp +.global _setjmp +.global setjmp +.type __setjmp, %function +.type _setjmp, %function +.type setjmp, %function +__setjmp: +_setjmp: +setjmp: + sw s0, 0(a0) + sw s1, 4(a0) + sw s2, 8(a0) + sw s3, 12(a0) + sw s4, 16(a0) + sw s5, 20(a0) + sw s6, 24(a0) + sw s7, 28(a0) + sw s8, 32(a0) + sw s9, 36(a0) + sw s10, 40(a0) + sw s11, 44(a0) + sw sp, 48(a0) + sw ra, 52(a0) + +#ifndef __riscv_float_abi_soft + fsd fs0, 56(a0) + fsd fs1, 64(a0) + fsd fs2, 72(a0) + fsd fs3, 80(a0) + fsd fs4, 88(a0) + fsd fs5, 96(a0) + fsd fs6, 104(a0) + fsd fs7, 112(a0) + fsd fs8, 120(a0) + fsd fs9, 128(a0) + fsd fs10, 136(a0) + fsd fs11, 144(a0) +#endif + + li a0, 0 + ret diff --git a/src/signal/riscv32/restore.s b/src/signal/riscv32/restore.s new file mode 100644 index 00000000..40012c75 --- /dev/null +++ b/src/signal/riscv32/restore.s @@ -0,0 +1,8 @@ +.global __restore +.type __restore, %function +__restore: +.global __restore_rt +.type __restore_rt, %function +__restore_rt: + li a7, 139 # SYS_rt_sigreturn + ecall diff --git a/src/signal/riscv32/sigsetjmp.s b/src/signal/riscv32/sigsetjmp.s new file mode 100644 index 00000000..c1caeab1 --- /dev/null +++ b/src/signal/riscv32/sigsetjmp.s @@ -0,0 +1,23 @@ +.global sigsetjmp +.global __sigsetjmp +.type sigsetjmp, %function +.type __sigsetjmp, %function +sigsetjmp: +__sigsetjmp: + bnez a1, 1f + tail setjmp +1: + + sw ra, 152(a0) + sw s0, 164(a0) + mv s0, a0 + + call setjmp + + mv a1, a0 + mv a0, s0 + lw s0, 164(a0) + lw ra, 152(a0) + +.hidden __sigsetjmp_tail + tail __sigsetjmp_tail From b28c44de8c3131b45588f61569b1711c987ba1c3 Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 05:56:46 -0400 Subject: [PATCH 284/297] riscv32: add thread support Identical to riscv64 except for stack offsets in clone. --- src/thread/riscv32/__set_thread_area.s | 6 +++++ src/thread/riscv32/__unmapself.s | 7 ++++++ src/thread/riscv32/clone.s | 34 ++++++++++++++++++++++++++ src/thread/riscv32/syscall_cp.s | 29 ++++++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 src/thread/riscv32/__set_thread_area.s create mode 100644 src/thread/riscv32/__unmapself.s create mode 100644 src/thread/riscv32/clone.s create mode 100644 src/thread/riscv32/syscall_cp.s diff --git a/src/thread/riscv32/__set_thread_area.s b/src/thread/riscv32/__set_thread_area.s new file mode 100644 index 00000000..828154d2 --- /dev/null +++ b/src/thread/riscv32/__set_thread_area.s @@ -0,0 +1,6 @@ +.global __set_thread_area +.type __set_thread_area, %function +__set_thread_area: + mv tp, a0 + li a0, 0 + ret diff --git a/src/thread/riscv32/__unmapself.s b/src/thread/riscv32/__unmapself.s new file mode 100644 index 00000000..2849119c --- /dev/null +++ b/src/thread/riscv32/__unmapself.s @@ -0,0 +1,7 @@ +.global __unmapself +.type __unmapself, %function +__unmapself: + li a7, 215 # SYS_munmap + ecall + li a7, 93 # SYS_exit + ecall diff --git a/src/thread/riscv32/clone.s b/src/thread/riscv32/clone.s new file mode 100644 index 00000000..3102239d --- /dev/null +++ b/src/thread/riscv32/clone.s @@ -0,0 +1,34 @@ +# __clone(func, stack, flags, arg, ptid, tls, ctid) +# a0, a1, a2, a3, a4, a5, a6 + +# syscall(SYS_clone, flags, stack, ptid, tls, ctid) +# a7 a0, a1, a2, a3, a4 + +.global __clone +.type __clone, %function +__clone: + # Save func and arg to stack + addi a1, a1, -16 + sw a0, 0(a1) + sw a3, 4(a1) + + # Call SYS_clone + mv a0, a2 + mv a2, a4 + mv a3, a5 + mv a4, a6 + li a7, 220 # SYS_clone + ecall + + beqz a0, 1f + # Parent + ret + + # Child +1: lw a1, 0(sp) + lw a0, 4(sp) + jalr a1 + + # Exit + li a7, 93 # SYS_exit + ecall diff --git a/src/thread/riscv32/syscall_cp.s b/src/thread/riscv32/syscall_cp.s new file mode 100644 index 00000000..079d1ba0 --- /dev/null +++ b/src/thread/riscv32/syscall_cp.s @@ -0,0 +1,29 @@ +.global __cp_begin +.hidden __cp_begin +.global __cp_end +.hidden __cp_end +.global __cp_cancel +.hidden __cp_cancel +.hidden __cancel +.global __syscall_cp_asm +.hidden __syscall_cp_asm +.type __syscall_cp_asm, %function +__syscall_cp_asm: +__cp_begin: + lw t0, 0(a0) + bnez t0, __cp_cancel + + mv t0, a1 + mv a0, a2 + mv a1, a3 + mv a2, a4 + mv a3, a5 + mv a4, a6 + mv a5, a7 + lw a6, 0(sp) + mv a7, t0 + ecall +__cp_end: + ret +__cp_cancel: + tail __cancel From 3ea3fcf78a5532e118856846df8adbf3f60ef716 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 29 Feb 2024 11:02:29 -0500 Subject: [PATCH 285/297] riscv32: add sysvipc msg/sem/shm bits despite riscv32 being natively time64, the IPC_TIME64 bit (0x100) is set in IPC_STAT and derived command macros, differentiating their values from the raw command values used to interface with the kernel. this reflects that the kernel ipc structure types are not natively time64, but have broken-down hi/lo fields that cannot be used in-place and require translation, and that the userspace struct types differ from the kernel types (relevant to things like strace). --- arch/riscv32/bits/ipcstat.h | 1 + arch/riscv32/bits/msg.h | 18 ++++++++++++++++++ arch/riscv32/bits/sem.h | 18 ++++++++++++++++++ arch/riscv32/bits/shm.h | 31 +++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 arch/riscv32/bits/ipcstat.h create mode 100644 arch/riscv32/bits/msg.h create mode 100644 arch/riscv32/bits/sem.h create mode 100644 arch/riscv32/bits/shm.h diff --git a/arch/riscv32/bits/ipcstat.h b/arch/riscv32/bits/ipcstat.h new file mode 100644 index 00000000..4f4fcb0c --- /dev/null +++ b/arch/riscv32/bits/ipcstat.h @@ -0,0 +1 @@ +#define IPC_STAT 0x102 diff --git a/arch/riscv32/bits/msg.h b/arch/riscv32/bits/msg.h new file mode 100644 index 00000000..7bbbb2bf --- /dev/null +++ b/arch/riscv32/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/riscv32/bits/sem.h b/arch/riscv32/bits/sem.h new file mode 100644 index 00000000..544e3d2a --- /dev/null +++ b/arch/riscv32/bits/sem.h @@ -0,0 +1,18 @@ +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; +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned short sem_nsems; + char __sem_nsems_pad[sizeof(long)-sizeof(short)]; +#else + char __sem_nsems_pad[sizeof(long)-sizeof(short)]; + unsigned short sem_nsems; +#endif + long __unused3; + long __unused4; + time_t sem_otime; + time_t sem_ctime; +}; diff --git a/arch/riscv32/bits/shm.h b/arch/riscv32/bits/shm.h new file mode 100644 index 00000000..725fb469 --- /dev/null +++ b/arch/riscv32/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; +}; From 8432d16a4664433b2f9a263aee0d7d829129a7bc Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Fri, 30 Oct 2020 12:16:29 -0700 Subject: [PATCH 286/297] riscv32: add new syscall numbers - add mount_setattr from linux v5.12 - add epoll_pwait2 from linux v5.11 - add process_madvise from linux v5.10 - add __NR_faccessat2 from linux v5.8 - add pidfd_getfd and openat2 syscall numbers from linux v5.6 - add clone3 syscall number from linux v5.3 - add process_mrelease from linux v5.15 - add futex_waitv from linux v5.16 - add set_mempolicy_home_node from linux v5.17 - add cachestat from linux v6.4 - add __NR_fchmodat2 from linux v6.6 --- arch/riscv32/bits/syscall.h.in | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/riscv32/bits/syscall.h.in b/arch/riscv32/bits/syscall.h.in index 852d2aaa..9228d840 100644 --- a/arch/riscv32/bits/syscall.h.in +++ b/arch/riscv32/bits/syscall.h.in @@ -279,7 +279,21 @@ #define __NR_fsmount 432 #define __NR_fspick 433 #define __NR_pidfd_open 434 - +#define __NR_clone3 435 +#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_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 #define __NR_futex __NR_futex_time64 #define __NR_sysriscv __NR_arch_specific_syscall From d25f0cccb92ba80e14b078f895d656126efdc77f Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Tue, 25 Jan 2022 20:32:50 -0800 Subject: [PATCH 287/297] riscv: define REG_S1 and REG_S2 These are used by applications to access members of mcontext, and are also defined by other libcs on linux. --- arch/riscv32/bits/signal.h | 2 ++ arch/riscv64/bits/signal.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h index 287367db..271e7da6 100644 --- a/arch/riscv32/bits/signal.h +++ b/arch/riscv32/bits/signal.h @@ -41,7 +41,9 @@ typedef struct mcontext_t { #define REG_SP 2 #define REG_TP 4 #define REG_S0 8 +#define REG_S1 9 #define REG_A0 10 +#define REG_S2 18 #endif #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h index fd6157a3..6a53feb7 100644 --- a/arch/riscv64/bits/signal.h +++ b/arch/riscv64/bits/signal.h @@ -41,7 +41,9 @@ typedef struct mcontext_t { #define REG_SP 2 #define REG_TP 4 #define REG_S0 8 +#define REG_S1 9 #define REG_A0 10 +#define REG_S2 18 #endif #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) From 377c363fb5519a224682692004ecd3703c19df93 Mon Sep 17 00:00:00 2001 From: Stefan O'Rear Date: Thu, 3 Sep 2020 05:26:50 -0400 Subject: [PATCH 288/297] configure: enable riscv32 port --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 940b3eaf..bc9fbe48 100755 --- a/configure +++ b/configure @@ -337,6 +337,7 @@ or1k*) ARCH=or1k ;; powerpc64*|ppc64*) ARCH=powerpc64 ;; powerpc*|ppc*) ARCH=powerpc ;; riscv64*) ARCH=riscv64 ;; +riscv32*) ARCH=riscv32 ;; sh[1-9bel-]*|sh|superh*) ARCH=sh ;; s390x*) ARCH=s390x ;; unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;; @@ -727,7 +728,7 @@ trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64" fi -if test "$ARCH" = "riscv64" ; then +if test "$ARCH" = "riscv64" -o "$ARCH" = "riscv32" ; then trycppif __riscv_float_abi_soft "$t" && SUBARCH=${SUBARCH}-sf trycppif __riscv_float_abi_single "$t" && SUBARCH=${SUBARCH}-sp fi From 13cd64af31f9d48f65f9d4b41d7f55266798ee0d Mon Sep 17 00:00:00 2001 From: wanghongliang Date: Mon, 26 Feb 2024 02:17:17 +0800 Subject: [PATCH 289/297] loongarch64: remove ptrace.h macros --- arch/loongarch64/bits/ptrace.h | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 arch/loongarch64/bits/ptrace.h diff --git a/arch/loongarch64/bits/ptrace.h b/arch/loongarch64/bits/ptrace.h deleted file mode 100644 index dce2fa51..00000000 --- a/arch/loongarch64/bits/ptrace.h +++ /dev/null @@ -1,4 +0,0 @@ -#define PTRACE_GET_THREAD_AREA 25 -#define PTRACE_SET_THREAD_AREA 26 -#define PTRACE_GET_WATCH_REGS 0xd0 -#define PTRACE_SET_WATCH_REGS 0xd1 From 8d852cdacd7896723098096e2dfc4060db84f0cf Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 29 Feb 2024 17:32:27 -0500 Subject: [PATCH 290/297] loongarch64: remove getrlimit/setrlimit syscall numbers these are not supported by the kernel for new archs; prlimit64 replaces them. --- arch/loongarch64/bits/syscall.h.in | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/loongarch64/bits/syscall.h.in b/arch/loongarch64/bits/syscall.h.in index 0980e533..bd3453e3 100644 --- a/arch/loongarch64/bits/syscall.h.in +++ b/arch/loongarch64/bits/syscall.h.in @@ -158,8 +158,6 @@ #define __NR_uname 160 #define __NR_sethostname 161 #define __NR_setdomainname 162 -#define __NR_getrlimit 163 -#define __NR_setrlimit 164 #define __NR_getrusage 165 #define __NR_umask 166 #define __NR_prctl 167 From 8d9d266573aced978c812973a2ae12b998250898 Mon Sep 17 00:00:00 2001 From: wanghongliang Date: Wed, 28 Feb 2024 06:38:08 +0800 Subject: [PATCH 291/297] loongarch64: add new syscall numbers --- arch/loongarch64/bits/syscall.h.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/loongarch64/bits/syscall.h.in b/arch/loongarch64/bits/syscall.h.in index bd3453e3..2afb4ea1 100644 --- a/arch/loongarch64/bits/syscall.h.in +++ b/arch/loongarch64/bits/syscall.h.in @@ -290,6 +290,21 @@ #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 +#define __NR_map_shadow_stack 453 +#define __NR_futex_wake 454 +#define __NR_futex_wait 455 +#define __NR_futex_requeue 456 #define __NR_fcntl __NR3264_fcntl #define __NR_statfs __NR3264_statfs #define __NR_fstatfs __NR3264_fstatfs From e5aa498451c85c74d924ba1d7b03a87a1774d1ed Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 29 Feb 2024 19:23:03 -0500 Subject: [PATCH 292/297] update INSTALL file archs list with riscv32, loongarch64 additions --- INSTALL | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index c583691d..ddbbbb2f 100644 --- a/INSTALL +++ b/INSTALL @@ -97,11 +97,16 @@ and ABI combinations: * OpenRISC 1000 (or1k) -* RISC-V 64 +* RISC-V + * 32-bit and 64-bit * Little endian * Hard, soft, and hard-single/soft-double floating point ABIs * Standard ELF; no shared-text NOMMU support +* LoongArch + * 64-bit ISA + * Hard, soft, and hard-single/soft-double floating point ABIs + Build and Installation Procedure From f5dba42f361c2c985dbe7d1087077d57fac561ba Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 29 Feb 2024 20:40:03 -0500 Subject: [PATCH 293/297] iconv: add cp932 as an alias for shift_jis --- src/locale/iconv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locale/iconv.c b/src/locale/iconv.c index 3047c27b..175def1c 100644 --- a/src/locale/iconv.c +++ b/src/locale/iconv.c @@ -49,7 +49,7 @@ static const unsigned char charmaps[] = "ucs4\0utf32\0\0\313" "ucs2\0\0\314" "eucjp\0\0\320" -"shiftjis\0sjis\0\0\321" +"shiftjis\0sjis\0cp932\0\0\321" "iso2022jp\0\0\322" "gb18030\0\0\330" "gbk\0\0\331" From 0784374d561435f7c787a555aeab8ede699ed298 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 29 Feb 2024 21:07:33 -0500 Subject: [PATCH 294/297] release 1.2.5 --- VERSION | 2 +- WHATSNEW | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e8ea05db..c813fe11 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.4 +1.2.5 diff --git a/WHATSNEW b/WHATSNEW index c5c8c9f4..7bd90728 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -2396,3 +2396,45 @@ arch-specific bugs fixed: - sigaction signal mask was bogus on or1k, microblaze, mips, and riscv - powerpc-sf longjmp asm clobbered value argument - or1k poll function passed timeout to syscall in wrong form + + + +1.2.5 release notes + +new features: +- statx function (linux extension; via syscall and fallback using fstatat) +- clone function is now usable and gives _Fork-like consistency in child +- statvfs now provides f_type result +- preadv2 and pwritev2 (linux extension) syscall wrappers +- riscv64 TLSDESC support + +new ports: +- loongarch64 +- riscv32 + +compatibility: +- DNS resolver can now handle answers with long CNAME chains +- string.h no longer provides (C23-incompat) non-prototype decl of basename +- fstatat statx backend now matches stat syscall non-automounting behavior +- mntent interfaces now handle escaped whitespace in paths/options + +standards updates: +- printf %lc of nul wchar now produces output +- snprintf and swprintf no longer fail on n > INT_MAX +- ppoll is now exposed in default feature profile + +bugs fixed: +- some long DNS answers were wrongly rejected despite new TCP support +- glob could wrongly return GLOB_NOMATCH if aborted before any matches +- multithreaded set*id could malfunction from thread sequencing logic bug +- certain use of threads after fork could deadlock thread-list lock +- posix_spawn child could deadlock in race with async parent death +- mbrtowc return value was wrong if argument n exceeded UINT_MAX +- 80-bit extended acoshl and powl got some corner cases wrong +- syslog incorrectly generated localized timestamps + +arch-specific bugs fixed: +- arm (32-bit) TLSDESC malfunctioned due to addends being processed wrong +- riscv64 icache flush operation was non-functional +- sh sigsetjmp failed to properly restore call-saved register r8 on return +- sh dlsym RTLD_NEXT did not identify calling module correctly From 841c8770ee9e90ca7871131f3ae9795d07ac809f Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 22 Mar 2024 10:21:49 -0700 Subject: [PATCH 295/297] Update to emscripten 3.1.56 --- arch/emscripten/bits/alltypes.h | 2 ++ arch/emscripten/bits/limits.h | 11 ----------- include/features.h | 7 +++++++ src/conf/sysconf.c | 4 +++- src/fcntl/fcntl.c | 7 +++++++ src/internal/pthread_impl.h | 15 +++++++++++---- src/network/res_msend.c | 4 ++++ src/stat/fstatat.c | 1 + src/thread/__timedwait.c | 13 +++++++++---- src/thread/pthread_cancel.c | 11 +++++++++++ src/thread/pthread_detach.c | 10 ++++++++++ src/thread/pthread_join.c | 5 ++--- 12 files changed, 67 insertions(+), 23 deletions(-) diff --git a/arch/emscripten/bits/alltypes.h b/arch/emscripten/bits/alltypes.h index d56dedad..148baddd 100644 --- a/arch/emscripten/bits/alltypes.h +++ b/arch/emscripten/bits/alltypes.h @@ -4,6 +4,8 @@ #define __BYTE_ORDER __LITTLE_ENDIAN +#define __LONG_MAX __LONG_MAX__ + #define _Addr __PTRDIFF_TYPE__ #define _Int64 __INT64_TYPE__ #define _Reg __PTRDIFF_TYPE__ diff --git a/arch/emscripten/bits/limits.h b/arch/emscripten/bits/limits.h index 338b2f2e..7a09fdc1 100644 --- a/arch/emscripten/bits/limits.h +++ b/arch/emscripten/bits/limits.h @@ -1,12 +1 @@ -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #define PAGE_SIZE 65536 -#define LONG_BIT 32 -#endif - -#if __LP64__ -#define LONG_MAX 0x7fffffffffffffffL -#else -#define LONG_MAX 0x7fffffffL -#endif -#define LLONG_MAX 0x7fffffffffffffffLL diff --git a/include/features.h b/include/features.h index 85cfb72a..952ffd96 100644 --- a/include/features.h +++ b/include/features.h @@ -16,6 +16,13 @@ #define _XOPEN_SOURCE 700 #endif +#if defined(__EMSCRIPTEN__) && defined(_GNU_SOURCE) +// In emscripten the LFS functions are kept around when _GNU_SOURCE is +// defined, for increased compatabiliy. This is also what glibc does. +#undef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE 1 +#endif + #if __STDC_VERSION__ >= 199901L #define __restrict restrict #elif !defined(__GNUC__) diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index 8d1d3acd..c300a834 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -4,7 +4,9 @@ #include #include #include +#ifndef __EMSCRIPTEN__ #include +#endif #include "syscall.h" #include "libc.h" @@ -230,7 +232,6 @@ long sysconf(int name) mem *= si.mem_unit; mem /= PAGE_SIZE; return (mem > LONG_MAX) ? LONG_MAX : mem; -#endif case JT_MINSIGSTKSZ & 255: case JT_SIGSTKSZ & 255: ; long val = __getauxval(AT_MINSIGSTKSZ); @@ -238,6 +239,7 @@ long sysconf(int name) if (values[name] == JT_SIGSTKSZ) val += SIGSTKSZ - MINSIGSTKSZ; return val; +#endif case JT_ZERO & 255: return 0; } diff --git a/src/fcntl/fcntl.c b/src/fcntl/fcntl.c index 6c43bdaa..1bce903d 100644 --- a/src/fcntl/fcntl.c +++ b/src/fcntl/fcntl.c @@ -24,7 +24,14 @@ int fcntl(int fd, int cmd, ...) if (cmd == F_GETOWN) { struct f_owner_ex ex; int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex); +#ifdef __EMSCRIPTEN__ + // XXX Emscripten: Mirror the behaviour/limitation of glibc which + // will misinterpret negative PIDs in range of -1 to -4095 as being + // errno values. + if (ret == -EINVAL) ret = __syscall(SYS_fcntl, fd, cmd, (void *)arg); +#else if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, (void *)arg); +#endif if (ret) return __syscall_ret(ret); return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid; } diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 740fe212..7f3a5483 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -97,12 +97,19 @@ struct pthread { // wait until it reaches 0, at which point the mailbox is considered // closed and no further messages will be enqueued. _Atomic int mailbox_refcount; - // Whether the thread has executed a `waitAsync` on this pthread struct - // and can be notified of new mailbox messages via `Atomics.notify`. - // Otherwise the notification has to fall back to the postMessage path. + // Whether the thread has executed an `Atomics.waitAsync` on this + // pthread struct and can be notified of new mailbox messages via + // `Atomics.notify`. Otherwise, such as when the environment does not + // implement `Atomics.waitAsync` or when the thread has not had a chance + // to initialize itself yet, the notification has to fall back to the + // postMessage path. Once this becomes true, it remains true so we never + // fall back to postMessage unnecessarily. _Atomic int waiting_async; #endif -#if _REENTRANT +#ifdef EMSCRIPTEN_DYNAMIC_LINKING + // When dynamic linking is enabled, threads use this to facilitate the + // synchronization of loaded code between threads. + // See emscripten_futex_wait.c. _Atomic char sleeping; #endif }; diff --git a/src/network/res_msend.c b/src/network/res_msend.c index babd0921..10994280 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -307,7 +307,11 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, * Immediately close TCP socket so as not to consume * resources we no longer need. */ alens[i] = alen; +#ifdef __EMSCRIPTEN__ + __wasi_fd_close((intptr_t)pfd[i].fd); +#else __syscall(SYS_close, pfd[i].fd); +#endif pfd[i].fd = -1; } } diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index a3b9594b..59e45101 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -139,6 +139,7 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric return 0; } #endif +#endif int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) { diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index 6c8284f6..eb1e498b 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -69,13 +69,18 @@ int __timedwait_cp(volatile int *addr, int val, // which may be either done by the user of __timedwait() function. if (is_runtime_thread || pthread_self()->canceldisable != PTHREAD_CANCEL_DISABLE || - pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) { + pthread_self()->cancelasync) { double sleepUntilTime = emscripten_get_now() + msecsToSleep; do { if (pthread_self()->cancel) { - // Emscripten-specific return value: The wait was canceled by user calling - // pthread_cancel() for this thread, and the caller needs to cooperatively - // cancel execution. + // The thread was canceled by pthread_cancel(). + // In the case of cancelasync or PTHREAD_CANCEL_ENABLE we can just call + // __pthread_testcancel(), which won't return at all. + __pthread_testcancel(); + // If __pthread_testcancel does return here it means that canceldisable + // must be set to PTHREAD_CANCEL_MASKED. This appear to mean "return + // ECANCELLED to the caller". See pthread_cond_timedwait.c for the only + // use of this that I could find. return ECANCELED; } msecsToSleep = sleepUntilTime - emscripten_get_now(); diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c index ef9ca61d..91c779ed 100644 --- a/src/thread/pthread_cancel.c +++ b/src/thread/pthread_cancel.c @@ -8,7 +8,13 @@ hidden long __cancel(), __syscall_cp_asm(), __syscall_cp_c(); long __cancel() { pthread_t self = __pthread_self(); +#ifdef __EMSCRIPTEN__ + // Emscripten doesn't have actual async cancelation so we make a best effort + // by cancelling cooperatively when self->cancelasync is set. if (self->canceldisable == PTHREAD_CANCEL_ENABLE || self->cancelasync) +#else + if (self->canceldisable == PTHREAD_CANCEL_ENABLE) +#endif pthread_exit(PTHREAD_CANCELED); self->canceldisable = PTHREAD_CANCEL_DISABLE; return -ECANCELED; @@ -77,7 +83,12 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx) void __testcancel() { pthread_t self = __pthread_self(); +#ifdef __EMSCRIPTEN__ + // See comment above about cancelasync under emscripten. + if (self->cancel && (self->cancelasync || !self->canceldisable)) +#else if (self->cancel && !self->canceldisable) +#endif __cancel(); } diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c index 598d2ef8..c25882cc 100644 --- a/src/thread/pthread_detach.c +++ b/src/thread/pthread_detach.c @@ -11,7 +11,17 @@ static int __pthread_detach(pthread_t t) #endif /* If the cas fails, detach state is either already-detached * or exiting/exited, and pthread_join will trap or cleanup. */ +#ifdef __EMSCRIPTEN__ + int old_state = a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED); + if (old_state != DT_JOINABLE) { + // Even though the man page says this is undefined behaviour to attempt to + // detach an already-detached thread we have several tests in the posixtest + // suite that depend on this (pthread_join.c) + if (old_state == DT_DETACHED) + return EINVAL; +#else if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE) { +#endif int cs; __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); __pthread_join(t, 0); diff --git a/src/thread/pthread_join.c b/src/thread/pthread_join.c index d68d149c..d209324a 100644 --- a/src/thread/pthread_join.c +++ b/src/thread/pthread_join.c @@ -29,9 +29,8 @@ static int __pthread_timedjoin_np(pthread_t t, void **res, const struct timespec // This also handle cases where the thread becomes detached // *during* the join. if (state >= DT_DETACHED) { - // Even though the man page says this is undefined - // behaviour we ave several tests in the posixtest suite - // that depend on this. + // Even though the man page says this is undefined behaviour we have + // several tests in the posixtest suite that depend on this. r = EINVAL; break; } From 21b82592770f6441cc1c4b2c4ddb1c18a0f6c14b Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 16 Apr 2024 12:50:31 -0700 Subject: [PATCH 296/297] Update to emscripten 3.1.57 --- arch/emscripten/bits/syscall.h | 2 +- arch/emscripten/syscall_arch.h | 2 +- include/limits.h | 7 +++++++ src/stat/fchmodat.c | 6 ++++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/emscripten/bits/syscall.h b/arch/emscripten/bits/syscall.h index 2522f9da..710fcd1f 100644 --- a/arch/emscripten/bits/syscall.h +++ b/arch/emscripten/bits/syscall.h @@ -68,7 +68,7 @@ #define SYS_linkat __syscall_linkat #define SYS_symlinkat __syscall_symlinkat #define SYS_readlinkat __syscall_readlinkat -#define SYS_fchmodat __syscall_fchmodat +#define SYS_fchmodat2 __syscall_fchmodat2 #define SYS_faccessat __syscall_faccessat #define SYS_pselect6 __syscall_pselect6 #define SYS_utimensat __syscall_utimensat diff --git a/arch/emscripten/syscall_arch.h b/arch/emscripten/syscall_arch.h index b72e1f73..b926704c 100644 --- a/arch/emscripten/syscall_arch.h +++ b/arch/emscripten/syscall_arch.h @@ -92,7 +92,7 @@ int __syscall_renameat(int olddirfd, intptr_t oldpath, int newdirfd, intptr_t ne int __syscall_linkat(int olddirfd, intptr_t oldpath, int newdirfd, intptr_t newpath, int flags); int __syscall_symlinkat(intptr_t target, int newdirfd, intptr_t linkpath); int __syscall_readlinkat(int dirfd, intptr_t path, intptr_t buf, size_t bufsize); -int __syscall_fchmodat(int dirfd, intptr_t path, int mode, ...); +int __syscall_fchmodat2(int dirfd, intptr_t path, int mode, int flags); int __syscall_faccessat(int dirfd, intptr_t path, int amode, int flags); int __syscall_pselect6(int nfds, intptr_t readfds, intptr_t writefds, intptr_t exceptfds, intptr_t timeout, intptr_t sigmaks); int __syscall_utimensat(int dirfd, intptr_t path, intptr_t times, int flags); diff --git a/include/limits.h b/include/limits.h index 53a27b9d..a1365cfc 100644 --- a/include/limits.h +++ b/include/limits.h @@ -51,7 +51,14 @@ #define SYMLOOP_MAX 40 #define WORD_BIT 32 #define SSIZE_MAX LONG_MAX +#ifdef __EMSCRIPTEN__ +// We depend on the JS API to reteive the local name for the current +// timezone and this can sometimes exceed 6 chars. For example: +// TZ='Asia/Kathmandu' yields 'GMT+5:45'. +#define TZNAME_MAX 16 +#else #define TZNAME_MAX 6 +#endif #define TTY_NAME_MAX 32 #define HOST_NAME_MAX 255 diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c index 33671f4f..4a4539f0 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -5,7 +5,9 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) { +#ifndef __EMSCRIPTEN__ if (!flag) return syscall(SYS_fchmodat, fd, path, mode); +#endif int ret = __syscall(SYS_fchmodat2, fd, path, mode, flag); if (ret != -ENOSYS) return __syscall_ret(ret); @@ -32,7 +34,11 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) ret = stat(proc, &st); if (!ret) { if (S_ISLNK(st.st_mode)) ret = __syscall_ret(-EOPNOTSUPP); +#ifdef __EMSCRIPTEN__ + else ret = syscall(SYS_fchmodat2, AT_FDCWD, proc, mode, 0); +#else else ret = syscall(SYS_fchmodat, AT_FDCWD, proc, mode); +#endif } #ifdef __EMSCRIPTEN__ From 05efe113974ded12a72b1899e64be10b471f76a9 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 17 Jun 2025 13:51:41 -0700 Subject: [PATCH 297/297] Update to emscripten 4.0.10 (#2) This change is the result of running ./system/lib/push_musl_changes.py --- arch/emscripten/bits/syscall.h | 3 --- arch/emscripten/syscall_arch.h | 3 --- src/env/__stack_chk_fail.c | 5 ++++ src/errno/__errno_location.c | 21 +++++++--------- src/errno/strerror.c | 12 +++++++++ src/exit/abort.c | 13 ++++++++++ src/fcntl/fcntl.c | 14 ++++++++--- src/internal/locale_impl.h | 8 ++++++ src/linux/statx.c | 4 +++ src/locale/iconv.c | 6 ++++- src/locale/locale_map.c | 2 ++ src/misc/getentropy.c | 8 ++++++ src/misc/getopt.c | 2 +- src/stdio/__stdio_close.c | 2 +- src/thread/pthread_join.c | 2 +- src/time/__tz.c | 45 ++++++++++++++++++++++++++++++---- src/time/clock_getres.c | 15 ++++++++++++ src/time/strftime.c | 6 +++++ 18 files changed, 140 insertions(+), 31 deletions(-) diff --git a/arch/emscripten/bits/syscall.h b/arch/emscripten/bits/syscall.h index 710fcd1f..32f84e9f 100644 --- a/arch/emscripten/bits/syscall.h +++ b/arch/emscripten/bits/syscall.h @@ -12,9 +12,7 @@ #define SYS_umask __syscall_umask #define SYS_getppid __syscall_getppid #define SYS_setsid __syscall_setsid -#define SYS_setrlimit __syscall_setrlimit #define SYS_getrusage __syscall_getrusage -#define SYS_symlink __syscall_symlink #define SYS_munmap __syscall_munmap #define SYS_fchmod __syscall_fchmod #define SYS_getpriority __syscall_getpriority @@ -36,7 +34,6 @@ #define SYS_mremap __syscall_mremap #define SYS_poll __syscall_poll #define SYS_getcwd __syscall_getcwd -#define SYS_ugetrlimit __syscall_ugetrlimit #define SYS_mmap2 __syscall_mmap2 #define SYS_truncate64 __syscall_truncate64 #define SYS_ftruncate64 __syscall_ftruncate64 diff --git a/arch/emscripten/syscall_arch.h b/arch/emscripten/syscall_arch.h index b926704c..8076adad 100644 --- a/arch/emscripten/syscall_arch.h +++ b/arch/emscripten/syscall_arch.h @@ -29,9 +29,7 @@ int __syscall_umask(int mask); int __syscall_getppid(void); int __syscall_getpgrp(void); int __syscall_setsid(void); -int __syscall_setrlimit(int resource, intptr_t limit); int __syscall_getrusage(int who, intptr_t usage); -int __syscall_symlink(intptr_t target, intptr_t linkpath); int __syscall_munmap(intptr_t addr, size_t len); int __syscall_fchmod(int fd, int mode); int __syscall_getpriority(int which, int who); @@ -54,7 +52,6 @@ int __syscall_munlockall(void); int __syscall_mremap(intptr_t old_addr, size_t old_size, size_t new_size, int flags, intptr_t new_addr); int __syscall_poll(intptr_t fds, int nfds, int timeout); int __syscall_getcwd(intptr_t buf, size_t size); -int __syscall_ugetrlimit(int resource, intptr_t rlim); intptr_t __syscall_mmap2(intptr_t addr, size_t len, int prot, int flags, int fd, off_t offset); int __syscall_truncate64(intptr_t path, off_t length); int __syscall_ftruncate64(int fd, off_t length); diff --git a/src/env/__stack_chk_fail.c b/src/env/__stack_chk_fail.c index e5352602..94d8e1d4 100644 --- a/src/env/__stack_chk_fail.c +++ b/src/env/__stack_chk_fail.c @@ -23,6 +23,11 @@ void __init_ssp(void *entropy) void __stack_chk_fail(void) { +#if defined(__EMSCRIPTEN__) && !defined(NDEBUG) + // Report the reason for the crash, at least in debug builds. + // This is the same message that glibc outputs (even in release builds). + emscripten_err("*** stack smashing detected ***"); +#endif a_crash(); } diff --git a/src/errno/__errno_location.c b/src/errno/__errno_location.c index dc153bce..05f55d9e 100644 --- a/src/errno/__errno_location.c +++ b/src/errno/__errno_location.c @@ -1,22 +1,19 @@ #include #include "pthread_impl.h" -#if __EMSCRIPTEN_PTHREADS__ -// for pthreads, use the proper location on the thread info, so each -// thread has its own errno -int *__errno_location(void) -{ - return &__pthread_self()->errno_val; -} -#else -// for single-threaded mode, avoid linking in pthreads support code -// just for this -static int __errno_storage = 0; +#if __EMSCRIPTEN__ +// For emscripten we use TLS here instead of `__pthread_self`, so that in single +// threaded builds this gets lowered away to normal global variable. +static _Thread_local int __errno_storage = 0; +#endif int *__errno_location(void) { +#if __EMSCRIPTEN__ return &__errno_storage; -} +#else + return &__pthread_self()->errno_val; #endif +} weak_alias(__errno_location, ___errno_location); diff --git a/src/errno/strerror.c b/src/errno/strerror.c index 7f926432..8ee4ac2f 100644 --- a/src/errno/strerror.c +++ b/src/errno/strerror.c @@ -36,12 +36,24 @@ char *__strerror_l(int e, locale_t loc) #endif if (e >= sizeof errmsgidx / sizeof *errmsgidx) e = 0; s = (char *)&errmsgstr + errmsgidx[e]; +#ifdef __EMSCRIPTEN__ + // strerror is a (debug) dependency of many emscripten syscalls which mean it + // must be excluded from LTO, along with all of its dependencies. + // In order to limit the transitive dependencies we disable localization of + // rrno messages here. + return (char *)s; +#else return (char *)LCTRANS(s, LC_MESSAGES, loc); +#endif } char *strerror(int e) { +#ifdef __EMSCRIPTEN__ + return __strerror_l(e, NULL); +#else return __strerror_l(e, CURRENT_LOCALE); +#endif } weak_alias(__strerror_l, strerror_l); diff --git a/src/exit/abort.c b/src/exit/abort.c index f21f458e..a6427d51 100644 --- a/src/exit/abort.c +++ b/src/exit/abort.c @@ -6,8 +6,20 @@ #include "lock.h" #include "ksigaction.h" +#if __EMSCRIPTEN__ +#include "emscripten_internal.h" +#endif + _Noreturn void abort(void) { +#if __EMSCRIPTEN__ + /* In emscripten we call out to JS to perform the actual abort where it can + * produce a nice error. + * Note that the JS library function is not called `abort` to avoid conflict + * with the JavaScript abort helper (which takes a JS string as an argument + * and is itself used to implement `_abort_js`) */ + _abort_js(); +#else raise(SIGABRT); /* If there was a SIGABRT handler installed and it returned, or if @@ -27,4 +39,5 @@ _Noreturn void abort(void) a_crash(); raise(SIGKILL); _Exit(127); +#endif } diff --git a/src/fcntl/fcntl.c b/src/fcntl/fcntl.c index 1bce903d..dbc913ba 100644 --- a/src/fcntl/fcntl.c +++ b/src/fcntl/fcntl.c @@ -3,22 +3,28 @@ #include #include #include "syscall.h" +#include -#ifdef __EMSCRIPTEN__ -__attribute__((no_sanitize("address"))) -#endif int fcntl(int fd, int cmd, ...) { - unsigned long arg; +#ifdef __EMSCRIPTEN__ // XXX Emscripten: According to the va_arg man page it is undefined behaviour to // read arguments that are not passed. This can lead to a false positive // in SAFE_HEAP, so avoid it. + unsigned long arg = 0; if (cmd != F_GETFL && cmd != F_GETFD && cmd != F_GETOWN) { va_list ap; va_start(ap, cmd); arg = va_arg(ap, unsigned long); va_end(ap); } +#else + unsigned long arg; + va_list ap; + va_start(ap, cmd); + arg = va_arg(ap, unsigned long); + va_end(ap); +#endif if (cmd == F_SETFL) arg |= O_LARGEFILE; if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, (void *)arg); if (cmd == F_GETOWN) { diff --git a/src/internal/locale_impl.h b/src/internal/locale_impl.h index 4431a92e..ed60d160 100644 --- a/src/internal/locale_impl.h +++ b/src/internal/locale_impl.h @@ -31,8 +31,16 @@ hidden char *__gettextdomain(void); #define LOC_MAP_FAILED ((const struct __locale_map *)-1) +#if __EMSCRIPTEN__ +// Disable message translation completely under emscripten since we don't +// support loading any actual locale data, and even looking up the current +// local via CURRENT_LOCALE via TLS is not free. +#define LCTRANS(msg, lc, loc) msg +#define LCTRANS_CUR(msg) msg +#else #define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)]) #define LCTRANS_CUR(msg) __lctrans_cur(msg) +#endif #define C_LOCALE ((locale_t)&__c_locale) #define UTF8_LOCALE ((locale_t)&__c_dot_utf8_locale) diff --git a/src/linux/statx.c b/src/linux/statx.c index 4616bff4..0245e346 100644 --- a/src/linux/statx.c +++ b/src/linux/statx.c @@ -7,6 +7,9 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct statx *restrict stx) { +#ifdef __EMSCRIPTEN__ + int ret; +#else int ret = __syscall(SYS_statx, dirfd, path, flags, mask, stx); #ifndef SYS_fstatat @@ -14,6 +17,7 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct #endif if (ret != -ENOSYS) return __syscall_ret(ret); +#endif struct stat st; ret = fstatat(dirfd, path, &st, flags); diff --git a/src/locale/iconv.c b/src/locale/iconv.c index 175def1c..3dd9fd90 100644 --- a/src/locale/iconv.c +++ b/src/locale/iconv.c @@ -495,7 +495,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (c >= 93 || d >= 94) { c += (0xa1-0x81); d += 0xa1; - if (c >= 93 || c>=0xc6-0x81 && d>0x52) + if (c > 0xc6-0x81 || c==0xc6-0x81 && d>0x52) goto ilseq; if (d-'A'<26) d = d-'A'; else if (d-'a'<26) d = d-'a'+26; @@ -538,6 +538,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (*outb < k) goto toobig; memcpy(*out, tmp, k); } else k = wctomb_utf8(*out, c); + /* This failure condition should be unreachable, but + * is included to prevent decoder bugs from translating + * into advancement outside the output buffer range. */ + if (k>4) goto ilseq; *out += k; *outb -= k; break; diff --git a/src/locale/locale_map.c b/src/locale/locale_map.c index 5b693565..d696066c 100644 --- a/src/locale/locale_map.c +++ b/src/locale/locale_map.c @@ -12,12 +12,14 @@ #define realloc undef #define free undef +#ifndef __EMSCRIPTEN__ const char *__lctrans_impl(const char *msg, const struct __locale_map *lm) { const char *trans = 0; if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg); return trans ? trans : msg; } +#endif static const char envvars[][12] = { "LC_CTYPE", diff --git a/src/misc/getentropy.c b/src/misc/getentropy.c index 651ea95f..f5204186 100644 --- a/src/misc/getentropy.c +++ b/src/misc/getentropy.c @@ -4,6 +4,10 @@ #include #include +#ifdef __EMSCRIPTEN__ +#include +#endif + int getentropy(void *buffer, size_t len) { int cs, ret = 0; @@ -16,6 +20,9 @@ int getentropy(void *buffer, size_t len) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); +#ifdef __EMSCRIPTEN__ + ret = __wasi_syscall_ret(__wasi_random_get(buffer, len)); +#else while (len) { ret = getrandom(pos, len, 0); if (ret < 0) { @@ -26,6 +33,7 @@ int getentropy(void *buffer, size_t len) len -= ret; ret = 0; } +#endif pthread_setcancelstate(cs, 0); diff --git a/src/misc/getopt.c b/src/misc/getopt.c index b02b81c3..b08abbc9 100644 --- a/src/misc/getopt.c +++ b/src/misc/getopt.c @@ -16,7 +16,7 @@ weak_alias(__optreset, optreset); void __getopt_msg(const char *a, const char *b, const char *c, size_t l) { FILE *f = stderr; - b = __lctrans_cur(b); + b = LCTRANS_CUR(b); /* XXX EMSCRIPTEN: Use macro version here */ FLOCK(f); fputs(a, f)>=0 && fwrite(b, strlen(b), 1, f) diff --git a/src/stdio/__stdio_close.c b/src/stdio/__stdio_close.c index ee1dbacf..7618de93 100644 --- a/src/stdio/__stdio_close.c +++ b/src/stdio/__stdio_close.c @@ -11,7 +11,7 @@ weak_alias(dummy, __aio_close); int __stdio_close(FILE *f) { #ifdef __EMSCRIPTEN__ - return __wasi_fd_close(__aio_close(f->fd)); + return __wasi_syscall_ret(__wasi_fd_close(__aio_close(f->fd))); #else return syscall(SYS_close, __aio_close(f->fd)); #endif diff --git a/src/thread/pthread_join.c b/src/thread/pthread_join.c index d209324a..a5d539b6 100644 --- a/src/thread/pthread_join.c +++ b/src/thread/pthread_join.c @@ -45,7 +45,7 @@ static int __pthread_timedjoin_np(pthread_t t, void **res, const struct timespec if (res) *res = t->result; #ifdef __EMSCRIPTEN__ // Thread was exited during this call, be sure to clean it up. - if (state == DT_EXITED) __emscripten_thread_cleanup(t); + if (state == DT_EXITED) _emscripten_thread_cleanup(t); #else // XXX Emscripten map_base unused if (t->map_base) __munmap(t->map_base, t->map_size); #endif diff --git a/src/time/__tz.c b/src/time/__tz.c index c34b3eb7..f6c4e5ad 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -9,14 +9,24 @@ #include "lock.h" #include "fork_impl.h" +#ifdef __EMSCRIPTEN__ +#include +#include +#include "emscripten_internal.h" +#endif + +#if defined(__EMSCRIPTEN__) && !defined(EMSCRIPTEN_STANDALONE_WASM) +#define USE_EXTERNAL_ZONEINFO +#endif + #define malloc __libc_malloc #define calloc undef #define realloc undef #define free undef -long __timezone = 0; -int __daylight = 0; -char *__tzname[2] = { 0, 0 }; +weak long __timezone = 0; +weak int __daylight = 0; +weak char *__tzname[2] = { 0, 0 }; weak_alias(__timezone, timezone); weak_alias(__daylight, daylight); @@ -24,21 +34,26 @@ weak_alias(__tzname, tzname); static char std_name[TZNAME_MAX+1]; static char dst_name[TZNAME_MAX+1]; -const char __utc[] = "UTC"; +weak const char __utc[] = "UTC"; static int dst_off; static int r0[5], r1[5]; +#ifndef USE_EXTERNAL_ZONEINFO static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end; static size_t map_size; +#endif static char old_tz_buf[32]; static char *old_tz = old_tz_buf; static size_t old_tz_size = sizeof old_tz_buf; static volatile int lock[1]; +#ifndef __EMSCRIPTEN__ volatile int *const __timezone_lockptr = lock; +#endif +#ifndef USE_EXTERNAL_ZONEINFO static int getint(const char **p) { unsigned x; @@ -122,9 +137,24 @@ static size_t zi_dotprod(const unsigned char *z, const unsigned char *v, size_t } return y; } +#endif static void do_tzset() { +#ifdef USE_EXTERNAL_ZONEINFO + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + static _Atomic bool done_init = false; + if (!done_init) { + pthread_mutex_lock(&lock); + if (!done_init) { + _tzset_js(&timezone, &daylight, std_name, dst_name); + __tzname[0] = std_name; + __tzname[1] = dst_name; + done_init = true; + } + pthread_mutex_unlock(&lock); + } +#else char buf[NAME_MAX+25], *pathname=buf+24; const char *try, *s, *p; const unsigned char *map = 0; @@ -255,8 +285,10 @@ static void do_tzset() if (*s == ',') s++, getrule(&s, r0); if (*s == ',') s++, getrule(&s, r1); +#endif } +#ifndef USE_EXTERNAL_ZONEINFO /* Search zoneinfo rules to find the one that applies to the given time, * and determine alternate opposite-DST-status rule that may be needed. */ @@ -416,6 +448,7 @@ void __secs_to_zone(long long t, int local, int *isdst, long *offset, long *oppo *zonename = __tzname[1]; UNLOCK(lock); } +#endif static void __tzset() { @@ -426,14 +459,16 @@ static void __tzset() weak_alias(__tzset, tzset); -const char *__tm_to_tzname(const struct tm *tm) +weak const char *__tm_to_tzname(const struct tm *tm) { const void *p = tm->__tm_zone; LOCK(lock); do_tzset(); +#ifndef USE_EXTERNAL_ZONEINFO if (p != __utc && p != __tzname[0] && p != __tzname[1] && (!zi || (uintptr_t)p-(uintptr_t)abbrevs >= abbrevs_end - abbrevs)) p = ""; +#endif UNLOCK(lock); return p; } diff --git a/src/time/clock_getres.c b/src/time/clock_getres.c index 81c67037..b733fdc0 100644 --- a/src/time/clock_getres.c +++ b/src/time/clock_getres.c @@ -3,6 +3,20 @@ int clock_getres(clockid_t clk, struct timespec *ts) { +#ifdef __EMSCRIPTEN__ + // See https://github.com/bytecodealliance/wasmtime/issues/374 + if (clk > __WASI_CLOCKID_THREAD_CPUTIME_ID || clk < 0) { + errno = EINVAL; + return -1; + } + __wasi_timestamp_t res; + __wasi_errno_t error = __wasi_clock_res_get(clk, &res); + if (error != __WASI_ERRNO_SUCCESS) { + return __wasi_syscall_ret(error); + } + *ts = __wasi_timestamp_to_timespec(res); + return 0; +#else #ifdef SYS_clock_getres_time64 /* On a 32-bit arch, use the old syscall if it exists. */ if (SYS_clock_getres != SYS_clock_getres_time64) { @@ -18,4 +32,5 @@ int clock_getres(clockid_t clk, struct timespec *ts) /* If reaching this point, it's a 64-bit arch or time64-only * 32-bit arch and we can get result directly into timespec. */ return syscall(SYS_clock_getres, clk, ts); +#endif } diff --git a/src/time/strftime.c b/src/time/strftime.c index c40246db..59d609ba 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -226,7 +226,13 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st s[l] = 0; return l; } +#ifdef __EMSCRIPTEN__ + // Handle trailing % by outputting a % rather than returning 0. Ideally + // this 6 character change could be upstreamed into musl... + if (*f != '%' || !f[1]) { +#else if (*f != '%') { +#endif s[l++] = *f; continue; }