summaryrefslogtreecommitdiff
path: root/system/musl/amalgamation.patch
diff options
context:
space:
mode:
authorA. Wilcox <AWilcox@Wilcox-Tech.com>2018-08-24 15:35:06 +0000
committerA. Wilcox <AWilcox@Wilcox-Tech.com>2018-08-24 15:35:06 +0000
commit409fe2a85188baaa8a737c1a4fe19fb0df47eb62 (patch)
treec59c9ba5ca00ed664fedc32b9a6557f4e3e41eb1 /system/musl/amalgamation.patch
parent23e639121014d2e94bcf768313a46a9df3d85d41 (diff)
downloadpackages-409fe2a85188baaa8a737c1a4fe19fb0df47eb62.tar.gz
packages-409fe2a85188baaa8a737c1a4fe19fb0df47eb62.tar.bz2
packages-409fe2a85188baaa8a737c1a4fe19fb0df47eb62.tar.xz
packages-409fe2a85188baaa8a737c1a4fe19fb0df47eb62.zip
system/musl: package patch now even with tip of POSIX branch
Diffstat (limited to 'system/musl/amalgamation.patch')
-rw-r--r--system/musl/amalgamation.patch6417
1 files changed, 6417 insertions, 0 deletions
diff --git a/system/musl/amalgamation.patch b/system/musl/amalgamation.patch
new file mode 100644
index 000000000..08228fb84
--- /dev/null
+++ b/system/musl/amalgamation.patch
@@ -0,0 +1,6417 @@
+diff --git a/Makefile b/Makefile
+index 308ddaae..e23a8332 100644
+--- a/Makefile
++++ b/Makefile
+@@ -116,17 +116,14 @@ obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC
+ OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%))
+ $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3
+
+-MEMOPS_SRCS = src/string/memcpy.c src/string/memmove.c src/string/memcmp.c src/string/memset.c
+-$(MEMOPS_SRCS:%.c=obj/%.o) $(MEMOPS_SRCS:%.c=obj/%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS)
+-
+-NOSSP_SRCS = $(wildcard crt/*.c) \
+- src/env/__libc_start_main.c src/env/__init_tls.c \
+- src/env/__stack_chk_fail.c \
+- src/thread/__set_thread_area.c src/thread/$(ARCH)/__set_thread_area.c \
+- src/string/memset.c src/string/$(ARCH)/memset.c \
+- src/string/memcpy.c src/string/$(ARCH)/memcpy.c \
+- ldso/dlstart.c ldso/dynlink.c
+-$(NOSSP_SRCS:%.c=obj/%.o) $(NOSSP_SRCS:%.c=obj/%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
++MEMOPS_OBJS = $(filter %/memcpy.o %/memmove.o %/memcmp.o %/memset.o, $(LIBC_OBJS))
++$(MEMOPS_OBJS) $(MEMOPS_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS)
++
++NOSSP_OBJS = $(CRT_OBJS) $(LDSO_OBJS) $(filter \
++ %/__libc_start_main.o %/__init_tls.o %/__stack_chk_fail.o \
++ %/__set_thread_area.o %/memset.o %/memcpy.o \
++ , $(LIBC_OBJS))
++$(NOSSP_OBJS) $(NOSSP_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
+
+ $(CRT_OBJS): CFLAGS_ALL += -DCRT
+
+diff --git a/arch/aarch64/bits/hwcap.h b/arch/aarch64/bits/hwcap.h
+index 11396d31..8541e329 100644
+--- a/arch/aarch64/bits/hwcap.h
++++ b/arch/aarch64/bits/hwcap.h
+@@ -14,3 +14,15 @@
+ #define HWCAP_JSCVT (1 << 13)
+ #define HWCAP_FCMA (1 << 14)
+ #define HWCAP_LRCPC (1 << 15)
++#define HWCAP_DCPOP (1 << 16)
++#define HWCAP_SHA3 (1 << 17)
++#define HWCAP_SM3 (1 << 18)
++#define HWCAP_SM4 (1 << 19)
++#define HWCAP_ASIMDDP (1 << 20)
++#define HWCAP_SHA512 (1 << 21)
++#define HWCAP_SVE (1 << 22)
++#define HWCAP_ASIMDFHM (1 << 23)
++#define HWCAP_DIT (1 << 24)
++#define HWCAP_USCAT (1 << 25)
++#define HWCAP_ILRCPC (1 << 26)
++#define HWCAP_FLAGM (1 << 27)
+diff --git a/arch/aarch64/bits/signal.h b/arch/aarch64/bits/signal.h
+index 1c67313d..b71261f5 100644
+--- a/arch/aarch64/bits/signal.h
++++ b/arch/aarch64/bits/signal.h
+@@ -25,6 +25,7 @@ typedef struct sigcontext {
+ #define FPSIMD_MAGIC 0x46508001
+ #define ESR_MAGIC 0x45535201
+ #define EXTRA_MAGIC 0x45585401
++#define SVE_MAGIC 0x53564501
+ struct _aarch64_ctx {
+ unsigned int magic;
+ unsigned int size;
+@@ -45,6 +46,44 @@ struct extra_context {
+ unsigned int size;
+ unsigned int __reserved[3];
+ };
++struct sve_context {
++ struct _aarch64_ctx head;
++ unsigned short vl;
++ unsigned short __reserved[3];
++};
++#define SVE_VQ_BYTES 16
++#define SVE_VQ_MIN 1
++#define SVE_VQ_MAX 512
++#define SVE_VL_MIN (SVE_VQ_MIN * SVE_VQ_BYTES)
++#define SVE_VL_MAX (SVE_VQ_MAX * SVE_VQ_BYTES)
++#define SVE_NUM_ZREGS 32
++#define SVE_NUM_PREGS 16
++#define sve_vl_valid(vl) \
++ ((vl) % SVE_VQ_BYTES == 0 && (vl) >= SVE_VL_MIN && (vl) <= SVE_VL_MAX)
++#define sve_vq_from_vl(vl) ((vl) / SVE_VQ_BYTES)
++#define sve_vl_from_vq(vq) ((vq) * SVE_VQ_BYTES)
++#define SVE_SIG_ZREG_SIZE(vq) ((unsigned)(vq) * SVE_VQ_BYTES)
++#define SVE_SIG_PREG_SIZE(vq) ((unsigned)(vq) * (SVE_VQ_BYTES / 8))
++#define SVE_SIG_FFR_SIZE(vq) SVE_SIG_PREG_SIZE(vq)
++#define SVE_SIG_REGS_OFFSET \
++ ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) \
++ / SVE_VQ_BYTES * SVE_VQ_BYTES)
++#define SVE_SIG_ZREGS_OFFSET SVE_SIG_REGS_OFFSET
++#define SVE_SIG_ZREG_OFFSET(vq, n) \
++ (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREG_SIZE(vq) * (n))
++#define SVE_SIG_ZREGS_SIZE(vq) \
++ (SVE_SIG_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_SIG_ZREGS_OFFSET)
++#define SVE_SIG_PREGS_OFFSET(vq) \
++ (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREGS_SIZE(vq))
++#define SVE_SIG_PREG_OFFSET(vq, n) \
++ (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREG_SIZE(vq) * (n))
++#define SVE_SIG_PREGS_SIZE(vq) \
++ (SVE_SIG_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_SIG_PREGS_OFFSET(vq))
++#define SVE_SIG_FFR_OFFSET(vq) \
++ (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREGS_SIZE(vq))
++#define SVE_SIG_REGS_SIZE(vq) \
++ (SVE_SIG_FFR_OFFSET(vq) + SVE_SIG_FFR_SIZE(vq) - SVE_SIG_REGS_OFFSET)
++#define SVE_SIG_CONTEXT_SIZE(vq) (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq))
+ #else
+ typedef struct {
+ long double __regs[18+256];
+diff --git a/arch/aarch64/pthread_arch.h b/arch/aarch64/pthread_arch.h
+index b2e2d8f1..e8499d8e 100644
+--- a/arch/aarch64/pthread_arch.h
++++ b/arch/aarch64/pthread_arch.h
+@@ -2,10 +2,11 @@ static inline struct pthread *__pthread_self()
+ {
+ char *self;
+ __asm__ __volatile__ ("mrs %0,tpidr_el0" : "=r"(self));
+- return (void*)(self + 16 - sizeof(struct pthread));
++ return (void*)(self - sizeof(struct pthread));
+ }
+
+ #define TLS_ABOVE_TP
+-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 16)
++#define GAP_ABOVE_TP 16
++#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
+
+ #define MC_PC pc
+diff --git a/arch/aarch64/reloc.h b/arch/aarch64/reloc.h
+index 51b66e23..40cf0b28 100644
+--- a/arch/aarch64/reloc.h
++++ b/arch/aarch64/reloc.h
+@@ -10,7 +10,7 @@
+
+ #define NO_LEGACY_INITFINI
+
+-#define TPOFF_K 16
++#define TPOFF_K 0
+
+ #define REL_SYMBOLIC R_AARCH64_ABS64
+ #define REL_GOT R_AARCH64_GLOB_DAT
+diff --git a/arch/arm/atomic_arch.h b/arch/arm/atomic_arch.h
+index c5c56f81..62458b45 100644
+--- a/arch/arm/atomic_arch.h
++++ b/arch/arm/atomic_arch.h
+@@ -7,8 +7,8 @@
+ extern uintptr_t __attribute__((__visibility__("hidden")))
+ __a_cas_ptr, __a_barrier_ptr;
+
+-#if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6ZK__) && !__thumb__) \
+- || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
++#if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \
++ || __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+
+ #define a_ll a_ll
+ static inline int a_ll(volatile int *p)
+@@ -91,4 +91,16 @@ static inline int a_clz_32(uint32_t x)
+ return x;
+ }
+
++#if __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
++
++#define a_ctz_32 a_ctz_32
++static inline int a_ctz_32(uint32_t x)
++{
++ uint32_t xr;
++ __asm__ ("rbit %0, %1" : "=r"(xr) : "r"(x));
++ return a_clz_32(xr);
++}
++
++#endif
++
+ #endif
+diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in
+index c594152e..1920516a 100644
+--- a/arch/arm/bits/syscall.h.in
++++ b/arch/arm/bits/syscall.h.in
+@@ -359,4 +359,5 @@
+ #define __ARM_NR_usr26 0x0f0003
+ #define __ARM_NR_usr32 0x0f0004
+ #define __ARM_NR_set_tls 0x0f0005
++#define __ARM_NR_get_tls 0x0f0006
+
+diff --git a/arch/arm/pthread_arch.h b/arch/arm/pthread_arch.h
+index 197752ef..8f2ae8f8 100644
+--- a/arch/arm/pthread_arch.h
++++ b/arch/arm/pthread_arch.h
+@@ -1,11 +1,11 @@
+-#if ((__ARM_ARCH_6K__ || __ARM_ARCH_6ZK__) && !__thumb__) \
++#if ((__ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \
+ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+
+ static inline pthread_t __pthread_self()
+ {
+ char *p;
+ __asm__ __volatile__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(p) );
+- return (void *)(p+8-sizeof(struct pthread));
++ return (void *)(p-sizeof(struct pthread));
+ }
+
+ #else
+@@ -21,12 +21,13 @@ static inline pthread_t __pthread_self()
+ extern uintptr_t __attribute__((__visibility__("hidden"))) __a_gettp_ptr;
+ register uintptr_t p __asm__("r0");
+ __asm__ __volatile__ ( BLX " %1" : "=r"(p) : "r"(__a_gettp_ptr) : "cc", "lr" );
+- return (void *)(p+8-sizeof(struct pthread));
++ return (void *)(p-sizeof(struct pthread));
+ }
+
+ #endif
+
+ #define TLS_ABOVE_TP
+-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8)
++#define GAP_ABOVE_TP 8
++#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
+
+ #define MC_PC arm_pc
+diff --git a/arch/arm/reloc.h b/arch/arm/reloc.h
+index b175711d..4b00bf64 100644
+--- a/arch/arm/reloc.h
++++ b/arch/arm/reloc.h
+@@ -16,7 +16,7 @@
+
+ #define NO_LEGACY_INITFINI
+
+-#define TPOFF_K 8
++#define TPOFF_K 0
+
+ #define REL_SYMBOLIC R_ARM_ABS32
+ #define REL_GOT R_ARM_GLOB_DAT
+diff --git a/arch/arm/syscall_arch.h b/arch/arm/syscall_arch.h
+index 6023303b..53fb155c 100644
+--- a/arch/arm/syscall_arch.h
++++ b/arch/arm/syscall_arch.h
+@@ -3,74 +3,99 @@
+ ((union { long long ll; long l[2]; }){ .ll = x }).l[1]
+ #define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))
+
++#ifdef __thumb__
++
++/* Avoid use of r7 in asm constraints when producing thumb code,
++ * since it's reserved as frame pointer and might not be supported. */
++#define __ASM____R7__
++#define __asm_syscall(...) do { \
++ __asm__ __volatile__ ( "mov %1,r7 ; mov r7,%2 ; svc 0 ; mov r7,%1" \
++ : "=r"(r0), "=&r"((int){0}) : __VA_ARGS__ : "memory"); \
++ return r0; \
++ } while (0)
++
++#else
++
++#define __ASM____R7__ __asm__("r7")
+ #define __asm_syscall(...) do { \
+ __asm__ __volatile__ ( "svc 0" \
+ : "=r"(r0) : __VA_ARGS__ : "memory"); \
+ return r0; \
+ } while (0)
++#endif
++
++/* For thumb2, we can allow 8-bit immediate syscall numbers, saving a
++ * register in the above dance around r7. Does not work for thumb1 where
++ * only movs, not mov, supports immediates, and we can't use movs because
++ * it doesn't support high regs. */
++#ifdef __thumb2__
++#define R7_OPERAND "rI"(r7)
++#else
++#define R7_OPERAND "r"(r7)
++#endif
+
+ static inline long __syscall0(long n)
+ {
+- register long r7 __asm__("r7") = n;
++ register long r7 __ASM____R7__ = n;
+ register long r0 __asm__("r0");
+- __asm_syscall("r"(r7));
++ __asm_syscall(R7_OPERAND);
+ }
+
+ static inline long __syscall1(long n, long a)
+ {
+- register long r7 __asm__("r7") = n;
++ register long r7 __ASM____R7__ = n;
+ register long r0 __asm__("r0") = a;
+- __asm_syscall("r"(r7), "0"(r0));
++ __asm_syscall(R7_OPERAND, "0"(r0));
+ }
+
+ static inline long __syscall2(long n, long a, long b)
+ {
+- register long r7 __asm__("r7") = n;
++ register long r7 __ASM____R7__ = n;
+ register long r0 __asm__("r0") = a;
+ register long r1 __asm__("r1") = b;
+- __asm_syscall("r"(r7), "0"(r0), "r"(r1));
++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1));
+ }
+
+ static inline long __syscall3(long n, long a, long b, long c)
+ {
+- register long r7 __asm__("r7") = n;
++ register long r7 __ASM____R7__ = n;
+ register long r0 __asm__("r0") = a;
+ register long r1 __asm__("r1") = b;
+ register long r2 __asm__("r2") = c;
+- __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2));
++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2));
+ }
+
+ static inline long __syscall4(long n, long a, long b, long c, long d)
+ {
+- register long r7 __asm__("r7") = n;
++ register long r7 __ASM____R7__ = n;
+ register long r0 __asm__("r0") = a;
+ register long r1 __asm__("r1") = b;
+ register long r2 __asm__("r2") = c;
+ register long r3 __asm__("r3") = d;
+- __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3));
++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3));
+ }
+
+ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
+ {
+- register long r7 __asm__("r7") = n;
++ register long r7 __ASM____R7__ = n;
+ register long r0 __asm__("r0") = a;
+ register long r1 __asm__("r1") = b;
+ register long r2 __asm__("r2") = c;
+ register long r3 __asm__("r3") = d;
+ register long r4 __asm__("r4") = e;
+- __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4));
++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4));
+ }
+
+ static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
+ {
+- register long r7 __asm__("r7") = n;
++ register long r7 __ASM____R7__ = n;
+ register long r0 __asm__("r0") = a;
+ register long r1 __asm__("r1") = b;
+ register long r2 __asm__("r2") = c;
+ register long r3 __asm__("r3") = d;
+ register long r4 __asm__("r4") = e;
+ register long r5 __asm__("r5") = f;
+- __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
++ __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
+ }
+
+ #define VDSO_USEFUL
+@@ -78,3 +103,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
+ #define VDSO_CGT_VER "LINUX_2.6"
+
+ #define SYSCALL_FADVISE_6_ARG
++
++#define SYSCALL_IPC_BROKEN_MODE
+diff --git a/arch/generic/bits/kd.h b/arch/generic/bits/kd.h
+new file mode 100644
+index 00000000..33b873f4
+--- /dev/null
++++ b/arch/generic/bits/kd.h
+@@ -0,0 +1 @@
++#include <linux/kd.h>
+diff --git a/arch/generic/bits/ptrace.h b/arch/generic/bits/ptrace.h
+new file mode 100644
+index 00000000..e69de29b
+diff --git a/arch/generic/bits/soundcard.h b/arch/generic/bits/soundcard.h
+new file mode 100644
+index 00000000..fade986f
+--- /dev/null
++++ b/arch/generic/bits/soundcard.h
+@@ -0,0 +1 @@
++#include <linux/soundcard.h>
+diff --git a/arch/generic/bits/termios.h b/arch/generic/bits/termios.h
+index 434c02c8..124f71d2 100644
+--- a/arch/generic/bits/termios.h
++++ b/arch/generic/bits/termios.h
+@@ -51,6 +51,7 @@ struct termios {
+ #define ONLRET 0000040
+ #define OFILL 0000100
+ #define OFDEL 0000200
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+ #define NLDLY 0000400
+ #define NL0 0000000
+ #define NL1 0000400
+@@ -70,6 +71,7 @@ struct termios {
+ #define FFDLY 0100000
+ #define FF0 0000000
+ #define FF1 0100000
++#endif
+
+ #define VTDLY 0040000
+ #define VT0 0000000
+diff --git a/arch/generic/bits/vt.h b/arch/generic/bits/vt.h
+new file mode 100644
+index 00000000..834abfbc
+--- /dev/null
++++ b/arch/generic/bits/vt.h
+@@ -0,0 +1 @@
++#include <linux/vt.h>
+diff --git a/arch/i386/atomic_arch.h b/arch/i386/atomic_arch.h
+index 7d2a48a5..047fb68d 100644
+--- a/arch/i386/atomic_arch.h
++++ b/arch/i386/atomic_arch.h
+@@ -92,10 +92,10 @@ static inline int a_ctz_64(uint64_t x)
+ return r;
+ }
+
+-#define a_ctz_l a_ctz_l
+-static inline int a_ctz_l(unsigned long x)
++#define a_ctz_32 a_ctz_32
++static inline int a_ctz_32(uint32_t x)
+ {
+- long r;
++ int r;
+ __asm__( "bsf %1,%0" : "=r"(r) : "r"(x) );
+ return r;
+ }
+diff --git a/arch/i386/bits/limits.h b/arch/i386/bits/limits.h
+index 65a3dd64..c340ceb2 100644
+--- a/arch/i386/bits/limits.h
++++ b/arch/i386/bits/limits.h
+@@ -1,6 +1,6 @@
+ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+-#define PAGE_SIZE 4096
++#define PAGESIZE 4096
+ #define LONG_BIT 32
+ #endif
+
+diff --git a/arch/i386/bits/ptrace.h b/arch/i386/bits/ptrace.h
+new file mode 100644
+index 00000000..7d0efbf3
+--- /dev/null
++++ b/arch/i386/bits/ptrace.h
+@@ -0,0 +1,11 @@
++#define PTRACE_GET_THREAD_AREA 25
++#define PTRACE_SET_THREAD_AREA 26
++#define PTRACE_SYSEMU 31
++#define PTRACE_SYSEMU_SINGLESTEP 32
++#define PTRACE_SINGLEBLOCK 33
++
++#define PT_GET_THREAD_AREA PTRACE_GET_THREAD_AREA
++#define PT_SET_THREAD_AREA PTRACE_SET_THREAD_AREA
++#define PT_SYSEMU PTRACE_SYSEMU
++#define PT_SYSEMU_SINGLESTEP PTRACE_SYSEMU_SINGLESTEP
++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK
+diff --git a/arch/i386/bits/user.h b/arch/i386/bits/user.h
+index 0e343930..33fea986 100644
+--- a/arch/i386/bits/user.h
++++ b/arch/i386/bits/user.h
+@@ -37,8 +37,8 @@ struct user {
+ int u_debugreg[8];
+ };
+
+-#define PAGE_MASK (~(PAGE_SIZE-1))
+-#define NBPG PAGE_SIZE
++#define PAGE_MASK (~(PAGESIZE-1))
++#define NBPG PAGESIZE
+ #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/m68k/atomic_arch.h b/arch/m68k/atomic_arch.h
+new file mode 100644
+index 00000000..b369649a
+--- /dev/null
++++ b/arch/m68k/atomic_arch.h
+@@ -0,0 +1,8 @@
++#define a_cas a_cas
++static inline int a_cas(volatile int *p, int t, int s)
++{
++ __asm__ __volatile__ (
++ "cas.l %0, %2, (%1)"
++ : "+d"(t) : "a"(p), "d"(s) : "memory", "cc");
++ return t;
++}
+diff --git a/arch/m68k/bits/alltypes.h.in b/arch/m68k/bits/alltypes.h.in
+new file mode 100644
+index 00000000..a4a8141f
+--- /dev/null
++++ b/arch/m68k/bits/alltypes.h.in
+@@ -0,0 +1,31 @@
++#define _Addr int
++#define _Int64 long long
++#define _Reg int
++
++TYPEDEF __builtin_va_list va_list;
++TYPEDEF __builtin_va_list __isoc_va_list;
++
++#ifndef __cplusplus
++TYPEDEF long wchar_t;
++#endif
++
++#if __mcffpu__
++TYPEDEF float float_t;
++TYPEDEF double double_t;
++#else
++TYPEDEF long double float_t;
++TYPEDEF long double double_t;
++#endif
++
++TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
++
++TYPEDEF long time_t;
++TYPEDEF long suseconds_t;
++
++TYPEDEF struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
++TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
++TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
++TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
++TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
++TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
++TYPEDEF struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
+diff --git a/arch/m68k/bits/endian.h b/arch/m68k/bits/endian.h
+new file mode 100644
+index 00000000..ef074b77
+--- /dev/null
++++ b/arch/m68k/bits/endian.h
+@@ -0,0 +1 @@
++#define __BYTE_ORDER __BIG_ENDIAN
+diff --git a/arch/m68k/bits/fcntl.h b/arch/m68k/bits/fcntl.h
+new file mode 100644
+index 00000000..f1c8400f
+--- /dev/null
++++ b/arch/m68k/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 040000
++#define O_NOFOLLOW 0100000
++#define O_CLOEXEC 02000000
++
++#define O_ASYNC 020000
++#define O_DIRECT 0200000
++#define O_LARGEFILE 0400000
++#define O_NOATIME 01000000
++#define O_PATH 010000000
++#define O_TMPFILE 020200000
++#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/m68k/bits/fenv.h b/arch/m68k/bits/fenv.h
+new file mode 100644
+index 00000000..c90a4a58
+--- /dev/null
++++ b/arch/m68k/bits/fenv.h
+@@ -0,0 +1,29 @@
++#if __HAVE_68881__ || __mcffpu__
++
++#define FE_INEXACT 8
++#define FE_DIVBYZERO 16
++#define FE_UNDERFLOW 32
++#define FE_OVERFLOW 64
++#define FE_INVALID 128
++
++#define FE_ALL_EXCEPT 0xf8
++
++#define FE_TONEAREST 0
++#define FE_TOWARDZERO 16
++#define FE_DOWNWARD 32
++#define FE_UPWARD 48
++
++#else
++
++#define FE_ALL_EXCEPT 0
++#define FE_TONEAREST 0
++
++#endif
++
++typedef unsigned fexcept_t;
++
++typedef struct {
++ unsigned __control_register, __status_register, __instruction_address;
++} fenv_t;
++
++#define FE_DFL_ENV ((const fenv_t *) -1)
+diff --git a/arch/m68k/bits/float.h b/arch/m68k/bits/float.h
+new file mode 100644
+index 00000000..0e6899d5
+--- /dev/null
++++ b/arch/m68k/bits/float.h
+@@ -0,0 +1,39 @@
++#if !__mcffpu__
++
++#define FLT_EVAL_METHOD 2
++
++#define LDBL_TRUE_MIN 3.6451995318824746025e-4951L
++#define LDBL_MIN 1.68105157155604675313e-4932L
++#define LDBL_MAX 1.1897314953572317650e+4932L
++#define LDBL_EPSILON 1.0842021724855044340e-19L
++
++#define LDBL_MANT_DIG 64
++#define LDBL_MIN_EXP (-16382)
++#define LDBL_MAX_EXP 16384
++
++#define LDBL_DIG 18
++#define LDBL_MIN_10_EXP (-4931)
++#define LDBL_MAX_10_EXP 4932
++
++#define DECIMAL_DIG 21
++
++#else
++
++#define FLT_EVAL_METHOD 0
++
++#define LDBL_TRUE_MIN 4.94065645841246544177e-324L
++#define LDBL_MIN 2.22507385850720138309e-308L
++#define LDBL_MAX 1.79769313486231570815e+308L
++#define LDBL_EPSILON 2.22044604925031308085e-16L
++
++#define LDBL_MANT_DIG 53
++#define LDBL_MIN_EXP (-1021)
++#define LDBL_MAX_EXP 1024
++
++#define LDBL_DIG 15
++#define LDBL_MIN_10_EXP (-307)
++#define LDBL_MAX_10_EXP 308
++
++#define DECIMAL_DIG 17
++
++#endif
+diff --git a/arch/m68k/bits/limits.h b/arch/m68k/bits/limits.h
+new file mode 100644
+index 00000000..fbc6d238
+--- /dev/null
++++ b/arch/m68k/bits/limits.h
+@@ -0,0 +1,7 @@
++#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
++ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
++#define LONG_BIT 32
++#endif
++
++#define LONG_MAX 0x7fffffffL
++#define LLONG_MAX 0x7fffffffffffffffLL
+diff --git a/arch/m68k/bits/posix.h b/arch/m68k/bits/posix.h
+new file mode 100644
+index 00000000..30a38714
+--- /dev/null
++++ b/arch/m68k/bits/posix.h
+@@ -0,0 +1,2 @@
++#define _POSIX_V6_ILP32_OFFBIG 1
++#define _POSIX_V7_ILP32_OFFBIG 1
+diff --git a/arch/m68k/bits/ptrace.h b/arch/m68k/bits/ptrace.h
+new file mode 100644
+index 00000000..da93e7a7
+--- /dev/null
++++ b/arch/m68k/bits/ptrace.h
+@@ -0,0 +1,2 @@
++#define PTRACE_GET_THREAD_AREA 25
++#define PTRACE_SINGLEBLOCK 33
+diff --git a/arch/m68k/bits/reg.h b/arch/m68k/bits/reg.h
+new file mode 100644
+index 00000000..99201f70
+--- /dev/null
++++ b/arch/m68k/bits/reg.h
+@@ -0,0 +1,45 @@
++#undef __WORDSIZE
++#define __WORDSIZE 32
++#define PT_D1 0
++#define PT_D2 1
++#define PT_D3 2
++#define PT_D4 3
++#define PT_D5 4
++#define PT_D6 5
++#define PT_D7 6
++#define PT_A0 7
++#define PT_A1 8
++#define PT_A2 9
++#define PT_A3 10
++#define PT_A4 11
++#define PT_A5 12
++#define PT_A6 13
++#define PT_D0 14
++#define PT_USP 15
++#define PT_ORIG_D0 16
++#define PT_SR 17
++#define PT_PC 18
++
++#if __mcffpu__
++#define PT_FP0 21
++#define PT_FP1 23
++#define PT_FP2 25
++#define PT_FP3 27
++#define PT_FP4 29
++#define PT_FP5 31
++#define PT_FP6 33
++#define PT_FP7 35
++#else
++#define PT_FP0 21
++#define PT_FP1 24
++#define PT_FP2 27
++#define PT_FP3 30
++#define PT_FP4 33
++#define PT_FP5 36
++#define PT_FP6 39
++#define PT_FP7 42
++#endif
++
++#define PT_FPCR 45
++#define PT_FPSR 46
++#define PT_FPIAR 47
+diff --git a/arch/m68k/bits/setjmp.h b/arch/m68k/bits/setjmp.h
+new file mode 100644
+index 00000000..5e091fb4
+--- /dev/null
++++ b/arch/m68k/bits/setjmp.h
+@@ -0,0 +1 @@
++typedef unsigned long __jmp_buf[39];
+diff --git a/arch/m68k/bits/signal.h b/arch/m68k/bits/signal.h
+new file mode 100644
+index 00000000..2c369ca3
+--- /dev/null
++++ b/arch/m68k/bits/signal.h
+@@ -0,0 +1,140 @@
++#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
++enum { R_D0 = 0 };
++#define R_D0 R_D0
++enum { R_D1 = 1 };
++#define R_D1 R_D1
++enum { R_D2 = 2 };
++#define R_D2 R_D2
++enum { R_D3 = 3 };
++#define R_D3 R_D3
++enum { R_D4 = 4 };
++#define R_D4 R_D4
++enum { R_D5 = 5 };
++#define R_D5 R_D5
++enum { R_D6 = 6 };
++#define R_D6 R_D6
++enum { R_D7 = 7 };
++#define R_D7 R_D7
++enum { R_A0 = 8 };
++#define R_A0 R_A0
++enum { R_A1 = 9 };
++#define R_A1 R_A1
++enum { R_A2 = 10 };
++#define R_A2 R_A2
++enum { R_A3 = 11 };
++#define R_A3 R_A3
++enum { R_A4 = 12 };
++#define R_A4 R_A4
++enum { R_A5 = 13 };
++#define R_A5 R_A5
++enum { R_A6 = 14 };
++#define R_A6 R_A6
++enum { R_A7 = 15 };
++#define R_A7 R_A7
++enum { R_SP = 15 };
++#define R_SP R_SP
++enum { R_PC = 16 };
++#define R_PC R_PC
++enum { R_PS = 17 };
++#define R_PS R_PS
++#endif
++
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
++
++struct sigcontext {
++ unsigned long sc_mask, sc_usp, sc_d0, sc_d1, sc_a0, sc_a1;
++ unsigned short sc_sr;
++ unsigned long sc_pc;
++ unsigned short sc_formatvec;
++ unsigned long sc_fpregs[6], sc_fpcntl[3];
++ unsigned char sc_fpstate[216];
++};
++
++typedef int greg_t, gregset_t[18];
++typedef struct {
++ int f_pcr, f_psr, f_fpiaddr, f_fpregs[8][3];
++} fpregset_t;
++
++typedef struct {
++ int version;
++ gregset_t gregs;
++ fpregset_t fpregs;
++} mcontext_t;
++#else
++typedef struct {
++ int __version;
++ int __gregs[18];
++ int __fpregs[27];
++} mcontext_t;
++#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;
++ mcontext_t uc_mcontext;
++ long __reserved[80];
++ sigset_t uc_sigmask;
++} 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/m68k/bits/stat.h b/arch/m68k/bits/stat.h
+new file mode 100644
+index 00000000..0f7b66a1
+--- /dev/null
++++ b/arch/m68k/bits/stat.h
+@@ -0,0 +1,21 @@
++/* copied from kernel definition, but with padding replaced
++ * by the corresponding correctly-sized userspace types. */
++
++struct stat {
++ dev_t st_dev;
++ short __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;
++ short __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/m68k/bits/stdint.h b/arch/m68k/bits/stdint.h
+new file mode 100644
+index 00000000..d1b27121
+--- /dev/null
++++ b/arch/m68k/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/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in
+new file mode 100644
+index 00000000..89cf114c
+--- /dev/null
++++ b/arch/m68k/bits/syscall.h.in
+@@ -0,0 +1,361 @@
++#define __NR_restart_syscall 0
++#define __NR_exit 1
++#define __NR_fork 2
++#define __NR_read 3
++#define __NR_write 4
++#define __NR_open 5
++#define __NR_close 6
++#define __NR_waitpid 7
++#define __NR_creat 8
++#define __NR_link 9
++#define __NR_unlink 10
++#define __NR_execve 11
++#define __NR_chdir 12
++#define __NR_time 13
++#define __NR_mknod 14
++#define __NR_chmod 15
++#define __NR_chown 16
++#define __NR_oldstat 18
++#define __NR_lseek 19
++#define __NR_getpid 20
++#define __NR_mount 21
++#define __NR_umount 22
++#define __NR_setuid 23
++#define __NR_getuid 24
++#define __NR_stime 25
++#define __NR_ptrace 26
++#define __NR_alarm 27
++#define __NR_oldfstat 28
++#define __NR_pause 29
++#define __NR_utime 30
++#define __NR_access 33
++#define __NR_nice 34
++#define __NR_sync 36
++#define __NR_kill 37
++#define __NR_rename 38
++#define __NR_mkdir 39
++#define __NR_rmdir 40
++#define __NR_dup 41
++#define __NR_pipe 42
++#define __NR_times 43
++#define __NR_brk 45
++#define __NR_setgid 46
++#define __NR_getgid 47
++#define __NR_signal 48
++#define __NR_geteuid 49
++#define __NR_getegid 50
++#define __NR_acct 51
++#define __NR_umount2 52
++#define __NR_ioctl 54
++#define __NR_fcntl 55
++#define __NR_setpgid 57
++#define __NR_umask 60
++#define __NR_chroot 61
++#define __NR_ustat 62
++#define __NR_dup2 63
++#define __NR_getppid 64
++#define __NR_getpgrp 65
++#define __NR_setsid 66
++#define __NR_sigaction 67
++#define __NR_sgetmask 68
++#define __NR_ssetmask 69
++#define __NR_setreuid 70
++#define __NR_setregid 71
++#define __NR_sigsuspend 72
++#define __NR_sigpending 73
++#define __NR_sethostname 74
++#define __NR_setrlimit 75
++#define __NR_getrlimit 76
++#define __NR_getrusage 77
++#define __NR_gettimeofday 78
++#define __NR_settimeofday 79
++#define __NR_getgroups 80
++#define __NR_setgroups 81
++#define __NR_select 82
++#define __NR_symlink 83
++#define __NR_oldlstat 84
++#define __NR_readlink 85
++#define __NR_uselib 86
++#define __NR_swapon 87
++#define __NR_reboot 88
++#define __NR_readdir 89
++#define __NR_mmap 90
++#define __NR_munmap 91
++#define __NR_truncate 92
++#define __NR_ftruncate 93
++#define __NR_fchmod 94
++#define __NR_fchown 95
++#define __NR_getpriority 96
++#define __NR_setpriority 97
++#define __NR_statfs 99
++#define __NR_fstatfs 100
++#define __NR_socketcall 102
++#define __NR_syslog 103
++#define __NR_setitimer 104
++#define __NR_getitimer 105
++#define __NR_stat 106
++#define __NR_lstat 107
++#define __NR_fstat 108
++#define __NR_vhangup 111
++#define __NR_wait4 114
++#define __NR_swapoff 115
++#define __NR_sysinfo 116
++#define __NR_ipc 117
++#define __NR_fsync 118
++#define __NR_sigreturn 119
++#define __NR_clone 120
++#define __NR_setdomainname 121
++#define __NR_uname 122
++#define __NR_cacheflush 123
++#define __NR_adjtimex 124
++#define __NR_mprotect 125
++#define __NR_sigprocmask 126
++#define __NR_create_module 127
++#define __NR_init_module 128
++#define __NR_delete_module 129
++#define __NR_get_kernel_syms 130
++#define __NR_quotactl 131
++#define __NR_getpgid 132
++#define __NR_fchdir 133
++#define __NR_bdflush 134
++#define __NR_sysfs 135
++#define __NR_personality 136
++#define __NR_setfsuid 138
++#define __NR_setfsgid 139
++#define __NR__llseek 140
++#define __NR_getdents 141
++#define __NR__newselect 142
++#define __NR_flock 143
++#define __NR_msync 144
++#define __NR_readv 145
++#define __NR_writev 146
++#define __NR_getsid 147
++#define __NR_fdatasync 148
++#define __NR__sysctl 149
++#define __NR_mlock 150
++#define __NR_munlock 151
++#define __NR_mlockall 152
++#define __NR_munlockall 153
++#define __NR_sched_setparam 154
++#define __NR_sched_getparam 155
++#define __NR_sched_setscheduler 156
++#define __NR_sched_getscheduler 157
++#define __NR_sched_yield 158
++#define __NR_sched_get_priority_max 159
++#define __NR_sched_get_priority_min 160
++#define __NR_sched_rr_get_interval 161
++#define __NR_nanosleep 162
++#define __NR_mremap 163
++#define __NR_setresuid 164
++#define __NR_getresuid 165
++#define __NR_getpagesize 166
++#define __NR_query_module 167
++#define __NR_poll 168
++#define __NR_nfsservctl 169
++#define __NR_setresgid 170
++#define __NR_getresgid 171
++#define __NR_prctl 172
++#define __NR_rt_sigreturn 173
++#define __NR_rt_sigaction 174
++#define __NR_rt_sigprocmask 175
++#define __NR_rt_sigpending 176
++#define __NR_rt_sigtimedwait 177
++#define __NR_rt_sigqueueinfo 178
++#define __NR_rt_sigsuspend 179
++#define __NR_pread64 180
++#define __NR_pwrite64 181
++#define __NR_lchown 182
++#define __NR_getcwd 183
++#define __NR_capget 184
++#define __NR_capset 185
++#define __NR_sigaltstack 186
++#define __NR_sendfile 187
++#define __NR_getpmsg 188
++#define __NR_putpmsg 189
++#define __NR_vfork 190
++#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_chown32 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_setgroups32 206
++#define __NR_fchown32 207
++#define __NR_setresuid32 208
++#define __NR_getresuid32 209
++#define __NR_setresgid32 210
++#define __NR_getresgid32 211
++#define __NR_lchown32 212
++#define __NR_setuid32 213
++#define __NR_setgid32 214
++#define __NR_setfsuid32 215
++#define __NR_setfsgid32 216
++#define __NR_pivot_root 217
++#define __NR_getdents64 220
++#define __NR_gettid 221
++#define __NR_tkill 222
++#define __NR_setxattr 223
++#define __NR_lsetxattr 224
++#define __NR_fsetxattr 225
++#define __NR_getxattr 226
++#define __NR_lgetxattr 227
++#define __NR_fgetxattr 228
++#define __NR_listxattr 229
++#define __NR_llistxattr 230
++#define __NR_flistxattr 231
++#define __NR_removexattr 232
++#define __NR_lremovexattr 233
++#define __NR_fremovexattr 234
++#define __NR_futex 235
++#define __NR_sendfile64 236
++#define __NR_mincore 237
++#define __NR_madvise 238
++#define __NR_fcntl64 239
++#define __NR_readahead 240
++#define __NR_io_setup 241
++#define __NR_io_destroy 242
++#define __NR_io_getevents 243
++#define __NR_io_submit 244
++#define __NR_io_cancel 245
++#define __NR_fadvise64 246
++#define __NR_exit_group 247
++#define __NR_lookup_dcookie 248
++#define __NR_epoll_create 249
++#define __NR_epoll_ctl 250
++#define __NR_epoll_wait 251
++#define __NR_remap_file_pages 252
++#define __NR_set_tid_address 253
++#define __NR_timer_create 254
++#define __NR_timer_settime 255
++#define __NR_timer_gettime 256
++#define __NR_timer_getoverrun 257
++#define __NR_timer_delete 258
++#define __NR_clock_settime 259
++#define __NR_clock_gettime 260
++#define __NR_clock_getres 261
++#define __NR_clock_nanosleep 262
++#define __NR_statfs64 263
++#define __NR_fstatfs64 264
++#define __NR_tgkill 265
++#define __NR_utimes 266
++#define __NR_fadvise64_64 267
++#define __NR_mbind 268
++#define __NR_get_mempolicy 269
++#define __NR_set_mempolicy 270
++#define __NR_mq_open 271
++#define __NR_mq_unlink 272
++#define __NR_mq_timedsend 273
++#define __NR_mq_timedreceive 274
++#define __NR_mq_notify 275
++#define __NR_mq_getsetattr 276
++#define __NR_waitid 277
++#define __NR_add_key 279
++#define __NR_request_key 280
++#define __NR_keyctl 281
++#define __NR_ioprio_set 282
++#define __NR_ioprio_get 283
++#define __NR_inotify_init 284
++#define __NR_inotify_add_watch 285
++#define __NR_inotify_rm_watch 286
++#define __NR_migrate_pages 287
++#define __NR_openat 288
++#define __NR_mkdirat 289
++#define __NR_mknodat 290
++#define __NR_fchownat 291
++#define __NR_futimesat 292
++#define __NR_fstatat64 293
++#define __NR_unlinkat 294
++#define __NR_renameat 295
++#define __NR_linkat 296
++#define __NR_symlinkat 297
++#define __NR_readlinkat 298
++#define __NR_fchmodat 299
++#define __NR_faccessat 300
++#define __NR_pselect6 301
++#define __NR_ppoll 302
++#define __NR_unshare 303
++#define __NR_set_robust_list 304
++#define __NR_get_robust_list 305
++#define __NR_splice 306
++#define __NR_sync_file_range 307
++#define __NR_tee 308
++#define __NR_vmsplice 309
++#define __NR_move_pages 310
++#define __NR_sched_setaffinity 311
++#define __NR_sched_getaffinity 312
++#define __NR_kexec_load 313
++#define __NR_getcpu 314
++#define __NR_epoll_pwait 315
++#define __NR_utimensat 316
++#define __NR_signalfd 317
++#define __NR_timerfd_create 318
++#define __NR_eventfd 319
++#define __NR_fallocate 320
++#define __NR_timerfd_settime 321
++#define __NR_timerfd_gettime 322
++#define __NR_signalfd4 323
++#define __NR_eventfd2 324
++#define __NR_epoll_create1 325
++#define __NR_dup3 326
++#define __NR_pipe2 327
++#define __NR_inotify_init1 328
++#define __NR_preadv 329
++#define __NR_pwritev 330
++#define __NR_rt_tgsigqueueinfo 331
++#define __NR_perf_event_open 332
++#define __NR_get_thread_area 333
++#define __NR_set_thread_area 334
++#define __NR_atomic_cmpxchg_32 335
++#define __NR_atomic_barrier 336
++#define __NR_fanotify_init 337
++#define __NR_fanotify_mark 338
++#define __NR_prlimit64 339
++#define __NR_name_to_handle_at 340
++#define __NR_open_by_handle_at 341
++#define __NR_clock_adjtime 342
++#define __NR_syncfs 343
++#define __NR_setns 344
++#define __NR_process_vm_readv 345
++#define __NR_process_vm_writev 346
++#define __NR_kcmp 347
++#define __NR_finit_module 348
++#define __NR_sched_setattr 349
++#define __NR_sched_getattr 350
++#define __NR_renameat2 351
++#define __NR_getrandom 352
++#define __NR_memfd_create 353
++#define __NR_bpf 354
++#define __NR_execveat 355
++#define __NR_socket 356
++#define __NR_socketpair 357
++#define __NR_bind 358
++#define __NR_connect 359
++#define __NR_listen 360
++#define __NR_accept4 361
++#define __NR_getsockopt 362
++#define __NR_setsockopt 363
++#define __NR_getsockname 364
++#define __NR_getpeername 365
++#define __NR_sendto 366
++#define __NR_sendmsg 367
++#define __NR_recvfrom 368
++#define __NR_recvmsg 369
++#define __NR_shutdown 370
++#define __NR_recvmmsg 371
++#define __NR_sendmmsg 372
++#define __NR_userfaultfd 373
++#define __NR_membarrier 374
++#define __NR_mlock2 375
++#define __NR_copy_file_range 376
++#define __NR_preadv2 377
++#define __NR_pwritev2 378
++#define __NR_statx 379
+diff --git a/arch/m68k/bits/user.h b/arch/m68k/bits/user.h
+new file mode 100644
+index 00000000..9a4ca128
+--- /dev/null
++++ b/arch/m68k/bits/user.h
+@@ -0,0 +1,33 @@
++#undef __WORDSIZE
++#define __WORDSIZE 32
++
++struct user_m68kfp_struct {
++ unsigned long fpregs[24], fpcntl[3];
++};
++
++struct user_regs_struct {
++ long d1, d2, d3, d4, d5, d6, d7;
++ long a0, a1, a2, a3, a4, a5, a6;
++ long d0, usp, orig_d0;
++ short stkadj, sr;
++ long pc;
++ short fmtvec, __pad;
++};
++
++struct user {
++ struct user_regs_struct regs;
++ int u_fpvalid;
++ struct user_m68kfp_struct m68kfp;
++ unsigned long u_tsize, u_dsize, u_ssize, start_code, start_stack;
++ long signal;
++ int reserved;
++ unsigned long u_ar0;
++ struct user_m68kfp_struct *u_fpstate;
++ unsigned long magic;
++ char u_comm[32];
++};
++
++#define NBPG 4096
++#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/m68k/crt_arch.h b/arch/m68k/crt_arch.h
+new file mode 100644
+index 00000000..48a42f29
+--- /dev/null
++++ b/arch/m68k/crt_arch.h
+@@ -0,0 +1,14 @@
++__asm__(
++".text\n"
++".weak _DYNAMIC \n"
++".hidden _DYNAMIC \n"
++".global " START "\n"
++START ":\n"
++" suba.l %fp,%fp \n"
++" movea.l %sp,%a0 \n"
++" lea _DYNAMIC-.-8,%a1 \n"
++" pea (%pc,%a1) \n"
++" pea (%a0) \n"
++" lea " START "_c-.-8,%a1 \n"
++" jsr (%pc,%a1) \n"
++);
+diff --git a/arch/m68k/pthread_arch.h b/arch/m68k/pthread_arch.h
+new file mode 100644
+index 00000000..02d5b8a0
+--- /dev/null
++++ b/arch/m68k/pthread_arch.h
+@@ -0,0 +1,13 @@
++static inline struct pthread *__pthread_self()
++{
++ uintptr_t tp = __syscall(SYS_get_thread_area);
++ return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
++}
++
++#define TLS_ABOVE_TP
++#define GAP_ABOVE_TP 0
++#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
++
++#define DTP_OFFSET 0x8000
++
++#define MC_PC gregs[R_PC]
+diff --git a/arch/m68k/reloc.h b/arch/m68k/reloc.h
+new file mode 100644
+index 00000000..f920b39e
+--- /dev/null
++++ b/arch/m68k/reloc.h
+@@ -0,0 +1,30 @@
++#if __HAVE_68881__
++#define FP_SUFFIX ""
++#elif __mcffpu__
++#define FP_SUFFIX "-fp64"
++#else
++#define FP_SUFFIX "-sf"
++#endif
++
++#define LDSO_ARCH "m68k" FP_SUFFIX
++
++#define TPOFF_K (-0x7000)
++
++#define REL_SYMBOLIC R_68K_32
++#define REL_OFFSET R_68K_PC32
++#define REL_GOT R_68K_GLOB_DAT
++#define REL_PLT R_68K_JMP_SLOT
++#define REL_RELATIVE R_68K_RELATIVE
++#define REL_COPY R_68K_COPY
++#define REL_DTPMOD R_68K_TLS_DTPMOD32
++#define REL_DTPOFF R_68K_TLS_DTPREL32
++#define REL_TPOFF R_68K_TLS_TPREL32
++
++#define CRTJMP(pc,sp) __asm__ __volatile__( \
++ "move.l %1,%%sp ; jmp (%0)" : : "r"(pc), "r"(sp) : "memory" )
++
++#define GETFUNCSYM(fp, sym, got) __asm__ ( \
++ ".hidden " #sym "\n" \
++ "lea " #sym "-.-8,%0 \n" \
++ "lea (%%pc,%0),%0 \n" \
++ : "=a"(*fp) : : "memory" )
+diff --git a/arch/m68k/syscall_arch.h b/arch/m68k/syscall_arch.h
+new file mode 100644
+index 00000000..af79c306
+--- /dev/null
++++ b/arch/m68k/syscall_arch.h
+@@ -0,0 +1,91 @@
++#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))
++
++static __inline long __syscall0(long n)
++{
++ register unsigned long d0 __asm__("d0") = n;
++ __asm__ __volatile__ ("trap #0" : "+r"(d0)
++ :
++ : "memory");
++ return d0;
++}
++
++static inline long __syscall1(long n, long a)
++{
++ register unsigned long d0 __asm__("d0") = n;
++ register unsigned long d1 __asm__("d1") = a;
++ __asm__ __volatile__ ("trap #0" : "+r"(d0)
++ : "r"(d1)
++ : "memory");
++ return d0;
++}
++
++static inline long __syscall2(long n, long a, long b)
++{
++ register unsigned long d0 __asm__("d0") = n;
++ register unsigned long d1 __asm__("d1") = a;
++ register unsigned long d2 __asm__("d2") = b;
++ __asm__ __volatile__ ("trap #0" : "+r"(d0)
++ : "r"(d1), "r"(d2)
++ : "memory");
++ return d0;
++}
++
++static inline long __syscall3(long n, long a, long b, long c)
++{
++ register unsigned long d0 __asm__("d0") = n;
++ register unsigned long d1 __asm__("d1") = a;
++ register unsigned long d2 __asm__("d2") = b;
++ register unsigned long d3 __asm__("d3") = c;
++ __asm__ __volatile__ ("trap #0" : "+r"(d0)
++ : "r"(d1), "r"(d2), "r"(d3)
++ : "memory");
++ return d0;
++}
++
++static inline long __syscall4(long n, long a, long b, long c, long d)
++{
++ register unsigned long d0 __asm__("d0") = n;
++ register unsigned long d1 __asm__("d1") = a;
++ register unsigned long d2 __asm__("d2") = b;
++ register unsigned long d3 __asm__("d3") = c;
++ register unsigned long d4 __asm__("d4") = d;
++ __asm__ __volatile__ ("trap #0" : "+r"(d0)
++ : "r"(d1), "r"(d2), "r"(d3), "r"(d4)
++ : "memory");
++ return d0;
++}
++
++static inline long __syscall5(long n, long a, long b, long c, long d, long e)
++{
++ register unsigned long d0 __asm__("d0") = n;
++ register unsigned long d1 __asm__("d1") = a;
++ register unsigned long d2 __asm__("d2") = b;
++ register unsigned long d3 __asm__("d3") = c;
++ register unsigned long d4 __asm__("d4") = d;
++ register unsigned long d5 __asm__("d5") = e;
++ __asm__ __volatile__ ("trap #0" : "+r"(d0)
++ : "r"(d1), "r"(d2), "r"(d3), "r"(d4), "r"(d5)
++ : "memory");
++ return d0;
++}
++
++static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
++{
++ register unsigned long d0 __asm__("d0") = n;
++ register unsigned long d1 __asm__("d1") = a;
++ register unsigned long d2 __asm__("d2") = b;
++ register unsigned long d3 __asm__("d3") = c;
++ register unsigned long d4 __asm__("d4") = d;
++ register unsigned long d5 __asm__("d5") = e;
++ register unsigned long a0 __asm__("a0") = f;
++ __asm__ __volatile__ ("trap #0" : "+r"(d0)
++ : "r"(d1), "r"(d2), "r"(d3), "r"(d4), "r"(d5), "r"(a0)
++ : "memory");
++ return d0;
++}
++
++#define SYSCALL_USE_SOCKETCALL
++#define SYSCALL_IPC_BROKEN_MODE
+diff --git a/arch/microblaze/syscall_arch.h b/arch/microblaze/syscall_arch.h
+index 8e2de7ea..6cf631ad 100644
+--- a/arch/microblaze/syscall_arch.h
++++ b/arch/microblaze/syscall_arch.h
+@@ -102,3 +102,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
+ #define SYSCALL_NO_INLINE
+
+ #endif
++
++#define SYSCALL_IPC_BROKEN_MODE
+diff --git a/arch/mips/bits/hwcap.h b/arch/mips/bits/hwcap.h
+index 05cffba4..13e86fe7 100644
+--- a/arch/mips/bits/hwcap.h
++++ b/arch/mips/bits/hwcap.h
+@@ -1,2 +1,3 @@
+ #define HWCAP_MIPS_R6 (1 << 0)
+ #define HWCAP_MIPS_MSA (1 << 1)
++#define HWCAP_MIPS_CRC32 (1 << 2)
+diff --git a/arch/mips/bits/mman.h b/arch/mips/bits/mman.h
+index c68aea88..9027bb63 100644
+--- a/arch/mips/bits/mman.h
++++ b/arch/mips/bits/mman.h
+@@ -18,6 +18,7 @@
+ #define MAP_STACK 0x40000
+ #undef MAP_HUGETLB
+ #define MAP_HUGETLB 0x80000
++#undef MAP_SYNC
+
+ #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+ #undef MADV_SOFT_OFFLINE
+diff --git a/arch/mips/bits/ptrace.h b/arch/mips/bits/ptrace.h
+new file mode 100644
+index 00000000..77a01c06
+--- /dev/null
++++ b/arch/mips/bits/ptrace.h
+@@ -0,0 +1,9 @@
++#define PTRACE_GET_THREAD_AREA 25
++#define PTRACE_SET_THREAD_AREA 26
++#define PTRACE_PEEKTEXT_3264 0xc0
++#define PTRACE_PEEKDATA_3264 0xc1
++#define PTRACE_POKETEXT_3264 0xc2
++#define PTRACE_POKEDATA_3264 0xc3
++#define PTRACE_GET_THREAD_AREA_3264 0xc4
++#define PTRACE_GET_WATCH_REGS 0xd0
++#define PTRACE_SET_WATCH_REGS 0xd1
+diff --git a/arch/mips/bits/socket.h b/arch/mips/bits/socket.h
+index 191ebdb5..b82c7d34 100644
+--- a/arch/mips/bits/socket.h
++++ b/arch/mips/bits/socket.h
+@@ -45,6 +45,7 @@ struct cmsghdr {
+ #define SO_BSDCOMPAT 14
+ #define SO_PASSCRED 17
+ #define SO_PEERCRED 18
++#define SO_PEERSEC 30
+ #define SO_SNDBUFFORCE 31
+ #define SO_RCVBUFFORCE 33
+
+diff --git a/arch/mips/bits/termios.h b/arch/mips/bits/termios.h
+index 6a1205d7..f7b9dd2e 100644
+--- a/arch/mips/bits/termios.h
++++ b/arch/mips/bits/termios.h
+@@ -52,6 +52,7 @@ struct termios {
+ #define ONLRET 0000040
+ #define OFILL 0000100
+ #define OFDEL 0000200
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+ #define NLDLY 0000400
+ #define NL0 0000000
+ #define NL1 0000400
+@@ -71,6 +72,7 @@ struct termios {
+ #define FFDLY 0100000
+ #define FF0 0000000
+ #define FF1 0100000
++#endif
+
+ #define VTDLY 0040000
+ #define VT0 0000000
+@@ -163,5 +165,5 @@ struct termios {
+ #define EXTPROC 0200000
+
+ #define XTABS 0014000
+-#define TIOCSER_TEMT 1
++#define TIOCSER_TEMT 0x01
+ #endif
+diff --git a/arch/mips/pthread_arch.h b/arch/mips/pthread_arch.h
+index e5812655..5fea15ad 100644
+--- a/arch/mips/pthread_arch.h
++++ b/arch/mips/pthread_arch.h
+@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self()
+ }
+
+ #define TLS_ABOVE_TP
++#define GAP_ABOVE_TP 0
+ #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
+
+ #define DTP_OFFSET 0x8000
+diff --git a/arch/mips64/bits/hwcap.h b/arch/mips64/bits/hwcap.h
+index 05cffba4..13e86fe7 100644
+--- a/arch/mips64/bits/hwcap.h
++++ b/arch/mips64/bits/hwcap.h
+@@ -1,2 +1,3 @@
+ #define HWCAP_MIPS_R6 (1 << 0)
+ #define HWCAP_MIPS_MSA (1 << 1)
++#define HWCAP_MIPS_CRC32 (1 << 2)
+diff --git a/arch/mips64/bits/mman.h b/arch/mips64/bits/mman.h
+index c68aea88..9027bb63 100644
+--- a/arch/mips64/bits/mman.h
++++ b/arch/mips64/bits/mman.h
+@@ -18,6 +18,7 @@
+ #define MAP_STACK 0x40000
+ #undef MAP_HUGETLB
+ #define MAP_HUGETLB 0x80000
++#undef MAP_SYNC
+
+ #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+ #undef MADV_SOFT_OFFLINE
+diff --git a/arch/mips64/bits/ptrace.h b/arch/mips64/bits/ptrace.h
+new file mode 100644
+index 00000000..77a01c06
+--- /dev/null
++++ b/arch/mips64/bits/ptrace.h
+@@ -0,0 +1,9 @@
++#define PTRACE_GET_THREAD_AREA 25
++#define PTRACE_SET_THREAD_AREA 26
++#define PTRACE_PEEKTEXT_3264 0xc0
++#define PTRACE_PEEKDATA_3264 0xc1
++#define PTRACE_POKETEXT_3264 0xc2
++#define PTRACE_POKEDATA_3264 0xc3
++#define PTRACE_GET_THREAD_AREA_3264 0xc4
++#define PTRACE_GET_WATCH_REGS 0xd0
++#define PTRACE_SET_WATCH_REGS 0xd1
+diff --git a/arch/mips64/bits/socket.h b/arch/mips64/bits/socket.h
+index cf801797..5aff0d91 100644
+--- a/arch/mips64/bits/socket.h
++++ b/arch/mips64/bits/socket.h
+@@ -61,6 +61,7 @@ struct cmsghdr {
+ #define SO_BSDCOMPAT 14
+ #define SO_PASSCRED 17
+ #define SO_PEERCRED 18
++#define SO_PEERSEC 30
+ #define SO_SNDBUFFORCE 31
+ #define SO_RCVBUFFORCE 33
+
+diff --git a/arch/mips64/bits/termios.h b/arch/mips64/bits/termios.h
+index 6a1205d7..f7b9dd2e 100644
+--- a/arch/mips64/bits/termios.h
++++ b/arch/mips64/bits/termios.h
+@@ -52,6 +52,7 @@ struct termios {
+ #define ONLRET 0000040
+ #define OFILL 0000100
+ #define OFDEL 0000200
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+ #define NLDLY 0000400
+ #define NL0 0000000
+ #define NL1 0000400
+@@ -71,6 +72,7 @@ struct termios {
+ #define FFDLY 0100000
+ #define FF0 0000000
+ #define FF1 0100000
++#endif
+
+ #define VTDLY 0040000
+ #define VT0 0000000
+@@ -163,5 +165,5 @@ struct termios {
+ #define EXTPROC 0200000
+
+ #define XTABS 0014000
+-#define TIOCSER_TEMT 1
++#define TIOCSER_TEMT 0x01
+ #endif
+diff --git a/arch/mips64/pthread_arch.h b/arch/mips64/pthread_arch.h
+index e5812655..5fea15ad 100644
+--- a/arch/mips64/pthread_arch.h
++++ b/arch/mips64/pthread_arch.h
+@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self()
+ }
+
+ #define TLS_ABOVE_TP
++#define GAP_ABOVE_TP 0
+ #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
+
+ #define DTP_OFFSET 0x8000
+diff --git a/arch/mipsn32/bits/hwcap.h b/arch/mipsn32/bits/hwcap.h
+index 05cffba4..13e86fe7 100644
+--- a/arch/mipsn32/bits/hwcap.h
++++ b/arch/mipsn32/bits/hwcap.h
+@@ -1,2 +1,3 @@
+ #define HWCAP_MIPS_R6 (1 << 0)
+ #define HWCAP_MIPS_MSA (1 << 1)
++#define HWCAP_MIPS_CRC32 (1 << 2)
+diff --git a/arch/mipsn32/bits/mman.h b/arch/mipsn32/bits/mman.h
+index c68aea88..9027bb63 100644
+--- a/arch/mipsn32/bits/mman.h
++++ b/arch/mipsn32/bits/mman.h
+@@ -18,6 +18,7 @@
+ #define MAP_STACK 0x40000
+ #undef MAP_HUGETLB
+ #define MAP_HUGETLB 0x80000
++#undef MAP_SYNC
+
+ #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+ #undef MADV_SOFT_OFFLINE
+diff --git a/arch/mipsn32/bits/ptrace.h b/arch/mipsn32/bits/ptrace.h
+new file mode 100644
+index 00000000..77a01c06
+--- /dev/null
++++ b/arch/mipsn32/bits/ptrace.h
+@@ -0,0 +1,9 @@
++#define PTRACE_GET_THREAD_AREA 25
++#define PTRACE_SET_THREAD_AREA 26
++#define PTRACE_PEEKTEXT_3264 0xc0
++#define PTRACE_PEEKDATA_3264 0xc1
++#define PTRACE_POKETEXT_3264 0xc2
++#define PTRACE_POKEDATA_3264 0xc3
++#define PTRACE_GET_THREAD_AREA_3264 0xc4
++#define PTRACE_GET_WATCH_REGS 0xd0
++#define PTRACE_SET_WATCH_REGS 0xd1
+diff --git a/arch/mipsn32/bits/socket.h b/arch/mipsn32/bits/socket.h
+index 191ebdb5..b82c7d34 100644
+--- a/arch/mipsn32/bits/socket.h
++++ b/arch/mipsn32/bits/socket.h
+@@ -45,6 +45,7 @@ struct cmsghdr {
+ #define SO_BSDCOMPAT 14
+ #define SO_PASSCRED 17
+ #define SO_PEERCRED 18
++#define SO_PEERSEC 30
+ #define SO_SNDBUFFORCE 31
+ #define SO_RCVBUFFORCE 33
+
+diff --git a/arch/mipsn32/bits/termios.h b/arch/mipsn32/bits/termios.h
+index 6a1205d7..f7b9dd2e 100644
+--- a/arch/mipsn32/bits/termios.h
++++ b/arch/mipsn32/bits/termios.h
+@@ -52,6 +52,7 @@ struct termios {
+ #define ONLRET 0000040
+ #define OFILL 0000100
+ #define OFDEL 0000200
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+ #define NLDLY 0000400
+ #define NL0 0000000
+ #define NL1 0000400
+@@ -71,6 +72,7 @@ struct termios {
+ #define FFDLY 0100000
+ #define FF0 0000000
+ #define FF1 0100000
++#endif
+
+ #define VTDLY 0040000
+ #define VT0 0000000
+@@ -163,5 +165,5 @@ struct termios {
+ #define EXTPROC 0200000
+
+ #define XTABS 0014000
+-#define TIOCSER_TEMT 1
++#define TIOCSER_TEMT 0x01
+ #endif
+diff --git a/arch/mipsn32/pthread_arch.h b/arch/mipsn32/pthread_arch.h
+index e5812655..5fea15ad 100644
+--- a/arch/mipsn32/pthread_arch.h
++++ b/arch/mipsn32/pthread_arch.h
+@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self()
+ }
+
+ #define TLS_ABOVE_TP
++#define GAP_ABOVE_TP 0
+ #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
+
+ #define DTP_OFFSET 0x8000
+diff --git a/arch/or1k/bits/limits.h b/arch/or1k/bits/limits.h
+index 483b6749..3a811c99 100644
+--- a/arch/or1k/bits/limits.h
++++ b/arch/or1k/bits/limits.h
+@@ -1,6 +1,6 @@
+ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+-#define PAGE_SIZE 8192
++#define PAGESIZE 8192
+ #define LONG_BIT 32
+ #endif
+
+diff --git a/arch/or1k/pthread_arch.h b/arch/or1k/pthread_arch.h
+index 7decd769..521b9c53 100644
+--- a/arch/or1k/pthread_arch.h
++++ b/arch/or1k/pthread_arch.h
+@@ -12,6 +12,7 @@ static inline struct pthread *__pthread_self()
+ }
+
+ #define TLS_ABOVE_TP
++#define GAP_ABOVE_TP 0
+ #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
+
+ #define MC_PC regs.pc
+diff --git a/arch/powerpc/bits/hwcap.h b/arch/powerpc/bits/hwcap.h
+index 82c92a93..803de9b5 100644
+--- a/arch/powerpc/bits/hwcap.h
++++ b/arch/powerpc/bits/hwcap.h
+@@ -38,3 +38,6 @@
+ #define PPC_FEATURE2_HTM_NOSC 0x01000000
+ #define PPC_FEATURE2_ARCH_3_00 0x00800000
+ #define PPC_FEATURE2_HAS_IEEE128 0x00400000
++#define PPC_FEATURE2_DARN 0x00200000
++#define PPC_FEATURE2_SCV 0x00100000
++#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
+diff --git a/arch/powerpc/bits/mman.h b/arch/powerpc/bits/mman.h
+index 95ec4358..b3a675a8 100644
+--- a/arch/powerpc/bits/mman.h
++++ b/arch/powerpc/bits/mman.h
+@@ -4,6 +4,7 @@
+ #define MAP_NORESERVE 0x40
+ #undef MAP_LOCKED
+ #define MAP_LOCKED 0x80
++#undef MAP_SYNC
+
+ #undef MCL_CURRENT
+ #define MCL_CURRENT 0x2000
+diff --git a/arch/powerpc/bits/ptrace.h b/arch/powerpc/bits/ptrace.h
+new file mode 100644
+index 00000000..75086ca0
+--- /dev/null
++++ b/arch/powerpc/bits/ptrace.h
+@@ -0,0 +1,23 @@
++#define PTRACE_GETVRREGS 0x12
++#define PTRACE_SETVRREGS 0x13
++#define PTRACE_GETEVRREGS 0x14
++#define PTRACE_SETEVRREGS 0x15
++#define PTRACE_GETREGS64 0x16
++#define PTRACE_SETREGS64 0x17
++#define PTRACE_GET_DEBUGREG 0x19
++#define PTRACE_SET_DEBUGREG 0x1a
++#define PTRACE_GETVSRREGS 0x1b
++#define PTRACE_SETVSRREGS 0x1c
++#define PTRACE_SINGLEBLOCK 0x100
++
++#define PT_GETVRREGS PTRACE_GETVRREGS
++#define PT_SETVRREGS PTRACE_SETVRREGS
++#define PT_GETEVRREGS PTRACE_GETEVRREGS
++#define PT_SETEVRREGS PTRACE_SETEVRREGS
++#define PT_GETREGS64 PTRACE_GETREGS64
++#define PT_SETREGS64 PTRACE_SETREGS64
++#define PT_GET_DEBUGREG PTRACE_GET_DEBUGREG
++#define PT_SET_DEBUGREG PTRACE_SET_DEBUGREG
++#define PT_GETVSRREGS PTRACE_GETVSRREGS
++#define PT_SETVSRREGS PTRACE_SETVSRREGS
++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK
+diff --git a/arch/powerpc/bits/socket.h b/arch/powerpc/bits/socket.h
+index 2fee8777..a94b8bdb 100644
+--- a/arch/powerpc/bits/socket.h
++++ b/arch/powerpc/bits/socket.h
+@@ -36,6 +36,7 @@ struct cmsghdr {
+ #define SO_PASSCRED 20
+ #define SO_PEERCRED 21
+ #define SO_ACCEPTCONN 30
++#define SO_PEERSEC 31
+ #define SO_SNDBUFFORCE 32
+ #define SO_RCVBUFFORCE 33
+ #define SO_PROTOCOL 38
+diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in
+index 20833915..7ce94bbd 100644
+--- a/arch/powerpc/bits/syscall.h.in
++++ b/arch/powerpc/bits/syscall.h.in
+@@ -368,4 +368,7 @@
+ #define __NR_pwritev2 381
+ #define __NR_kexec_file_load 382
+ #define __NR_statx 383
++#define __NR_pkey_alloc 384
++#define __NR_pkey_free 385
++#define __NR_pkey_mprotect 386
+
+diff --git a/arch/powerpc/bits/termios.h b/arch/powerpc/bits/termios.h
+index 0b09630c..e3f22e86 100644
+--- a/arch/powerpc/bits/termios.h
++++ b/arch/powerpc/bits/termios.h
+@@ -53,6 +53,7 @@ struct termios {
+ #define ONLRET 0000040
+ #define OFILL 0000100
+ #define OFDEL 0000200
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+ #define NLDLY 0001400
+ #define NL0 0000000
+ #define NL1 0000400
+@@ -74,6 +75,7 @@ struct termios {
+ #define BSDLY 0100000
+ #define BS0 0000000
+ #define BS1 0100000
++#endif
+
+ #define VTDLY 0200000
+ #define VT0 0000000
+@@ -165,5 +167,5 @@ struct termios {
+ #define EXTPROC 0x10000000
+
+ #define XTABS 00006000
+-#define TIOCSER_TEMT 1
++#define TIOCSER_TEMT 0x01
+ #endif
+diff --git a/arch/powerpc/pthread_arch.h b/arch/powerpc/pthread_arch.h
+index 7c5c4fad..79e5a09f 100644
+--- a/arch/powerpc/pthread_arch.h
++++ b/arch/powerpc/pthread_arch.h
+@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self()
+ }
+
+ #define TLS_ABOVE_TP
++#define GAP_ABOVE_TP 0
+ #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
+
+ #define DTP_OFFSET 0x8000
+diff --git a/arch/powerpc64/bits/hwcap.h b/arch/powerpc64/bits/hwcap.h
+index 82c92a93..803de9b5 100644
+--- a/arch/powerpc64/bits/hwcap.h
++++ b/arch/powerpc64/bits/hwcap.h
+@@ -38,3 +38,6 @@
+ #define PPC_FEATURE2_HTM_NOSC 0x01000000
+ #define PPC_FEATURE2_ARCH_3_00 0x00800000
+ #define PPC_FEATURE2_HAS_IEEE128 0x00400000
++#define PPC_FEATURE2_DARN 0x00200000
++#define PPC_FEATURE2_SCV 0x00100000
++#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
+diff --git a/arch/powerpc64/bits/mman.h b/arch/powerpc64/bits/mman.h
+index 95ec4358..b3a675a8 100644
+--- a/arch/powerpc64/bits/mman.h
++++ b/arch/powerpc64/bits/mman.h
+@@ -4,6 +4,7 @@
+ #define MAP_NORESERVE 0x40
+ #undef MAP_LOCKED
+ #define MAP_LOCKED 0x80
++#undef MAP_SYNC
+
+ #undef MCL_CURRENT
+ #define MCL_CURRENT 0x2000
+diff --git a/arch/powerpc64/bits/ptrace.h b/arch/powerpc64/bits/ptrace.h
+new file mode 100644
+index 00000000..75086ca0
+--- /dev/null
++++ b/arch/powerpc64/bits/ptrace.h
+@@ -0,0 +1,23 @@
++#define PTRACE_GETVRREGS 0x12
++#define PTRACE_SETVRREGS 0x13
++#define PTRACE_GETEVRREGS 0x14
++#define PTRACE_SETEVRREGS 0x15
++#define PTRACE_GETREGS64 0x16
++#define PTRACE_SETREGS64 0x17
++#define PTRACE_GET_DEBUGREG 0x19
++#define PTRACE_SET_DEBUGREG 0x1a
++#define PTRACE_GETVSRREGS 0x1b
++#define PTRACE_SETVSRREGS 0x1c
++#define PTRACE_SINGLEBLOCK 0x100
++
++#define PT_GETVRREGS PTRACE_GETVRREGS
++#define PT_SETVRREGS PTRACE_SETVRREGS
++#define PT_GETEVRREGS PTRACE_GETEVRREGS
++#define PT_SETEVRREGS PTRACE_SETEVRREGS
++#define PT_GETREGS64 PTRACE_GETREGS64
++#define PT_SETREGS64 PTRACE_SETREGS64
++#define PT_GET_DEBUGREG PTRACE_GET_DEBUGREG
++#define PT_SET_DEBUGREG PTRACE_SET_DEBUGREG
++#define PT_GETVSRREGS PTRACE_GETVSRREGS
++#define PT_SETVSRREGS PTRACE_SETVSRREGS
++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK
+diff --git a/arch/powerpc64/bits/socket.h b/arch/powerpc64/bits/socket.h
+index 2f748ae8..0f3c9aac 100644
+--- a/arch/powerpc64/bits/socket.h
++++ b/arch/powerpc64/bits/socket.h
+@@ -54,6 +54,7 @@ struct cmsghdr {
+ #define SO_PASSCRED 20
+ #define SO_PEERCRED 21
+ #define SO_ACCEPTCONN 30
++#define SO_PEERSEC 31
+ #define SO_SNDBUFFORCE 32
+ #define SO_RCVBUFFORCE 33
+ #define SO_PROTOCOL 38
+diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in
+index 936f43c0..1da1ecc0 100644
+--- a/arch/powerpc64/bits/syscall.h.in
++++ b/arch/powerpc64/bits/syscall.h.in
+@@ -359,4 +359,7 @@
+ #define __NR_pwritev2 381
+ #define __NR_kexec_file_load 382
+ #define __NR_statx 383
++#define __NR_pkey_alloc 384
++#define __NR_pkey_free 385
++#define __NR_pkey_mprotect 386
+
+diff --git a/arch/powerpc64/bits/termios.h b/arch/powerpc64/bits/termios.h
+index 0b09630c..e3f22e86 100644
+--- a/arch/powerpc64/bits/termios.h
++++ b/arch/powerpc64/bits/termios.h
+@@ -53,6 +53,7 @@ struct termios {
+ #define ONLRET 0000040
+ #define OFILL 0000100
+ #define OFDEL 0000200
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+ #define NLDLY 0001400
+ #define NL0 0000000
+ #define NL1 0000400
+@@ -74,6 +75,7 @@ struct termios {
+ #define BSDLY 0100000
+ #define BS0 0000000
+ #define BS1 0100000
++#endif
+
+ #define VTDLY 0200000
+ #define VT0 0000000
+@@ -165,5 +167,5 @@ struct termios {
+ #define EXTPROC 0x10000000
+
+ #define XTABS 00006000
+-#define TIOCSER_TEMT 1
++#define TIOCSER_TEMT 0x01
+ #endif
+diff --git a/arch/powerpc64/pthread_arch.h b/arch/powerpc64/pthread_arch.h
+index 2f976fe2..37b75e29 100644
+--- a/arch/powerpc64/pthread_arch.h
++++ b/arch/powerpc64/pthread_arch.h
+@@ -6,6 +6,7 @@ static inline struct pthread *__pthread_self()
+ }
+
+ #define TLS_ABOVE_TP
++#define GAP_ABOVE_TP 0
+ #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
+
+ #define DTP_OFFSET 0x8000
+diff --git a/arch/s390x/bits/limits.h b/arch/s390x/bits/limits.h
+index 792a30b9..86ef7663 100644
+--- a/arch/s390x/bits/limits.h
++++ b/arch/s390x/bits/limits.h
+@@ -1,6 +1,6 @@
+ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+-#define PAGE_SIZE 4096
++#define PAGESIZE 4096
+ #define LONG_BIT 64
+ #endif
+
+diff --git a/arch/s390x/bits/ptrace.h b/arch/s390x/bits/ptrace.h
+new file mode 100644
+index 00000000..d50e3262
+--- /dev/null
++++ b/arch/s390x/bits/ptrace.h
+@@ -0,0 +1,9 @@
++#define PTRACE_SINGLEBLOCK 12
++#define PTRACE_PEEKUSR_AREA 0x5000
++#define PTRACE_POKEUSR_AREA 0x5001
++#define PTRACE_GET_LAST_BREAK 0x5006
++#define PTRACE_ENABLE_TE 0x5009
++#define PTRACE_DISABLE_TE 0x5010
++#define PTRACE_TE_ABORT_RAND 0x5011
++
++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK
+diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in
+index 4fe1a64f..409e9155 100644
+--- a/arch/s390x/bits/syscall.h.in
++++ b/arch/s390x/bits/syscall.h.in
+@@ -322,4 +322,6 @@
+ #define __NR_pwritev2 377
+ #define __NR_s390_guarded_storage 378
+ #define __NR_statx 379
++#define __NR_s390_sthyi 380
++#define __NR_kexec_file_load 381
+
+diff --git a/arch/s390x/bits/user.h b/arch/s390x/bits/user.h
+index 17bce16f..ff3f0483 100644
+--- a/arch/s390x/bits/user.h
++++ b/arch/s390x/bits/user.h
+@@ -54,8 +54,8 @@ struct user {
+ char u_comm[32];
+ };
+
+-#define PAGE_MASK (~(PAGE_SIZE-1))
+-#define NBPG PAGE_SIZE
++#define PAGE_MASK (~(PAGESIZE-1))
++#define NBPG PAGESIZE
+ #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/sh/bits/limits.h b/arch/sh/bits/limits.h
+index 65a3dd64..c340ceb2 100644
+--- a/arch/sh/bits/limits.h
++++ b/arch/sh/bits/limits.h
+@@ -1,6 +1,6 @@
+ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+-#define PAGE_SIZE 4096
++#define PAGESIZE 4096
+ #define LONG_BIT 32
+ #endif
+
+diff --git a/arch/sh/pthread_arch.h b/arch/sh/pthread_arch.h
+index 2756e7ec..41fefacf 100644
+--- a/arch/sh/pthread_arch.h
++++ b/arch/sh/pthread_arch.h
+@@ -2,10 +2,11 @@ static inline struct pthread *__pthread_self()
+ {
+ char *self;
+ __asm__ __volatile__ ("stc gbr,%0" : "=r" (self) );
+- return (struct pthread *) (self + 8 - sizeof(struct pthread));
++ return (struct pthread *) (self - sizeof(struct pthread));
+ }
+
+ #define TLS_ABOVE_TP
+-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8)
++#define GAP_ABOVE_TP 8
++#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
+
+ #define MC_PC sc_pc
+diff --git a/arch/sh/reloc.h b/arch/sh/reloc.h
+index 0238ce07..a1f16cb1 100644
+--- a/arch/sh/reloc.h
++++ b/arch/sh/reloc.h
+@@ -20,7 +20,7 @@
+
+ #define LDSO_ARCH "sh" ENDIAN_SUFFIX FP_SUFFIX ABI_SUFFIX
+
+-#define TPOFF_K 8
++#define TPOFF_K 0
+
+ #define REL_SYMBOLIC R_SH_DIR32
+ #define REL_OFFSET R_SH_REL32
+diff --git a/arch/sh/syscall_arch.h b/arch/sh/syscall_arch.h
+index 84758fe0..48f61d94 100644
+--- a/arch/sh/syscall_arch.h
++++ b/arch/sh/syscall_arch.h
+@@ -86,3 +86,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
+ register long r1 __asm__("r1") = f;
+ __asm_syscall(22, "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "0"(r0), "r"(r1));
+ }
++
++#define SYSCALL_IPC_BROKEN_MODE
+diff --git a/arch/x32/atomic_arch.h b/arch/x32/atomic_arch.h
+index a744c299..918c2d4e 100644
+--- a/arch/x32/atomic_arch.h
++++ b/arch/x32/atomic_arch.h
+@@ -106,8 +106,8 @@ static inline int a_ctz_64(uint64_t x)
+ return x;
+ }
+
+-#define a_ctz_l a_ctz_l
+-static inline int a_ctz_l(unsigned long x)
++#define a_ctz_32 a_ctz_32
++static inline int a_ctz_32(uint32_t x)
+ {
+ __asm__( "bsf %1,%0" : "=r"(x) : "r"(x) );
+ return x;
+diff --git a/arch/x32/bits/limits.h b/arch/x32/bits/limits.h
+index 65a3dd64..c340ceb2 100644
+--- a/arch/x32/bits/limits.h
++++ b/arch/x32/bits/limits.h
+@@ -1,6 +1,6 @@
+ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+-#define PAGE_SIZE 4096
++#define PAGESIZE 4096
+ #define LONG_BIT 32
+ #endif
+
+diff --git a/arch/x32/bits/ptrace.h b/arch/x32/bits/ptrace.h
+new file mode 100644
+index 00000000..7f8a09b5
+--- /dev/null
++++ b/arch/x32/bits/ptrace.h
+@@ -0,0 +1,13 @@
++#define PTRACE_GET_THREAD_AREA 25
++#define PTRACE_SET_THREAD_AREA 26
++#define PTRACE_ARCH_PRCTL 30
++#define PTRACE_SYSEMU 31
++#define PTRACE_SYSEMU_SINGLESTEP 32
++#define PTRACE_SINGLEBLOCK 33
++
++#define PT_GET_THREAD_AREA PTRACE_GET_THREAD_AREA
++#define PT_SET_THREAD_AREA PTRACE_SET_THREAD_AREA
++#define PT_ARCH_PRCTL PTRACE_ARCH_PRCTL
++#define PT_SYSEMU PTRACE_SYSEMU
++#define PT_SYSEMU_SINGLESTEP PTRACE_SYSEMU_SINGLESTEP
++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK
+diff --git a/arch/x32/bits/user.h b/arch/x32/bits/user.h
+index 471bb19d..4073cc06 100644
+--- a/arch/x32/bits/user.h
++++ b/arch/x32/bits/user.h
+@@ -34,8 +34,8 @@ struct user {
+ unsigned long u_debugreg[8];
+ };
+
+-#define PAGE_MASK (~(PAGE_SIZE-1))
+-#define NBPG PAGE_SIZE
++#define PAGE_MASK (~(PAGESIZE-1))
++#define NBPG PAGESIZE
+ #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/x86_64/bits/limits.h b/arch/x86_64/bits/limits.h
+index 792a30b9..86ef7663 100644
+--- a/arch/x86_64/bits/limits.h
++++ b/arch/x86_64/bits/limits.h
+@@ -1,6 +1,6 @@
+ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+-#define PAGE_SIZE 4096
++#define PAGESIZE 4096
+ #define LONG_BIT 64
+ #endif
+
+diff --git a/arch/x86_64/bits/ptrace.h b/arch/x86_64/bits/ptrace.h
+new file mode 100644
+index 00000000..7f8a09b5
+--- /dev/null
++++ b/arch/x86_64/bits/ptrace.h
+@@ -0,0 +1,13 @@
++#define PTRACE_GET_THREAD_AREA 25
++#define PTRACE_SET_THREAD_AREA 26
++#define PTRACE_ARCH_PRCTL 30
++#define PTRACE_SYSEMU 31
++#define PTRACE_SYSEMU_SINGLESTEP 32
++#define PTRACE_SINGLEBLOCK 33
++
++#define PT_GET_THREAD_AREA PTRACE_GET_THREAD_AREA
++#define PT_SET_THREAD_AREA PTRACE_SET_THREAD_AREA
++#define PT_ARCH_PRCTL PTRACE_ARCH_PRCTL
++#define PT_SYSEMU PTRACE_SYSEMU
++#define PT_SYSEMU_SINGLESTEP PTRACE_SYSEMU_SINGLESTEP
++#define PT_STEPBLOCK PTRACE_SINGLEBLOCK
+diff --git a/arch/x86_64/bits/user.h b/arch/x86_64/bits/user.h
+index 471bb19d..4073cc06 100644
+--- a/arch/x86_64/bits/user.h
++++ b/arch/x86_64/bits/user.h
+@@ -34,8 +34,8 @@ struct user {
+ unsigned long u_debugreg[8];
+ };
+
+-#define PAGE_MASK (~(PAGE_SIZE-1))
+-#define NBPG PAGE_SIZE
++#define PAGE_MASK (~(PAGESIZE-1))
++#define NBPG PAGESIZE
+ #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/configure b/configure
+index 1e59c461..f940af9a 100755
+--- a/configure
++++ b/configure
+@@ -320,6 +320,7 @@ i?86*) ARCH=i386 ;;
+ x86_64-x32*|x32*|x86_64*x32) ARCH=x32 ;;
+ x86_64-nt64*) ARCH=nt64 ;;
+ x86_64*) ARCH=x86_64 ;;
++m68k*) ARCH=m68k ;;
+ mips64*|mipsisa64*) ARCH=mips64 ;;
+ mips*) ARCH=mips ;;
+ microblaze*) ARCH=microblaze ;;
+@@ -590,10 +591,12 @@ tryldflag LDFLAGS_AUTO -Wl,--no-undefined
+ # versions built without shared library support and pcc are broken.
+ tryldflag LDFLAGS_AUTO -Wl,--exclude-libs=ALL
+
+-# Linking with -Bsymbolic-functions is no longer mandatory for
+-# the dynamic linker to work, but enable it if it works as
+-# a linking optimization.
+-tryldflag LDFLAGS_AUTO -Wl,-Bsymbolic-functions
++# Public data symbols must be interposable to allow for copy
++# relocations, but otherwise we want to bind symbols at libc link
++# time to eliminate startup relocations and PLT overhead. Use
++# --dynamic-list rather than -Bsymbolic-functions for greater
++# control over what symbols are left unbound.
++tryldflag LDFLAGS_AUTO -Wl,--dynamic-list="$srcdir/dynamic.list"
+
+ # Find compiler runtime library
+ test -z "$LIBCC" && tryldflag LIBCC -lgcc && tryldflag LIBCC -lgcc_eh
+@@ -639,6 +642,13 @@ if test "$ARCH" = "aarch64" ; then
+ trycppif __AARCH64EB__ "$t" && SUBARCH=${SUBARCH}_be
+ fi
+
++if test "$ARCH" = "m68k" ; then
++if trycppif "__HAVE_68881__" ; then : ;
++elif trycppif "__mcffpu__" ; then SUBARCH="-fp64"
++else SUBARCH="-sf"
++fi
++fi
++
+ if test "$ARCH" = "mips" ; then
+ trycppif "__mips_isa_rev >= 6" "$t" && SUBARCH=${SUBARCH}r6
+ trycppif "_MIPSEL || __MIPSEL || __MIPSEL__" "$t" && SUBARCH=${SUBARCH}el
+diff --git a/dynamic.list b/dynamic.list
+new file mode 100644
+index 00000000..686f8eb4
+--- /dev/null
++++ b/dynamic.list
+@@ -0,0 +1,44 @@
++{
++environ;
++__environ;
++
++stdin;
++stdout;
++stderr;
++
++malloc;
++calloc;
++realloc;
++free;
++memalign;
++posix_memalign;
++aligned_alloc;
++malloc_usable_size;
++
++timezone;
++daylight;
++tzname;
++__timezone;
++__daylight;
++__tzname;
++
++signgam;
++__signgam;
++
++optarg;
++optind;
++opterr;
++optreset;
++__optreset;
++
++getdate_err;
++
++h_errno;
++
++program_invocation_name;
++program_invocation_short_name;
++__progname;
++__progname_full;
++
++__stack_chk_guard;
++};
+diff --git a/include/alltypes.h.in b/include/alltypes.h.in
+index 6a9c105f..622ca01d 100644
+--- a/include/alltypes.h.in
++++ b/include/alltypes.h.in
+@@ -7,10 +7,10 @@ TYPEDEF _Addr regoff_t;
+ TYPEDEF _Reg register_t;
+
+ TYPEDEF signed char int8_t;
+-TYPEDEF short int16_t;
+-TYPEDEF int int32_t;
+-TYPEDEF _Int64 int64_t;
+-TYPEDEF _Int64 intmax_t;
++TYPEDEF signed short int16_t;
++TYPEDEF signed int int32_t;
++TYPEDEF signed _Int64 int64_t;
++TYPEDEF signed _Int64 intmax_t;
+ TYPEDEF unsigned char uint8_t;
+ TYPEDEF unsigned short uint16_t;
+ TYPEDEF unsigned int uint32_t;
+diff --git a/include/elf.h b/include/elf.h
+index e79915fe..c2297353 100644
+--- a/include/elf.h
++++ b/include/elf.h
+@@ -623,6 +623,7 @@ typedef struct {
+
+
+ #define NT_PRSTATUS 1
++#define NT_PRFPREG 2
+ #define NT_FPREGSET 2
+ #define NT_PRPSINFO 3
+ #define NT_PRXREG 4
+@@ -644,6 +645,19 @@ typedef struct {
+ #define NT_PPC_VMX 0x100
+ #define NT_PPC_SPE 0x101
+ #define NT_PPC_VSX 0x102
++#define NT_PPC_TAR 0x103
++#define NT_PPC_PPR 0x104
++#define NT_PPC_DSCR 0x105
++#define NT_PPC_EBB 0x106
++#define NT_PPC_PMU 0x107
++#define NT_PPC_TM_CGPR 0x108
++#define NT_PPC_TM_CFPR 0x109
++#define NT_PPC_TM_CVMX 0x10a
++#define NT_PPC_TM_CVSX 0x10b
++#define NT_PPC_TM_SPR 0x10c
++#define NT_PPC_TM_CTAR 0x10d
++#define NT_PPC_TM_CPPR 0x10e
++#define NT_PPC_TM_CDSCR 0x10f
+ #define NT_386_TLS 0x200
+ #define NT_386_IOPERM 0x201
+ #define NT_X86_XSTATE 0x202
+@@ -656,14 +670,21 @@ typedef struct {
+ #define NT_S390_LAST_BREAK 0x306
+ #define NT_S390_SYSTEM_CALL 0x307
+ #define NT_S390_TDB 0x308
++#define NT_S390_VXRS_LOW 0x309
++#define NT_S390_VXRS_HIGH 0x30a
++#define NT_S390_GS_CB 0x30b
++#define NT_S390_GS_BC 0x30c
++#define NT_S390_RI_CB 0x30d
+ #define NT_ARM_VFP 0x400
+ #define NT_ARM_TLS 0x401
+ #define NT_ARM_HW_BREAK 0x402
+ #define NT_ARM_HW_WATCH 0x403
+ #define NT_ARM_SYSTEM_CALL 0x404
++#define NT_ARM_SVE 0x405
+ #define NT_METAG_CBUF 0x500
+ #define NT_METAG_RPIPE 0x501
+ #define NT_METAG_TLS 0x502
++#define NT_ARC_V2 0x600
+ #define NT_VERSION 1
+
+
+@@ -721,7 +742,8 @@ typedef struct {
+ #define DT_ENCODING 32
+ #define DT_PREINIT_ARRAY 32
+ #define DT_PREINIT_ARRAYSZ 33
+-#define DT_NUM 34
++#define DT_SYMTAB_SHNDX 34
++#define DT_NUM 35
+ #define DT_LOOS 0x6000000d
+ #define DT_HIOS 0x6ffff000
+ #define DT_LOPROC 0x70000000
+@@ -821,6 +843,8 @@ typedef struct {
+ #define DF_1_SYMINTPOSE 0x00800000
+ #define DF_1_GLOBAUDIT 0x01000000
+ #define DF_1_SINGLETON 0x02000000
++#define DF_1_STUB 0x04000000
++#define DF_1_PIE 0x08000000
+
+ #define DTF_1_PARINIT 0x00000001
+ #define DTF_1_CONFEXP 0x00000002
+@@ -1002,6 +1026,14 @@ typedef struct {
+ #define AT_L2_CACHESHAPE 36
+ #define AT_L3_CACHESHAPE 37
+
++#define AT_L1I_CACHESIZE 40
++#define AT_L1I_CACHEGEOMETRY 41
++#define AT_L1D_CACHESIZE 42
++#define AT_L1D_CACHEGEOMETRY 43
++#define AT_L2_CACHESIZE 44
++#define AT_L2_CACHEGEOMETRY 45
++#define AT_L3_CACHESIZE 46
++#define AT_L3_CACHEGEOMETRY 47
+
+
+
+@@ -1097,7 +1129,25 @@ typedef struct {
+ #define R_68K_GLOB_DAT 20
+ #define R_68K_JMP_SLOT 21
+ #define R_68K_RELATIVE 22
+-#define R_68K_NUM 23
++#define R_68K_TLS_GD32 25
++#define R_68K_TLS_GD16 26
++#define R_68K_TLS_GD8 27
++#define R_68K_TLS_LDM32 28
++#define R_68K_TLS_LDM16 29
++#define R_68K_TLS_LDM8 30
++#define R_68K_TLS_LDO32 31
++#define R_68K_TLS_LDO16 32
++#define R_68K_TLS_LDO8 33
++#define R_68K_TLS_IE32 34
++#define R_68K_TLS_IE16 35
++#define R_68K_TLS_IE8 36
++#define R_68K_TLS_LE32 37
++#define R_68K_TLS_LE16 38
++#define R_68K_TLS_LE8 39
++#define R_68K_TLS_DTPMOD32 40
++#define R_68K_TLS_DTPREL32 41
++#define R_68K_TLS_TPREL32 42
++#define R_68K_NUM 43
+
+ #define R_386_NONE 0
+ #define R_386_32 1
+@@ -2233,6 +2283,7 @@ enum
+
+ #define PPC64_OPT_TLS 1
+ #define PPC64_OPT_MULTI_TOC 2
++#define PPC64_OPT_LOCALENTRY 4
+
+ #define STO_PPC64_LOCAL_BIT 5
+ #define STO_PPC64_LOCAL_MASK 0xe0
+diff --git a/include/limits.h b/include/limits.h
+index f9805a1e..ab163a22 100644
+--- a/include/limits.h
++++ b/include/limits.h
+@@ -40,14 +40,9 @@
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+ #define PIPE_BUF 4096
+-#ifdef PAGE_SIZE
+-#define PAGESIZE PAGE_SIZE
+-#endif
+ #define FILESIZEBITS 64
+ #define NAME_MAX 255
+-#define SYMLINK_MAX 255
+ #define PATH_MAX 4096
+-#define NZERO 20
+ #define NGROUPS_MAX 32
+ #define ARG_MAX 131072
+ #define IOV_MAX 1024
+@@ -82,13 +77,22 @@
+ #define RE_DUP_MAX 255
+
+ #define NL_ARGMAX 9
+-#define NL_LANGMAX 32
+ #define NL_MSGMAX 32767
+ #define NL_SETMAX 255
+ #define NL_TEXTMAX 2048
+
+ #endif
+
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
++
++#ifdef PAGESIZE
++#define PAGE_SIZE PAGESIZE
++#endif
++#define NZERO 20
++#define NL_LANGMAX 32
++
++#endif
++
+ #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) \
+ || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700)
+
+diff --git a/include/math.h b/include/math.h
+index 6ac91da2..fea34686 100644
+--- a/include/math.h
++++ b/include/math.h
+@@ -27,7 +27,7 @@ extern "C" {
+ #define MATH_ERREXCEPT 2
+ #define math_errhandling 2
+
+-#define FP_ILOGBNAN (-1-(int)(((unsigned)-1)>>1))
++#define FP_ILOGBNAN (-1-0x7fffffff)
+ #define FP_ILOGB0 FP_ILOGBNAN
+
+ #define FP_NAN 0
+diff --git a/include/net/if_arp.h b/include/net/if_arp.h
+index c832ff95..27becc83 100644
+--- a/include/net/if_arp.h
++++ b/include/net/if_arp.h
+@@ -59,6 +59,7 @@ struct arphdr {
+ #define ARPHRD_LAPB 516
+ #define ARPHRD_DDCMP 517
+ #define ARPHRD_RAWHDLC 518
++#define ARPHRD_RAWIP 519
+
+ #define ARPHRD_TUNNEL 768
+ #define ARPHRD_TUNNEL6 769
+diff --git a/include/netinet/if_ether.h b/include/netinet/if_ether.h
+index 97134d75..ecd6c73c 100644
+--- a/include/netinet/if_ether.h
++++ b/include/netinet/if_ether.h
+@@ -5,6 +5,7 @@
+ #include <sys/types.h>
+
+ #define ETH_ALEN 6
++#define ETH_TLEN 2
+ #define ETH_HLEN 14
+ #define ETH_ZLEN 60
+ #define ETH_DATA_LEN 1500
+@@ -17,6 +18,7 @@
+ #define ETH_P_PUP 0x0200
+ #define ETH_P_PUPAT 0x0201
+ #define ETH_P_TSN 0x22F0
++#define ETH_P_ERSPAN2 0x22EB
+ #define ETH_P_IP 0x0800
+ #define ETH_P_X25 0x0805
+ #define ETH_P_ARP 0x0806
+@@ -53,6 +55,8 @@
+ #define ETH_P_AOE 0x88A2
+ #define ETH_P_8021AD 0x88A8
+ #define ETH_P_802_EX1 0x88B5
++#define ETH_P_ERSPAN 0x88BE
++#define ETH_P_PREAUTH 0x88C7
+ #define ETH_P_TIPC 0x88CA
+ #define ETH_P_MACSEC 0x88E5
+ #define ETH_P_8021AH 0x88E7
+@@ -66,11 +70,13 @@
+ #define ETH_P_IBOE 0x8915
+ #define ETH_P_80221 0x8917
+ #define ETH_P_HSR 0x892F
++#define ETH_P_NSH 0x894F
+ #define ETH_P_LOOPBACK 0x9000
+ #define ETH_P_QINQ1 0x9100
+ #define ETH_P_QINQ2 0x9200
+ #define ETH_P_QINQ3 0x9300
+ #define ETH_P_EDSA 0xDADA
++#define ETH_P_IFE 0xED3E
+ #define ETH_P_AF_IUCV 0xFBFB
+
+ #define ETH_P_802_3_MIN 0x0600
+@@ -100,6 +106,7 @@
+ #define ETH_P_IEEE802154 0x00F6
+ #define ETH_P_CAIF 0x00F7
+ #define ETH_P_XDSA 0x00F8
++#define ETH_P_MAP 0x00F9
+
+ struct ethhdr {
+ uint8_t h_dest[ETH_ALEN];
+diff --git a/include/netinet/in.h b/include/netinet/in.h
+index f18b478d..192679a6 100644
+--- a/include/netinet/in.h
++++ b/include/netinet/in.h
+@@ -363,6 +363,7 @@ struct ip6_mtuinfo {
+ #define IPV6_TRANSPARENT 75
+ #define IPV6_UNICAST_IF 76
+ #define IPV6_RECVFRAGSIZE 77
++#define IPV6_FREEBIND 78
+
+ #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+ #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
+diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h
+index 4d20936a..1e2acfbf 100644
+--- a/include/netinet/tcp.h
++++ b/include/netinet/tcp.h
+@@ -34,6 +34,8 @@
+ #define TCP_FASTOPEN_CONNECT 30
+ #define TCP_ULP 31
+ #define TCP_MD5SIG_EXT 32
++#define TCP_FASTOPEN_KEY 33
++#define TCP_FASTOPEN_NO_COOKIE 34
+
+ #define TCP_ESTABLISHED 1
+ #define TCP_SYN_SENT 2
+@@ -54,6 +56,16 @@ enum {
+ TCP_NLA_SNDBUF_LIMITED,
+ TCP_NLA_DATA_SEGS_OUT,
+ TCP_NLA_TOTAL_RETRANS,
++ TCP_NLA_PACING_RATE,
++ TCP_NLA_DELIVERY_RATE,
++ TCP_NLA_SND_CWND,
++ TCP_NLA_REORDERING,
++ TCP_NLA_MIN_RTT,
++ TCP_NLA_RECUR_RETRANS,
++ TCP_NLA_DELIVERY_RATE_APP_LMT,
++ TCP_NLA_SNDQ_SIZE,
++ TCP_NLA_CA_STATE,
++ TCP_NLA_SND_SSTHRESH,
+ };
+
+ #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+@@ -220,6 +232,14 @@ struct tcp_md5sig {
+ uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN];
+ };
+
++struct tcp_diag_md5sig {
++ uint8_t tcpm_family;
++ uint8_t tcpm_prefixlen;
++ uint16_t tcpm_keylen;
++ uint32_t tcpm_addr[4];
++ uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN];
++};
++
+ struct tcp_repair_window {
+ uint32_t snd_wl1;
+ uint32_t snd_wnd;
+diff --git a/include/signal.h b/include/signal.h
+index 2c8b3d55..a4f85cca 100644
+--- a/include/signal.h
++++ b/include/signal.h
+@@ -210,7 +210,7 @@ int sigpending(sigset_t *);
+ int sigwait(const sigset_t *__restrict, int *__restrict);
+ int sigwaitinfo(const sigset_t *__restrict, siginfo_t *__restrict);
+ int sigtimedwait(const sigset_t *__restrict, siginfo_t *__restrict, const struct timespec *__restrict);
+-int sigqueue(pid_t, int, const union sigval);
++int sigqueue(pid_t, int, union sigval);
+
+ int pthread_sigmask(int, const sigset_t *__restrict, sigset_t *__restrict);
+ int pthread_kill(pthread_t, int);
+@@ -231,6 +231,8 @@ int sigrelse(int);
+ void (*sigset(int, void (*)(int)))(int);
+ #define TRAP_BRKPT 1
+ #define TRAP_TRACE 2
++#define TRAP_BRANCH 3
++#define TRAP_HWBKPT 4
+ #define POLL_IN 1
+ #define POLL_OUT 2
+ #define POLL_MSG 3
+diff --git a/include/stdio.h b/include/stdio.h
+index 7c4f9ee4..afadd912 100644
+--- a/include/stdio.h
++++ b/include/stdio.h
+@@ -49,6 +49,7 @@ extern "C" {
+
+ typedef union _G_fpos64_t {
+ char __opaque[16];
++ long long __lldata;
+ double __align;
+ } fpos_t;
+
+diff --git a/include/stdlib.h b/include/stdlib.h
+index 42ca8336..4bbaded0 100644
+--- a/include/stdlib.h
++++ b/include/stdlib.h
+@@ -39,14 +39,18 @@ void *malloc (size_t);
+ void *calloc (size_t, size_t);
+ void *realloc (void *, size_t);
+ void free (void *);
++#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L
+ void *aligned_alloc(size_t, size_t);
++#endif
+
+ _Noreturn void abort (void);
+ int atexit (void (*) (void));
+ _Noreturn void exit (int);
+ _Noreturn void _Exit (int);
++#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L
+ int at_quick_exit (void (*) (void));
+ _Noreturn void quick_exit (int);
++#endif
+
+ char *getenv (const char *);
+
+@@ -100,7 +104,6 @@ int posix_memalign (void **, size_t, size_t);
+ int setenv (const char *, const char *, int);
+ int unsetenv (const char *);
+ int mkstemp (char *);
+-int mkostemp (char *, int);
+ char *mkdtemp (char *);
+ int getsubopt (char **, char *const *, char **);
+ int rand_r (unsigned *);
+@@ -138,6 +141,7 @@ void lcong48 (unsigned short [7]);
+ #include <alloca.h>
+ char *mktemp (char *);
+ int mkstemps (char *, int);
++int mkostemp (char *, int);
+ int mkostemps (char *, int, int);
+ void *valloc (size_t);
+ void *memalign(size_t, size_t);
+diff --git a/include/string.h b/include/string.h
+index ce1dc300..795a2abc 100644
+--- a/include/string.h
++++ b/include/string.h
+@@ -82,6 +82,7 @@ void *memccpy (void *__restrict, const void *__restrict, int, size_t);
+ char *strsep(char **, const char *);
+ size_t strlcat (char *, const char *, size_t);
+ size_t strlcpy (char *, const char *, size_t);
++void explicit_bzero (void *, size_t);
+ #endif
+
+ #ifdef _GNU_SOURCE
+diff --git a/include/sys/epoll.h b/include/sys/epoll.h
+index ffe2311f..ac81a841 100644
+--- a/include/sys/epoll.h
++++ b/include/sys/epoll.h
+@@ -21,6 +21,7 @@ enum EPOLL_EVENTS { __EPOLL_DUMMY };
+ #define EPOLLPRI 0x002
+ #define EPOLLOUT 0x004
+ #define EPOLLRDNORM 0x040
++#define EPOLLNVAL 0x020
+ #define EPOLLRDBAND 0x080
+ #define EPOLLWRNORM 0x100
+ #define EPOLLWRBAND 0x200
+diff --git a/include/sys/kd.h b/include/sys/kd.h
+index 793fd59f..42122b9c 100644
+--- a/include/sys/kd.h
++++ b/include/sys/kd.h
+@@ -1,8 +1 @@
+-#ifndef _SYS_KD_H
+-#define _SYS_KD_H
+-
+-#define _LINUX_TYPES_H
+-#include <linux/kd.h>
+-#undef _LINUX_TYPES_H
+-
+-#endif
++#include <bits/kd.h>
+diff --git a/include/sys/mman.h b/include/sys/mman.h
+index 8a5149c9..99d02a2e 100644
+--- a/include/sys/mman.h
++++ b/include/sys/mman.h
+@@ -20,6 +20,7 @@ extern "C" {
+
+ #define MAP_SHARED 0x01
+ #define MAP_PRIVATE 0x02
++#define MAP_SHARED_VALIDATE 0x03
+ #define MAP_TYPE 0x0f
+ #define MAP_FIXED 0x10
+ #define MAP_ANON 0x20
+@@ -33,8 +34,23 @@ extern "C" {
+ #define MAP_NONBLOCK 0x10000
+ #define MAP_STACK 0x20000
+ #define MAP_HUGETLB 0x40000
++#define MAP_SYNC 0x80000
++#define MAP_FIXED_NOREPLACE 0x100000
+ #define MAP_FILE 0
+
++#define MAP_HUGE_SHIFT 26
++#define MAP_HUGE_MASK 0x3f
++#define MAP_HUGE_64KB (16 << 26)
++#define MAP_HUGE_512KB (19 << 26)
++#define MAP_HUGE_1MB (20 << 26)
++#define MAP_HUGE_2MB (21 << 26)
++#define MAP_HUGE_8MB (23 << 26)
++#define MAP_HUGE_16MB (24 << 26)
++#define MAP_HUGE_256MB (28 << 26)
++#define MAP_HUGE_1GB (30 << 26)
++#define MAP_HUGE_2GB (31 << 26)
++#define MAP_HUGE_16GB (34U << 26)
++
+ #define PROT_NONE 0
+ #define PROT_READ 1
+ #define PROT_WRITE 2
+@@ -72,10 +88,23 @@ extern "C" {
+ #define MADV_NOHUGEPAGE 15
+ #define MADV_DONTDUMP 16
+ #define MADV_DODUMP 17
++#define MADV_WIPEONFORK 18
++#define MADV_KEEPONFORK 19
+ #define MADV_HWPOISON 100
+ #define MADV_SOFT_OFFLINE 101
+ #endif
+
++#ifdef _GNU_SOURCE
++#define MREMAP_MAYMOVE 1
++#define MREMAP_FIXED 2
++
++#define MLOCK_ONFAULT 0x01
++
++#define MFD_CLOEXEC 0x0001U
++#define MFD_ALLOW_SEALING 0x0002U
++#define MFD_HUGETLB 0x0004U
++#endif
++
+ #include <bits/mman.h>
+
+ void *mmap (void *, size_t, int, int, int, off_t);
+@@ -92,14 +121,13 @@ int mlockall (int);
+ int munlockall (void);
+
+ #ifdef _GNU_SOURCE
+-#define MREMAP_MAYMOVE 1
+-#define MREMAP_FIXED 2
+ void *mremap (void *, size_t, size_t, int, ...);
+ int remap_file_pages (void *, size_t, int, size_t, int);
++int memfd_create (const char *, unsigned);
++int mlock2 (const void *, size_t, unsigned);
+ #endif
+
+ #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+-#define MLOCK_ONFAULT 0x01
+ int madvise (void *, size_t, int);
+ int mincore (void *, size_t, unsigned char *);
+ #endif
+diff --git a/include/sys/msg.h b/include/sys/msg.h
+index 139f22b7..be6afc34 100644
+--- a/include/sys/msg.h
++++ b/include/sys/msg.h
+@@ -27,6 +27,7 @@ typedef unsigned long msglen_t;
+
+ #define MSG_STAT 11
+ #define MSG_INFO 12
++#define MSG_STAT_ANY 13
+
+ struct msginfo {
+ int msgpool, msgmap, msgmax, msgmnb, msgmni, msgssz, msgtql;
+diff --git a/include/sys/prctl.h b/include/sys/prctl.h
+index 24f4f8bd..af76408c 100644
+--- a/include/sys/prctl.h
++++ b/include/sys/prctl.h
+@@ -130,6 +130,21 @@ struct prctl_mm_map {
+ #define PR_CAP_AMBIENT_LOWER 3
+ #define PR_CAP_AMBIENT_CLEAR_ALL 4
+
++#define PR_SVE_SET_VL 50
++#define PR_SVE_SET_VL_ONEXEC (1 << 18)
++#define PR_SVE_GET_VL 51
++#define PR_SVE_VL_LEN_MASK 0xffff
++#define PR_SVE_VL_INHERIT (1 << 17)
++
++#define PR_GET_SPECULATION_CTRL 52
++#define PR_SET_SPECULATION_CTRL 53
++#define PR_SPEC_STORE_BYPASS 0
++#define PR_SPEC_NOT_AFFECTED 0
++#define PR_SPEC_PRCTL (1UL << 0)
++#define PR_SPEC_ENABLE (1UL << 1)
++#define PR_SPEC_DISABLE (1UL << 2)
++#define PR_SPEC_FORCE_DISABLE (1UL << 3)
++
+ int prctl (int, ...);
+
+ #ifdef __cplusplus
+diff --git a/include/sys/ptrace.h b/include/sys/ptrace.h
+index d9d45408..229e1f3d 100644
+--- a/include/sys/ptrace.h
++++ b/include/sys/ptrace.h
+@@ -40,6 +40,7 @@ extern "C" {
+ #define PTRACE_GETSIGMASK 0x420a
+ #define PTRACE_SETSIGMASK 0x420b
+ #define PTRACE_SECCOMP_GET_FILTER 0x420c
++#define PTRACE_SECCOMP_GET_METADATA 0x420d
+
+ #define PT_READ_I PTRACE_PEEKTEXT
+ #define PT_READ_D PTRACE_PEEKDATA
+@@ -83,15 +84,23 @@ extern "C" {
+ #define PTRACE_EVENT_VFORK_DONE 5
+ #define PTRACE_EVENT_EXIT 6
+ #define PTRACE_EVENT_SECCOMP 7
++#define PTRACE_EVENT_STOP 128
+
+ #define PTRACE_PEEKSIGINFO_SHARED 1
+
+-struct ptrace_peeksiginfo_args {
++#include <bits/ptrace.h>
++
++struct __ptrace_peeksiginfo_args {
+ uint64_t off;
+ uint32_t flags;
+ int32_t nr;
+ };
+
++struct __ptrace_seccomp_metadata {
++ uint64_t filter_off;
++ uint64_t flags;
++};
++
+ long ptrace(int, ...);
+
+ #ifdef __cplusplus
+diff --git a/include/sys/random.h b/include/sys/random.h
+new file mode 100644
+index 00000000..4ee7bf2c
+--- /dev/null
++++ b/include/sys/random.h
+@@ -0,0 +1,19 @@
++#ifndef _SYS_RANDOM_H
++#define _SYS_RANDOM_H
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define __NEED_size_t
++#define __NEED_ssize_t
++#include <bits/alltypes.h>
++
++#define GRND_NONBLOCK 0x0001
++#define GRND_RANDOM 0x0002
++
++ssize_t getrandom(void *, size_t, unsigned);
++
++#ifdef __cplusplus
++}
++#endif
++#endif
+diff --git a/include/sys/sem.h b/include/sys/sem.h
+index e7c36980..61cdb83d 100644
+--- a/include/sys/sem.h
++++ b/include/sys/sem.h
+@@ -33,6 +33,7 @@ extern "C" {
+
+ #define SEM_STAT 18
+ #define SEM_INFO 19
++#define SEM_STAT_ANY 20
+
+ struct seminfo {
+ int semmap;
+diff --git a/include/sys/shm.h b/include/sys/shm.h
+index 67be822b..662fde59 100644
+--- a/include/sys/shm.h
++++ b/include/sys/shm.h
+@@ -35,11 +35,25 @@ extern "C" {
+ #define SHM_UNLOCK 12
+ #define SHM_STAT 13
+ #define SHM_INFO 14
++#define SHM_STAT_ANY 15
+ #define SHM_DEST 01000
+ #define SHM_LOCKED 02000
+ #define SHM_HUGETLB 04000
+ #define SHM_NORESERVE 010000
+
++#define SHM_HUGE_SHIFT 26
++#define SHM_HUGE_MASK 0x3f
++#define SHM_HUGE_64KB (16 << 26)
++#define SHM_HUGE_512KB (19 << 26)
++#define SHM_HUGE_1MB (20 << 26)
++#define SHM_HUGE_2MB (21 << 26)
++#define SHM_HUGE_8MB (23 << 26)
++#define SHM_HUGE_16MB (24 << 26)
++#define SHM_HUGE_256MB (28 << 26)
++#define SHM_HUGE_1GB (30 << 26)
++#define SHM_HUGE_2GB (31 << 26)
++#define SHM_HUGE_16GB (34U << 26)
++
+ typedef unsigned long shmatt_t;
+
+ void *shmat(int, const void *, int);
+diff --git a/include/sys/socket.h b/include/sys/socket.h
+index 051d20e0..14be6e99 100644
+--- a/include/sys/socket.h
++++ b/include/sys/socket.h
+@@ -108,7 +108,8 @@ struct linger {
+ #define PF_VSOCK 40
+ #define PF_KCM 41
+ #define PF_QIPCRTR 42
+-#define PF_MAX 43
++#define PF_SMC 43
++#define PF_MAX 44
+
+ #define AF_UNSPEC PF_UNSPEC
+ #define AF_LOCAL PF_LOCAL
+@@ -156,6 +157,7 @@ struct linger {
+ #define AF_VSOCK PF_VSOCK
+ #define AF_KCM PF_KCM
+ #define AF_QIPCRTR PF_QIPCRTR
++#define AF_SMC PF_SMC
+ #define AF_MAX PF_MAX
+
+ #ifndef SO_DEBUG
+@@ -181,6 +183,7 @@ struct linger {
+ #define SO_RCVTIMEO 20
+ #define SO_SNDTIMEO 21
+ #define SO_ACCEPTCONN 30
++#define SO_PEERSEC 31
+ #define SO_SNDBUFFORCE 32
+ #define SO_RCVBUFFORCE 33
+ #define SO_PROTOCOL 38
+@@ -201,7 +204,6 @@ struct linger {
+ #define SO_TIMESTAMP 29
+ #define SCM_TIMESTAMP SO_TIMESTAMP
+
+-#define SO_PEERSEC 31
+ #define SO_PASSSEC 34
+ #define SO_TIMESTAMPNS 35
+ #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
+@@ -230,6 +232,7 @@ struct linger {
+ #define SO_COOKIE 57
+ #define SCM_TIMESTAMPING_PKTINFO 58
+ #define SO_PEERGROUPS 59
++#define SO_ZEROCOPY 60
+
+ #ifndef SOL_SOCKET
+ #define SOL_SOCKET 1
+@@ -261,6 +264,7 @@ struct linger {
+ #define SOL_ALG 279
+ #define SOL_NFC 280
+ #define SOL_KCM 281
++#define SOL_TLS 282
+
+ #define SOMAXCONN 128
+
+@@ -282,6 +286,7 @@ struct linger {
+ #define MSG_MORE 0x8000
+ #define MSG_WAITFORONE 0x10000
+ #define MSG_BATCH 0x40000
++#define MSG_ZEROCOPY 0x4000000
+ #define MSG_FASTOPEN 0x20000000
+ #define MSG_CMSG_CLOEXEC 0x40000000
+
+diff --git a/include/sys/soundcard.h b/include/sys/soundcard.h
+index fade986f..5ca77646 100644
+--- a/include/sys/soundcard.h
++++ b/include/sys/soundcard.h
+@@ -1 +1 @@
+-#include <linux/soundcard.h>
++#include <bits/soundcard.h>
+diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h
+index e0839eca..ef07d684 100644
+--- a/include/sys/statvfs.h
++++ b/include/sys/statvfs.h
+@@ -42,6 +42,7 @@ int fstatvfs (int, struct statvfs *);
+ #define ST_IMMUTABLE 512
+ #define ST_NOATIME 1024
+ #define ST_NODIRATIME 2048
++#define ST_RELATIME 4096
+
+ #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+ #define statvfs64 statvfs
+diff --git a/include/sys/vt.h b/include/sys/vt.h
+index 834abfbc..5000de49 100644
+--- a/include/sys/vt.h
++++ b/include/sys/vt.h
+@@ -1 +1 @@
+-#include <linux/vt.h>
++#include <bits/vt.h>
+diff --git a/include/tar.h b/include/tar.h
+index be589842..2eba66ec 100644
+--- a/include/tar.h
++++ b/include/tar.h
+@@ -1,9 +1,13 @@
+ #ifndef _TAR_H
+ #define _TAR_H
+
++#include <features.h>
++
+ #define TSUID 04000
+ #define TSGID 02000
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+ #define TSVTX 01000
++#endif
+ #define TUREAD 00400
+ #define TUWRITE 00200
+ #define TUEXEC 00100
+diff --git a/include/time.h b/include/time.h
+index 672b3fc3..c5946dd0 100644
+--- a/include/time.h
++++ b/include/time.h
+@@ -58,11 +58,14 @@ struct tm *gmtime (const time_t *);
+ struct tm *localtime (const time_t *);
+ char *asctime (const struct tm *);
+ char *ctime (const time_t *);
+-int timespec_get(struct timespec *, int);
+
+-#define CLOCKS_PER_SEC 1000000L
++#if __STDC_VERSION__ >= 201112L
++int timespec_get(struct timespec *, int);
+
+ #define TIME_UTC 1
++#endif
++
++#define CLOCKS_PER_SEC 1000000L
+
+ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
+diff --git a/include/uchar.h b/include/uchar.h
+index 8dabf1ed..7e5c4d40 100644
+--- a/include/uchar.h
++++ b/include/uchar.h
+@@ -3,7 +3,9 @@
+
+ #ifdef __cplusplus
+ extern "C" {
+-#else
++#endif
++
++#if __cplusplus < 201103L
+ typedef unsigned short char16_t;
+ typedef unsigned char32_t;
+ #endif
+diff --git a/include/unistd.h b/include/unistd.h
+index 09190af4..1bdd3292 100644
+--- a/include/unistd.h
++++ b/include/unistd.h
+@@ -128,12 +128,11 @@ long fpathconf(int, int);
+ long sysconf(int);
+ size_t confstr(int, char *, size_t);
+
++#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+ #define F_ULOCK 0
+ #define F_LOCK 1
+ #define F_TLOCK 2
+ #define F_TEST 3
+-
+-#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+ int setreuid(uid_t, uid_t);
+ int setregid(gid_t, gid_t);
+ int lockf(int, int, off_t);
+@@ -176,6 +175,7 @@ int acct(const char *);
+ long syscall(long, ...);
+ int execvpe(const char *, char *const [], char *const []);
+ int issetugid(void);
++int getentropy(void *, size_t);
+ #endif
+
+ #ifdef _GNU_SOURCE
+@@ -274,6 +274,7 @@ int eaccess(const char *, int);
+ #define _PC_ALLOC_SIZE_MIN 18
+ #define _PC_SYMLINK_MAX 19
+ #define _PC_2_SYMLINKS 20
++#define _PC_TIMESTAMP_RESOLUTION 21
+
+ #define _SC_ARG_MAX 0
+ #define _SC_CHILD_MAX 1
+@@ -417,6 +418,7 @@ int eaccess(const char *, int);
+ #define _SC_XOPEN_STREAMS 246
+ #define _SC_THREAD_ROBUST_PRIO_INHERIT 247
+ #define _SC_THREAD_ROBUST_PRIO_PROTECT 248
++#define _SC_XOPEN_UUCP 249
+
+ #define _CS_PATH 0
+ #define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 1
+@@ -459,6 +461,8 @@ int eaccess(const char *, int);
+ #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/ldso/dynlink.c b/ldso/dynlink.c
+index 9bf6924b..87281ddb 100644
+--- a/ldso/dynlink.c
++++ b/ldso/dynlink.c
+@@ -133,6 +133,9 @@ static struct dso *const nodeps_dummy;
+
+ struct debug *_dl_debug_addr = &debug;
+
++__attribute__((__visibility__("hidden")))
++extern int __malloc_replaced;
++
+ __attribute__((__visibility__("hidden")))
+ void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0;
+
+@@ -158,10 +161,26 @@ static void *laddr(const struct dso *p, size_t v)
+ for (j=0; v-p->loadmap->segs[j].p_vaddr >= p->loadmap->segs[j].p_memsz; j++);
+ return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
+ }
++static void *laddr_pg(const struct dso *p, size_t v)
++{
++ size_t j=0;
++ size_t pgsz = PAGE_SIZE;
++ if (!p->loadmap) return p->base + v;
++ for (j=0; ; j++) {
++ size_t a = p->loadmap->segs[j].p_vaddr;
++ size_t b = a + p->loadmap->segs[j].p_memsz;
++ a &= -pgsz;
++ b += pgsz-1;
++ b &= -pgsz;
++ if (v-a<b-a) break;
++ }
++ return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
++}
+ #define fpaddr(p, v) ((void (*)())&(struct funcdesc){ \
+ laddr(p, v), (p)->got })
+ #else
+ #define laddr(p, v) (void *)((p)->base + (v))
++#define laddr_pg(p, v) laddr(p, v)
+ #define fpaddr(p, v) ((void (*)())laddr(p, v))
+ #endif
+
+@@ -366,6 +385,14 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
+ sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0;
+ tls_val = def.sym ? def.sym->st_value : 0;
+
++ if ((type == REL_TPOFF || type == REL_TPOFF_NEG)
++ && runtime && def.dso->tls_id > static_tls_cnt) {
++ error("Error relocating %s: %s: initial-exec TLS "
++ "resolves to dynamic definition in %s",
++ dso->name, name, def.dso->name);
++ longjmp(*rtld_fail, 1);
++ }
++
+ switch(type) {
+ case REL_NONE:
+ break;
+@@ -419,7 +446,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
+ #endif
+ case REL_TLSDESC:
+ if (stride<3) addend = reloc_addr[1];
+- if (runtime && def.dso->tls_id >= static_tls_cnt) {
++ if (runtime && def.dso->tls_id > static_tls_cnt) {
+ struct td_index *new = malloc(sizeof *new);
+ if (!new) {
+ error(
+@@ -476,23 +503,16 @@ static void redo_lazy_relocs()
+ /* A huge hack: to make up for the wastefulness of shared libraries
+ * needing at least a page of dirty memory even if they have no global
+ * data, we reclaim the gaps at the beginning and end of writable maps
+- * and "donate" them to the heap by setting up minimal malloc
+- * structures and then freeing them. */
++ * and "donate" them to the heap. */
+
+ static void reclaim(struct dso *dso, size_t start, size_t end)
+ {
+- size_t *a, *z;
++ void __malloc_donate(char *, char *);
+ if (start >= dso->relro_start && start < dso->relro_end) start = dso->relro_end;
+ if (end >= dso->relro_start && end < dso->relro_end) end = dso->relro_start;
+- start = start + 6*sizeof(size_t)-1 & -4*sizeof(size_t);
+- end = (end & -4*sizeof(size_t)) - 2*sizeof(size_t);
+- if (start>end || end-start < 4*sizeof(size_t)) return;
+- a = laddr(dso, start);
+- z = laddr(dso, end);
+- a[-2] = 1;
+- a[-1] = z[0] = end-start + 2*sizeof(size_t) | 1;
+- z[1] = 1;
+- free(a);
++ if (start >= end) return;
++ char *base = laddr_pg(dso, start);
++ __malloc_donate(base, base+(end-start));
+ }
+
+ static void reclaim_gaps(struct dso *dso)
+@@ -500,7 +520,6 @@ static void reclaim_gaps(struct dso *dso)
+ Phdr *ph = dso->phdr;
+ size_t phcnt = dso->phnum;
+
+- if (DL_FDPIC) return; // FIXME
+ for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {
+ if (ph->p_type!=PT_LOAD) continue;
+ if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
+@@ -695,18 +714,17 @@ static void *map_library(int fd, struct dso *dso)
+ dso->phnum = eh->e_phnum;
+ dso->phentsize = eh->e_phentsize;
+ }
+- /* Reuse the existing mapping for the lowest-address LOAD */
+- if ((ph->p_vaddr & -PAGE_SIZE) == addr_min && !DL_NOMMU_SUPPORT)
+- continue;
+ this_min = ph->p_vaddr & -PAGE_SIZE;
+ this_max = ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE;
+ off_start = ph->p_offset & -PAGE_SIZE;
+ prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
+ ((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
+ ((ph->p_flags&PF_X) ? PROT_EXEC : 0));
+- if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
+- goto error;
+- if (ph->p_memsz > ph->p_filesz) {
++ /* Reuse the existing mapping for the lowest-address LOAD */
++ if ((ph->p_vaddr & -PAGE_SIZE) != addr_min || DL_NOMMU_SUPPORT)
++ if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
++ goto error;
++ if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) {
+ size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
+ size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
+ memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
+@@ -1583,8 +1601,9 @@ _Noreturn void __dls3(size_t *sp)
+ libc.tls_head = tls_tail = &app.tls;
+ app.tls_id = tls_cnt = 1;
+ #ifdef TLS_ABOVE_TP
+- app.tls.offset = 0;
+- tls_offset = app.tls.size
++ app.tls.offset = GAP_ABOVE_TP;
++ app.tls.offset += -GAP_ABOVE_TP & (app.tls.align-1);
++ tls_offset = app.tls.offset + app.tls.size
+ + ( -((uintptr_t)app.tls.image + app.tls.size)
+ & (app.tls.align-1) );
+ #else
+@@ -1683,6 +1702,12 @@ _Noreturn void __dls3(size_t *sp)
+ if (ldso_fail) _exit(127);
+ if (ldd_mode) _exit(0);
+
++ /* Determine if malloc was interposed by a replacement implementation
++ * so that calloc and the memalign family can harden against the
++ * possibility of incomplete replacement. */
++ if (find_sym(head, "malloc", 1).dso != &ldso)
++ __malloc_replaced = 1;
++
+ /* Switch to runtime mode: any further failures in the dynamic
+ * linker are a reportable failure rather than a fatal startup
+ * error. */
+@@ -1861,8 +1886,17 @@ static void *addr2dso(size_t a)
+ return p;
+ }
+ } else {
++ Phdr *ph = p->phdr;
++ size_t phcnt = p->phnum;
++ size_t entsz = p->phentsize;
++ size_t base = (size_t)p->base;
++ for (; phcnt--; ph=(void *)((char *)ph+entsz)) {
++ if (ph->p_type != PT_LOAD) continue;
++ if (a-base-ph->p_vaddr < ph->p_memsz)
++ return p;
++ }
+ if (a-(size_t)p->map < p->map_len)
+- return p;
++ return 0;
+ }
+ }
+ return 0;
+@@ -1926,16 +1960,18 @@ failed:
+ return 0;
+ }
+
+-int dladdr(const void *addr, Dl_info *info)
++int dladdr(const void *addr_arg, Dl_info *info)
+ {
++ size_t addr = (size_t)addr_arg;
+ struct dso *p;
+ Sym *sym, *bestsym;
+ uint32_t nsym;
+ char *strings;
+- void *best = 0;
++ size_t best = 0;
++ size_t besterr = -1;
+
+ pthread_rwlock_rdlock(&lock);
+- p = addr2dso((size_t)addr);
++ p = addr2dso(addr);
+ pthread_rwlock_unlock(&lock);
+
+ if (!p) return 0;
+@@ -1945,11 +1981,12 @@ int dladdr(const void *addr, Dl_info *info)
+ nsym = count_syms(p);
+
+ if (DL_FDPIC) {
+- size_t idx = ((size_t)addr-(size_t)p->funcdescs)
++ size_t idx = (addr-(size_t)p->funcdescs)
+ / sizeof(*p->funcdescs);
+ if (idx < nsym && (sym[idx].st_info&0xf) == STT_FUNC) {
+- best = p->funcdescs + idx;
++ best = (size_t)(p->funcdescs + idx);
+ bestsym = sym + idx;
++ besterr = 0;
+ }
+ }
+
+@@ -1957,25 +1994,35 @@ int dladdr(const void *addr, Dl_info *info)
+ if (sym->st_value
+ && (1<<(sym->st_info&0xf) & OK_TYPES)
+ && (1<<(sym->st_info>>4) & OK_BINDS)) {
+- void *symaddr = laddr(p, sym->st_value);
+- if (symaddr > addr || symaddr < best)
++ size_t symaddr = (size_t)laddr(p, sym->st_value);
++ if (symaddr > addr || symaddr <= best)
+ continue;
+ best = symaddr;
+ bestsym = sym;
++ besterr = addr - symaddr;
+ if (addr == symaddr)
+ break;
+ }
+ }
+
+- if (!best) return 0;
+-
+- if (DL_FDPIC && (bestsym->st_info&0xf) == STT_FUNC)
+- best = p->funcdescs + (bestsym - p->syms);
++ if (bestsym && besterr > bestsym->st_size-1) {
++ best = 0;
++ bestsym = 0;
++ }
+
+ info->dli_fname = p->name;
+ info->dli_fbase = p->map;
++
++ if (!best) {
++ info->dli_sname = 0;
++ info->dli_saddr = 0;
++ return 1;
++ }
++
++ if (DL_FDPIC && (bestsym->st_info&0xf) == STT_FUNC)
++ best = (size_t)(p->funcdescs + (bestsym - p->syms));
+ info->dli_sname = strings + bestsym->st_name;
+- info->dli_saddr = best;
++ info->dli_saddr = (void *)best;
+
+ return 1;
+ }
+diff --git a/src/complex/casin.c b/src/complex/casin.c
+index dfdda988..01ed6184 100644
+--- a/src/complex/casin.c
++++ b/src/complex/casin.c
+@@ -12,5 +12,6 @@ double complex casin(double complex z)
+ x = creal(z);
+ y = cimag(z);
+ w = CMPLX(1.0 - (x - y)*(x + y), -2.0*x*y);
+- return clog(CMPLX(-y, x) + csqrt(w));
++ double complex r = clog(CMPLX(-y, x) + csqrt(w));
++ return CMPLX(cimag(r), -creal(r));
+ }
+diff --git a/src/complex/casinf.c b/src/complex/casinf.c
+index 93f0e335..4fcb76fc 100644
+--- a/src/complex/casinf.c
++++ b/src/complex/casinf.c
+@@ -10,5 +10,6 @@ float complex casinf(float complex z)
+ x = crealf(z);
+ y = cimagf(z);
+ w = CMPLXF(1.0 - (x - y)*(x + y), -2.0*x*y);
+- return clogf(CMPLXF(-y, x) + csqrtf(w));
++ float complex r = clogf(CMPLXF(-y, x) + csqrtf(w));
++ return CMPLXF(cimagf(r), -crealf(r));
+ }
+diff --git a/src/complex/casinl.c b/src/complex/casinl.c
+index 0916c60f..3b7ceba7 100644
+--- a/src/complex/casinl.c
++++ b/src/complex/casinl.c
+@@ -15,6 +15,7 @@ long double complex casinl(long double complex z)
+ x = creall(z);
+ y = cimagl(z);
+ w = CMPLXL(1.0 - (x - y)*(x + y), -2.0*x*y);
+- return clogl(CMPLXL(-y, x) + csqrtl(w));
++ long double complex r = clogl(CMPLXL(-y, x) + csqrtl(w));
++ return CMPLXL(cimagl(r), -creall(r));
+ }
+ #endif
+diff --git a/src/complex/catan.c b/src/complex/catan.c
+index 39ce6cf2..7dc2afeb 100644
+--- a/src/complex/catan.c
++++ b/src/complex/catan.c
+@@ -91,29 +91,17 @@ double complex catan(double complex z)
+ x = creal(z);
+ y = cimag(z);
+
+- if (x == 0.0 && y > 1.0)
+- goto ovrf;
+-
+ x2 = x * x;
+ a = 1.0 - x2 - (y * y);
+- if (a == 0.0)
+- goto ovrf;
+
+ t = 0.5 * atan2(2.0 * x, a);
+ w = _redupi(t);
+
+ t = y - 1.0;
+ a = x2 + (t * t);
+- if (a == 0.0)
+- goto ovrf;
+
+ t = y + 1.0;
+ a = (x2 + t * t)/a;
+- w = w + (0.25 * log(a)) * I;
+- return w;
+-
+-ovrf:
+- // FIXME
+- w = MAXNUM + MAXNUM * I;
++ w = CMPLX(w, 0.25 * log(a));
+ return w;
+ }
+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;
+ }
+diff --git a/src/conf/fpathconf.c b/src/conf/fpathconf.c
+index 8eb037e6..7e4b8003 100644
+--- a/src/conf/fpathconf.c
++++ b/src/conf/fpathconf.c
+@@ -24,8 +24,9 @@ long fpathconf(int fd, int name)
+ [_PC_REC_MIN_XFER_SIZE] = 4096,
+ [_PC_REC_XFER_ALIGN] = 4096,
+ [_PC_ALLOC_SIZE_MIN] = 4096,
+- [_PC_SYMLINK_MAX] = SYMLINK_MAX,
+- [_PC_2_SYMLINKS] = 1
++ [_PC_SYMLINK_MAX] = -1,
++ [_PC_2_SYMLINKS] = 1,
++ [_PC_TIMESTAMP_RESOLUTION] = 1000000,
+ };
+ if (name >= sizeof(values)/sizeof(values[0])) {
+ errno = EINVAL;
+diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c
+index 9ce330a5..58830a09 100644
+--- a/src/conf/sysconf.c
++++ b/src/conf/sysconf.c
+@@ -164,6 +164,7 @@ long sysconf(int name)
+ [_SC_XOPEN_STREAMS] = JT_ZERO,
+ [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1,
+ [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1,
++ [_SC_XOPEN_UUCP] = -1,
+ };
+
+ if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) {
+diff --git a/src/dirent/__dirent.h b/src/dirent/__dirent.h
+index 101b0368..828a5f17 100644
+--- a/src/dirent/__dirent.h
++++ b/src/dirent/__dirent.h
+@@ -1,9 +1,11 @@
+ struct __dirstream
+ {
+- int fd;
+ off_t tell;
++ int fd;
+ int buf_pos;
+ int buf_end;
+ volatile int lock[1];
++ /* Any changes to this struct must preserve the property:
++ * offsetof(struct __dirent, buf) % sizeof(off_t) == 0 */
+ char buf[2048];
+ };
+diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c
+index 2cf0632c..eef92f79 100644
+--- a/src/dirent/readdir.c
++++ b/src/dirent/readdir.c
+@@ -1,10 +1,12 @@
+ #include <dirent.h>
+ #include <errno.h>
++#include <stddef.h>
+ #include "__dirent.h"
+ #include "syscall.h"
+ #include "libc.h"
+
+-int __getdents(int, struct dirent *, size_t);
++typedef char dirstream_buf_alignment_check[1-2*(int)(
++ offsetof(struct __dirstream, buf) % sizeof(off_t))];
+
+ struct dirent *readdir(DIR *dir)
+ {
+diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
+index b125eb1f..31d324a8 100644
+--- a/src/env/__init_tls.c
++++ b/src/env/__init_tls.c
+@@ -15,7 +15,8 @@ int __init_tp(void *p)
+ int r = __set_thread_area(TP_ADJ(p));
+ if (r < 0) return -1;
+ if (!r) libc.can_do_threads = 1;
+- td->tid = __syscall(SYS_set_tid_address, &td->tid);
++ td->detach_state = DT_JOINABLE;
++ td->tid = __syscall(SYS_set_tid_address, &td->detach_state);
+ td->locale = &libc.global_locale;
+ td->robust_list.head = &td->robust_list.head;
+ return 0;
+@@ -103,13 +104,19 @@ static void static_init_tls(size_t *aux)
+
+ main_tls.size += (-main_tls.size - (uintptr_t)main_tls.image)
+ & (main_tls.align-1);
+- if (main_tls.align < MIN_TLS_ALIGN) main_tls.align = MIN_TLS_ALIGN;
+-#ifndef TLS_ABOVE_TP
++#ifdef TLS_ABOVE_TP
++ main_tls.offset = GAP_ABOVE_TP;
++ main_tls.offset += -GAP_ABOVE_TP & (main_tls.align-1);
++#else
+ main_tls.offset = main_tls.size;
+ #endif
++ if (main_tls.align < MIN_TLS_ALIGN) main_tls.align = MIN_TLS_ALIGN;
+
+ libc.tls_align = main_tls.align;
+ libc.tls_size = 2*sizeof(void *) + sizeof(struct pthread)
++#ifdef TLS_ABOVE_TP
++ + main_tls.offset
++#endif
+ + main_tls.size + main_tls.align
+ + MIN_TLS_ALIGN-1 & -MIN_TLS_ALIGN;
+
+diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
+index 2d758af7..0583f686 100644
+--- a/src/env/__libc_start_main.c
++++ b/src/env/__libc_start_main.c
+@@ -42,11 +42,13 @@ void __init_libc(char **envp, char *pn)
+ && !aux[AT_SECURE]) return;
+
+ struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} };
++ int r =
+ #ifdef SYS_poll
+ __syscall(SYS_poll, pfd, 3, 0);
+ #else
+ __syscall(SYS_ppoll, pfd, 3, &(struct timespec){0}, 0, _NSIG/8);
+ #endif
++ if (r<0) a_crash();
+ for (i=0; i<3; i++) if (pfd[i].revents&POLLNVAL)
+ if (__sys_open("/dev/null", O_RDWR)<0)
+ a_crash();
+diff --git a/src/errno/__errno_location.c b/src/errno/__errno_location.c
+index 7172a1be..ad9f9241 100644
+--- a/src/errno/__errno_location.c
++++ b/src/errno/__errno_location.c
+@@ -1,3 +1,4 @@
++#include <errno.h>
+ #include "pthread_impl.h"
+
+ int *__errno_location(void)
+diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h
+index 915044b5..2f04d400 100644
+--- a/src/errno/__strerror.h
++++ b/src/errno/__strerror.h
+@@ -100,5 +100,6 @@ E(EREMOTEIO, "Remote I/O error")
+ E(EDQUOT, "Quota exceeded")
+ E(ENOMEDIUM, "No medium found")
+ E(EMEDIUMTYPE, "Wrong medium type")
++E(EMULTIHOP, "Multihop attempted")
+
+ E(0, "No error information")
+diff --git a/src/exit/abort.c b/src/exit/abort.c
+index ecc0f735..5e5a87c3 100644
+--- a/src/exit/abort.c
++++ b/src/exit/abort.c
+@@ -1,13 +1,31 @@
+ #include <stdlib.h>
+ #include <signal.h>
++#include <string.h>
+ #include "syscall.h"
+ #include "pthread_impl.h"
+ #include "atomic.h"
+
+ _Noreturn void abort(void)
+ {
++ struct sigaction abrtaction;
++ sigset_t abrtset;
++
+ raise(SIGABRT);
+ __block_all_sigs(0);
++
++ /* Unblock just SIGABRT, and set default handler */
++ sigemptyset(&abrtset);
++ sigaddset(&abrtset, SIGABRT);
++ sigprocmask(SIG_UNBLOCK, &abrtset, 0);
++
++ memset(&abrtaction, 0, sizeof(struct sigaction));
++ abrtaction.sa_handler = SIG_DFL;
++
++ sigaction(SIGABRT, &abrtaction, NULL);
++
++ raise(SIGABRT);
++
++ /* Ok, give up. */
+ a_crash();
+ raise(SIGKILL);
+ _Exit(127);
+diff --git a/src/fenv/m68k/fenv.c b/src/fenv/m68k/fenv.c
+new file mode 100644
+index 00000000..e60949d1
+--- /dev/null
++++ b/src/fenv/m68k/fenv.c
+@@ -0,0 +1,84 @@
++#include <fenv.h>
++
++#if __HAVE_68881__ || __mcffpu__
++
++static unsigned getsr()
++{
++ unsigned v;
++ __asm__ __volatile__ ("fmove.l %%fpsr,%0" : "=dm"(v));
++ return v;
++}
++
++static void setsr(unsigned v)
++{
++ __asm__ __volatile__ ("fmove.l %0,%%fpsr" : : "dm"(v));
++}
++
++static unsigned getcr()
++{
++ unsigned v;
++ __asm__ __volatile__ ("fmove.l %%fpcr,%0" : "=dm"(v));
++ return v;
++}
++
++static void setcr(unsigned v)
++{
++ __asm__ __volatile__ ("fmove.l %0,%%fpcr" : : "dm"(v));
++}
++
++int feclearexcept(int mask)
++{
++ if (mask & ~FE_ALL_EXCEPT) return -1;
++ setsr(getsr() & ~mask);
++ return 0;
++}
++
++int feraiseexcept(int mask)
++{
++ if (mask & ~FE_ALL_EXCEPT) return -1;
++ setsr(getsr() | mask);
++ return 0;
++}
++
++int fetestexcept(int mask)
++{
++ return getsr() & mask;
++}
++
++int fegetround(void)
++{
++ return getcr() & FE_UPWARD;
++}
++
++int __fesetround(int r)
++{
++ setcr((getcr() & ~FE_UPWARD) | r);
++ return 0;
++}
++
++int fegetenv(fenv_t *envp)
++{
++ envp->__control_register = getcr();
++ envp->__status_register = getsr();
++ __asm__ __volatile__ ("fmove.l %%fpiar,%0"
++ : "=dm"(envp->__instruction_address));
++ return 0;
++}
++
++int fesetenv(const fenv_t *envp)
++{
++ static const fenv_t default_env = { 0 };
++ if (envp == FE_DFL_ENV)
++ envp = &default_env;
++ setcr(envp->__control_register);
++ setsr(envp->__status_register);
++ __asm__ __volatile__ ("fmove.l %0,%%fpiar"
++ : : "dm"(envp->__instruction_address));
++ return 0;
++}
++
++#else
++
++#include "../fenv.c"
++
++#endif
+diff --git a/src/internal/atomic.h b/src/internal/atomic.h
+index ab473dd7..f938879b 100644
+--- a/src/internal/atomic.h
++++ b/src/internal/atomic.h
+@@ -251,6 +251,22 @@ static inline void a_crash()
+ }
+ #endif
+
++#ifndef a_ctz_32
++#define a_ctz_32 a_ctz_32
++static inline int a_ctz_32(uint32_t x)
++{
++#ifdef a_clz_32
++ return 31-a_clz_32(x&-x);
++#else
++ static const char debruijn32[32] = {
++ 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
++ 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
++ };
++ return debruijn32[(x&-x)*0x076be629 >> 27];
++#endif
++}
++#endif
++
+ #ifndef a_ctz_64
+ #define a_ctz_64 a_ctz_64
+ static inline int a_ctz_64(uint64_t x)
+@@ -261,22 +277,23 @@ static inline int a_ctz_64(uint64_t x)
+ 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
+ 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
+ };
+- static const char debruijn32[32] = {
+- 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
+- 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
+- };
+ if (sizeof(long) < 8) {
+ uint32_t y = x;
+ if (!y) {
+ y = x>>32;
+- return 32 + debruijn32[(y&-y)*0x076be629 >> 27];
++ return 32 + a_ctz_32(y);
+ }
+- return debruijn32[(y&-y)*0x076be629 >> 27];
++ return a_ctz_32(y);
+ }
+ return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
+ }
+ #endif
+
++static inline int a_ctz_l(unsigned long x)
++{
++ return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x);
++}
++
+ #ifndef a_clz_64
+ #define a_clz_64 a_clz_64
+ static inline int a_clz_64(uint64_t x)
+@@ -298,17 +315,4 @@ static inline int a_clz_64(uint64_t x)
+ }
+ #endif
+
+-#ifndef a_ctz_l
+-#define a_ctz_l a_ctz_l
+-static inline int a_ctz_l(unsigned long x)
+-{
+- static const char debruijn32[32] = {
+- 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
+- 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
+- };
+- if (sizeof(long) == 8) return a_ctz_64(x);
+- return debruijn32[(x&-x)*0x076be629 >> 27];
+-}
+-#endif
+-
+ #endif
+diff --git a/src/internal/libm.h b/src/internal/libm.h
+index df864111..a2505f7e 100644
+--- a/src/internal/libm.h
++++ b/src/internal/libm.h
+@@ -28,6 +28,17 @@ union ldshape {
+ uint16_t se;
+ } i;
+ };
++#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN
++/* This is the m68k variant of 80-bit long double, and this definition only works
++ * on archs where the alignment requirement of uint64_t is <= 4. */
++union ldshape {
++ long double f;
++ struct {
++ uint16_t se;
++ uint16_t pad;
++ uint64_t m;
++ } i;
++};
+ #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN
+ union ldshape {
+ long double f;
+diff --git a/src/internal/m68k/syscall.s b/src/internal/m68k/syscall.s
+new file mode 100644
+index 00000000..9972a34d
+--- /dev/null
++++ b/src/internal/m68k/syscall.s
+@@ -0,0 +1,9 @@
++.global __syscall
++.hidden __syscall
++.type __syscall,%function
++__syscall:
++ movem.l %d2-%d5,-(%sp)
++ movem.l 20(%sp),%d0-%d5/%a0
++ trap #0
++ movem.l (%sp)+,%d2-%d5
++ rts
+diff --git a/src/internal/malloc_impl.h b/src/internal/malloc_impl.h
+new file mode 100644
+index 00000000..5d025b06
+--- /dev/null
++++ b/src/internal/malloc_impl.h
+@@ -0,0 +1,45 @@
++#ifndef MALLOC_IMPL_H
++#define MALLOC_IMPL_H
++
++void *__mmap(void *, size_t, int, int, int, off_t);
++int __munmap(void *, size_t);
++void *__mremap(void *, size_t, size_t, int, ...);
++int __madvise(void *, size_t, int);
++
++struct chunk {
++ size_t psize, csize;
++ struct chunk *next, *prev;
++};
++
++struct bin {
++ volatile int lock[2];
++ struct chunk *head;
++ struct chunk *tail;
++};
++
++#define SIZE_ALIGN (4*sizeof(size_t))
++#define SIZE_MASK (-SIZE_ALIGN)
++#define OVERHEAD (2*sizeof(size_t))
++#define MMAP_THRESHOLD (0x1c00*SIZE_ALIGN)
++#define DONTCARE 16
++#define RECLAIM 163840
++
++#define CHUNK_SIZE(c) ((c)->csize & -2)
++#define CHUNK_PSIZE(c) ((c)->psize & -2)
++#define PREV_CHUNK(c) ((struct chunk *)((char *)(c) - CHUNK_PSIZE(c)))
++#define NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CHUNK_SIZE(c)))
++#define MEM_TO_CHUNK(p) (struct chunk *)((char *)(p) - OVERHEAD)
++#define CHUNK_TO_MEM(c) (void *)((char *)(c) + OVERHEAD)
++#define BIN_TO_CHUNK(i) (MEM_TO_CHUNK(&mal.bins[i].head))
++
++#define C_INUSE ((size_t)1)
++
++#define IS_MMAPPED(c) !((c)->csize & (C_INUSE))
++
++__attribute__((__visibility__("hidden")))
++void __bin_chunk(struct chunk *);
++
++__attribute__((__visibility__("hidden")))
++extern int __malloc_replaced;
++
++#endif
+diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
+index f6a4f2c2..3826bd8e 100644
+--- a/src/internal/pthread_impl.h
++++ b/src/internal/pthread_impl.h
+@@ -19,38 +19,36 @@ struct pthread {
+ void **dtv, *unused1, *unused2;
+ uintptr_t sysinfo;
+ uintptr_t canary, canary2;
+- pid_t tid, pid;
+
+ /* Part 2 -- implementation details, non-ABI. */
+- int tsd_used, errno_val;
+- volatile int cancel, canceldisable, cancelasync;
+- int detached;
++ int tid;
++ int errno_val;
++ volatile int detach_state;
++ volatile int cancel;
++ volatile unsigned char canceldisable, cancelasync;
++ unsigned char tsd_used:1;
++ unsigned char unblock_cancel:1;
++ unsigned char dlerror_flag:1;
+ unsigned char *map_base;
+ size_t map_size;
+ void *stack;
+ size_t stack_size;
++ size_t guard_size;
+ void *start_arg;
+ void *(*start)(void *);
+ void *result;
+ struct __ptcb *cancelbuf;
+ void **tsd;
+- volatile int dead;
+ struct {
+ volatile void *volatile head;
+ long off;
+ volatile void *volatile pending;
+ } robust_list;
+- int unblock_cancel;
+ volatile int timer_id;
+ locale_t locale;
+ volatile int killlock[1];
+- volatile int exitlock[1];
+- volatile int startlock[2];
+- unsigned long sigmask[_NSIG/8/sizeof(long)];
+ char *dlerror_buf;
+- int dlerror_flag;
+ void *stdio_locks;
+- size_t guard_size;
+
+ /* Part 3 -- the positions of these fields relative to
+ * the end of the structure is external and internal ABI. */
+@@ -58,6 +56,22 @@ struct pthread {
+ void **dtv_copy;
+ };
+
++struct start_sched_args {
++ void *start_arg;
++ void *(*start_fn)(void *);
++ sigset_t mask;
++ pthread_attr_t *attr;
++ volatile int futex;
++};
++
++enum {
++ DT_EXITED = 0,
++ DT_EXITING,
++ DT_JOINABLE,
++ DT_DETACHED,
++ DT_DYNAMIC,
++};
++
+ struct __timer {
+ int timerid;
+ pthread_t thread;
+@@ -147,8 +161,8 @@ static inline void __wake(volatile void *addr, int cnt, int priv)
+ static inline void __futexwait(volatile void *addr, int val, int priv)
+ {
+ if (priv) priv = FUTEX_PRIVATE;
+- __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val) != -ENOSYS ||
+- __syscall(SYS_futex, addr, FUTEX_WAIT, val);
++ __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS ||
++ __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0);
+ }
+
+ void __acquire_ptc(void);
+diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h
+index 7cdf729d..1127a492 100644
+--- a/src/internal/stdio_impl.h
++++ b/src/internal/stdio_impl.h
+@@ -9,7 +9,7 @@
+
+ #define FFINALLOCK(f) ((f)->lock>=0 ? __lockfile((f)) : 0)
+ #define FLOCK(f) int __need_unlock = ((f)->lock>=0 ? __lockfile((f)) : 0)
+-#define FUNLOCK(f) if (__need_unlock) __unlockfile((f)); else
++#define FUNLOCK(f) do { if (__need_unlock) __unlockfile((f)); } while (0)
+
+ #define F_PERM 1
+ #define F_NORD 4
+diff --git a/src/ipc/msgctl.c b/src/ipc/msgctl.c
+index 4372c719..ea9b2337 100644
+--- a/src/ipc/msgctl.c
++++ b/src/ipc/msgctl.c
+@@ -1,12 +1,34 @@
+ #include <sys/msg.h>
++#include <endian.h>
+ #include "syscall.h"
+ #include "ipc.h"
+
++#if __BYTE_ORDER != __BIG_ENDIAN
++#undef SYSCALL_IPC_BROKEN_MODE
++#endif
++
+ int msgctl(int q, int cmd, struct msqid_ds *buf)
+ {
++#ifdef SYSCALL_IPC_BROKEN_MODE
++ struct msqid_ds tmp;
++ if (cmd == IPC_SET) {
++ tmp = *buf;
++ tmp.msg_perm.mode *= 0x10000U;
++ buf = &tmp;
++ }
++#endif
+ #ifdef SYS_msgctl
+- return syscall(SYS_msgctl, q, cmd | IPC_64, buf);
++ int r = __syscall(SYS_msgctl, q, cmd | IPC_64, buf);
+ #else
+- return syscall(SYS_ipc, IPCOP_msgctl, q, cmd | IPC_64, 0, buf, 0);
++ int r = __syscall(SYS_ipc, IPCOP_msgctl, q, cmd | IPC_64, 0, buf, 0);
++#endif
++#ifdef SYSCALL_IPC_BROKEN_MODE
++ if (r >= 0) switch (cmd) {
++ case IPC_STAT:
++ case MSG_STAT:
++ case MSG_STAT_ANY:
++ buf->msg_perm.mode >>= 16;
++ }
+ #endif
++ return __syscall_ret(r);
+ }
+diff --git a/src/ipc/semctl.c b/src/ipc/semctl.c
+index 673a9a8c..941e2813 100644
+--- a/src/ipc/semctl.c
++++ b/src/ipc/semctl.c
+@@ -1,8 +1,13 @@
+ #include <sys/sem.h>
+ #include <stdarg.h>
++#include <endian.h>
+ #include "syscall.h"
+ #include "ipc.h"
+
++#if __BYTE_ORDER != __BIG_ENDIAN
++#undef SYSCALL_IPC_BROKEN_MODE
++#endif
++
+ union semun {
+ int val;
+ struct semid_ds *buf;
+@@ -20,9 +25,26 @@ int semctl(int id, int num, int cmd, ...)
+ arg = va_arg(ap, union semun);
+ va_end(ap);
+ }
++#ifdef SYSCALL_IPC_BROKEN_MODE
++ struct semid_ds tmp;
++ if (cmd == IPC_SET) {
++ tmp = *arg.buf;
++ tmp.sem_perm.mode *= 0x10000U;
++ arg.buf = &tmp;
++ }
++#endif
+ #ifdef SYS_semctl
+- return syscall(SYS_semctl, id, num, cmd | IPC_64, arg.buf);
++ int r = __syscall(SYS_semctl, id, num, cmd | IPC_64, arg.buf);
+ #else
+- return syscall(SYS_ipc, IPCOP_semctl, id, num, cmd | IPC_64, &arg.buf);
++ int r = __syscall(SYS_ipc, IPCOP_semctl, id, num, cmd | IPC_64, &arg.buf);
++#endif
++#ifdef SYSCALL_IPC_BROKEN_MODE
++ if (r >= 0) switch (cmd) {
++ case IPC_STAT:
++ case SEM_STAT:
++ case SEM_STAT_ANY:
++ arg.buf->sem_perm.mode >>= 16;
++ }
+ #endif
++ return __syscall_ret(r);
+ }
+diff --git a/src/ipc/shmctl.c b/src/ipc/shmctl.c
+index e2879f20..c951a581 100644
+--- a/src/ipc/shmctl.c
++++ b/src/ipc/shmctl.c
+@@ -1,12 +1,34 @@
+ #include <sys/shm.h>
++#include <endian.h>
+ #include "syscall.h"
+ #include "ipc.h"
+
++#if __BYTE_ORDER != __BIG_ENDIAN
++#undef SYSCALL_IPC_BROKEN_MODE
++#endif
++
+ int shmctl(int id, int cmd, struct shmid_ds *buf)
+ {
++#ifdef SYSCALL_IPC_BROKEN_MODE
++ struct shmid_ds tmp;
++ if (cmd == IPC_SET) {
++ tmp = *buf;
++ tmp.shm_perm.mode *= 0x10000U;
++ buf = &tmp;
++ }
++#endif
+ #ifdef SYS_shmctl
+- return syscall(SYS_shmctl, id, cmd | IPC_64, buf);
++ int r = __syscall(SYS_shmctl, id, cmd | IPC_64, buf);
+ #else
+- return syscall(SYS_ipc, IPCOP_shmctl, id, cmd | IPC_64, 0, buf, 0);
++ int r = __syscall(SYS_ipc, IPCOP_shmctl, id, cmd | IPC_64, 0, buf, 0);
++#endif
++#ifdef SYSCALL_IPC_BROKEN_MODE
++ if (r >= 0) switch (cmd) {
++ case IPC_STAT:
++ case SHM_STAT:
++ case SHM_STAT_ANY:
++ buf->shm_perm.mode >>= 16;
++ }
+ #endif
++ return __syscall_ret(r);
+ }
+diff --git a/src/ldso/aarch64/tlsdesc.s b/src/ldso/aarch64/tlsdesc.s
+index 8ed5c267..8e4004d7 100644
+--- a/src/ldso/aarch64/tlsdesc.s
++++ b/src/ldso/aarch64/tlsdesc.s
+@@ -14,7 +14,7 @@ __tlsdesc_static:
+ // size_t __tlsdesc_dynamic(size_t *a)
+ // {
+ // struct {size_t modidx,off;} *p = (void*)a[1];
+-// size_t *dtv = *(size_t**)(tp + 16 - 8);
++// size_t *dtv = *(size_t**)(tp - 8);
+ // if (p->modidx <= dtv[0])
+ // return dtv[p->modidx] + p->off - tp;
+ // return __tls_get_new(p) - tp;
+@@ -28,8 +28,7 @@ __tlsdesc_dynamic:
+ mrs x1,tpidr_el0 // tp
+ ldr x0,[x0,#8] // p
+ ldr x2,[x0] // p->modidx
+- add x3,x1,#8
+- ldr x3,[x3] // dtv
++ ldr x3,[x1,#-8] // dtv
+ ldr x4,[x3] // dtv[0]
+ cmp x2,x4
+ b.hi 1f
+diff --git a/src/ldso/m68k/dlsym.s b/src/ldso/m68k/dlsym.s
+new file mode 100644
+index 00000000..5209ae1b
+--- /dev/null
++++ b/src/ldso/m68k/dlsym.s
+@@ -0,0 +1,12 @@
++.text
++.global dlsym
++.hidden __dlsym
++.type dlsym,@function
++dlsym:
++ move.l (%sp),-(%sp)
++ move.l 12(%sp),-(%sp)
++ move.l 12(%sp),-(%sp)
++ lea __dlsym-.-8,%a1
++ jsr (%pc,%a1)
++ add.l #12,%sp
++ rts
+diff --git a/src/linux/getrandom.c b/src/linux/getrandom.c
+new file mode 100644
+index 00000000..6cc6f6b0
+--- /dev/null
++++ b/src/linux/getrandom.c
+@@ -0,0 +1,7 @@
++#include <sys/random.h>
++#include "syscall.h"
++
++ssize_t getrandom(void *buf, size_t buflen, unsigned flags)
++{
++ return syscall_cp(SYS_getrandom, buf, buflen, flags);
++}
+diff --git a/src/linux/memfd_create.c b/src/linux/memfd_create.c
+new file mode 100644
+index 00000000..1649fe55
+--- /dev/null
++++ b/src/linux/memfd_create.c
+@@ -0,0 +1,8 @@
++#define _GNU_SOURCE 1
++#include <sys/mman.h>
++#include "syscall.h"
++
++int memfd_create(const char *name, unsigned flags)
++{
++ return syscall(SYS_memfd_create, name, flags);
++}
+diff --git a/src/linux/mlock2.c b/src/linux/mlock2.c
+new file mode 100644
+index 00000000..10132742
+--- /dev/null
++++ b/src/linux/mlock2.c
+@@ -0,0 +1,10 @@
++#define _GNU_SOURCE 1
++#include <sys/mman.h>
++#include "syscall.h"
++
++int mlock2(const void *addr, size_t len, unsigned flags)
++{
++ if (flags == 0)
++ return mlock(addr, len);
++ return syscall(SYS_mlock2, addr, len, flags);
++}
+diff --git a/src/locale/iconv.c b/src/locale/iconv.c
+index d469856c..3047c27b 100644
+--- a/src/locale/iconv.c
++++ b/src/locale/iconv.c
+@@ -458,16 +458,24 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
+ * range in the hkscs table then hard-coded
+ * here. Ugly, yes. */
+ if (c/256 == 0xdc) {
+- if (totype-0300U > 8) k = 2;
+- else k = "\10\4\4\10\4\4\10\2\4"[totype-0300];
+- if (k > *outb) goto toobig;
+- x += iconv(combine_to_from(to, 0),
++ union {
++ char c[8];
++ wchar_t wc[2];
++ } tmp;
++ char *ptmp = tmp.c;
++ size_t tmpx = iconv(combine_to_from(to, find_charmap("utf8")),
+ &(char *){"\303\212\314\204"
+ "\303\212\314\214"
+ "\303\252\314\204"
+ "\303\252\314\214"
+ +c%256}, &(size_t){4},
+- out, outb);
++ &ptmp, &(size_t){sizeof tmp});
++ size_t tmplen = ptmp - tmp.c;
++ if (tmplen > *outb) goto toobig;
++ if (tmpx) x++;
++ memcpy(*out, &tmp, tmplen);
++ *out += tmplen;
++ *outb -= tmplen;
+ continue;
+ }
+ if (!c) goto ilseq;
+@@ -539,6 +547,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
+ if (*outb < 1) goto toobig;
+ if (c<256 && c==legacy_map(tomap, c)) {
+ revout:
++ if (*outb < 1) goto toobig;
+ *(*out)++ = c;
+ *outb -= 1;
+ break;
+@@ -645,6 +654,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
+ *out += 4;
+ *outb -= 4;
+ break;
++ case UTF_32:
++ totype = UTF_32BE;
+ case UTF_32BE:
+ case UTF_32LE:
+ if (*outb < 4) goto toobig;
+diff --git a/src/locale/langinfo.c b/src/locale/langinfo.c
+index b16caf44..83be6433 100644
+--- a/src/locale/langinfo.c
++++ b/src/locale/langinfo.c
+@@ -33,7 +33,7 @@ char *__nl_langinfo_l(nl_item item, locale_t loc)
+ int idx = item & 65535;
+ const char *str;
+
+- if (item == CODESET) return MB_CUR_MAX==1 ? "ASCII" : "UTF-8";
++ if (item == CODESET) return loc->cat[LC_CTYPE] ? "UTF-8" : "ASCII";
+
+ /* _NL_LOCALE_NAME extension */
+ if (idx == 65535 && cat < LC_ALL)
+diff --git a/src/locale/setlocale.c b/src/locale/setlocale.c
+index 40bc7ece..4d51cdfe 100644
+--- a/src/locale/setlocale.c
++++ b/src/locale/setlocale.c
+@@ -25,6 +25,8 @@ char *setlocale(int cat, const char *name)
+
+ if ((unsigned)cat > LC_ALL) return 0;
+
++ if (name && (!strncmp(name, "VSX4L", 5))) return 0;
++
+ LOCK(lock);
+
+ /* For LC_ALL, setlocale is required to return a string which
+diff --git a/src/malloc/__brk.c b/src/malloc/__brk.c
+deleted file mode 100644
+index 4c9119b4..00000000
+--- a/src/malloc/__brk.c
++++ /dev/null
+@@ -1,7 +0,0 @@
+-#include <stdint.h>
+-#include "syscall.h"
+-
+-uintptr_t __brk(uintptr_t newbrk)
+-{
+- return __syscall(SYS_brk, newbrk);
+-}
+diff --git a/src/malloc/calloc.c b/src/malloc/calloc.c
+deleted file mode 100644
+index 436c0b03..00000000
+--- a/src/malloc/calloc.c
++++ /dev/null
+@@ -1,13 +0,0 @@
+-#include <stdlib.h>
+-#include <errno.h>
+-
+-void *__malloc0(size_t);
+-
+-void *calloc(size_t m, size_t n)
+-{
+- if (n && m > (size_t)-1/n) {
+- errno = ENOMEM;
+- return 0;
+- }
+- return __malloc0(n * m);
+-}
+diff --git a/src/malloc/lite_malloc.c b/src/malloc/lite_malloc.c
+index 701f60b4..96c4feac 100644
+--- a/src/malloc/lite_malloc.c
++++ b/src/malloc/lite_malloc.c
+@@ -47,4 +47,14 @@ static void *__simple_malloc(size_t n)
+ }
+
+ weak_alias(__simple_malloc, malloc);
+-weak_alias(__simple_malloc, __malloc0);
++
++static void *__simple_calloc(size_t m, size_t n)
++{
++ if (n && m > (size_t)-1/n) {
++ errno = ENOMEM;
++ return 0;
++ }
++ return __simple_malloc(n * m);
++}
++
++weak_alias(__simple_calloc, calloc);
+diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c
+index 9e05e1d6..d72883e1 100644
+--- a/src/malloc/malloc.c
++++ b/src/malloc/malloc.c
+@@ -8,53 +8,19 @@
+ #include "libc.h"
+ #include "atomic.h"
+ #include "pthread_impl.h"
++#include "malloc_impl.h"
+
+ #if defined(__GNUC__) && defined(__PIC__)
+ #define inline inline __attribute__((always_inline))
+ #endif
+
+-void *__mmap(void *, size_t, int, int, int, off_t);
+-int __munmap(void *, size_t);
+-void *__mremap(void *, size_t, size_t, int, ...);
+-int __madvise(void *, size_t, int);
+-
+-struct chunk {
+- size_t psize, csize;
+- struct chunk *next, *prev;
+-};
+-
+-struct bin {
+- volatile int lock[2];
+- struct chunk *head;
+- struct chunk *tail;
+-};
+-
+ static struct {
+ volatile uint64_t binmap;
+ struct bin bins[64];
+ volatile int free_lock[2];
+ } mal;
+
+-
+-#define SIZE_ALIGN (4*sizeof(size_t))
+-#define SIZE_MASK (-SIZE_ALIGN)
+-#define OVERHEAD (2*sizeof(size_t))
+-#define MMAP_THRESHOLD (0x1c00*SIZE_ALIGN)
+-#define DONTCARE 16
+-#define RECLAIM 163840
+-
+-#define CHUNK_SIZE(c) ((c)->csize & -2)
+-#define CHUNK_PSIZE(c) ((c)->psize & -2)
+-#define PREV_CHUNK(c) ((struct chunk *)((char *)(c) - CHUNK_PSIZE(c)))
+-#define NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CHUNK_SIZE(c)))
+-#define MEM_TO_CHUNK(p) (struct chunk *)((char *)(p) - OVERHEAD)
+-#define CHUNK_TO_MEM(c) (void *)((char *)(c) + OVERHEAD)
+-#define BIN_TO_CHUNK(i) (MEM_TO_CHUNK(&mal.bins[i].head))
+-
+-#define C_INUSE ((size_t)1)
+-
+-#define IS_MMAPPED(c) !((c)->csize & (C_INUSE))
+-
++int __malloc_replaced;
+
+ /* Synchronization tools */
+
+@@ -314,7 +280,7 @@ static void trim(struct chunk *self, size_t n)
+ next->psize = n1-n | C_INUSE;
+ self->csize = n | C_INUSE;
+
+- free(CHUNK_TO_MEM(split));
++ __bin_chunk(split);
+ }
+
+ void *malloc(size_t n)
+@@ -366,15 +332,40 @@ void *malloc(size_t n)
+ return CHUNK_TO_MEM(c);
+ }
+
+-void *__malloc0(size_t n)
++static size_t mal0_clear(char *p, size_t pagesz, size_t n)
+ {
++#ifdef __GNUC__
++ typedef uint64_t __attribute__((__may_alias__)) T;
++#else
++ typedef unsigned char T;
++#endif
++ char *pp = p + n;
++ size_t i = (uintptr_t)pp & (pagesz - 1);
++ for (;;) {
++ pp = memset(pp - i, 0, i);
++ if (pp - p < pagesz) return pp - p;
++ for (i = pagesz; i; i -= 2*sizeof(T), pp -= 2*sizeof(T))
++ if (((T *)pp)[-1] | ((T *)pp)[-2])
++ break;
++ }
++}
++
++void *calloc(size_t m, size_t n)
++{
++ if (n && m > (size_t)-1/n) {
++ errno = ENOMEM;
++ return 0;
++ }
++ n *= m;
+ void *p = malloc(n);
+- if (p && !IS_MMAPPED(MEM_TO_CHUNK(p))) {
+- size_t *z;
+- n = (n + sizeof *z - 1)/sizeof *z;
+- for (z=p; n; n--, z++) if (*z) *z=0;
++ if (!p) return p;
++ if (!__malloc_replaced) {
++ if (IS_MMAPPED(MEM_TO_CHUNK(p)))
++ return p;
++ if (n >= PAGE_SIZE)
++ n = mal0_clear(p, PAGE_SIZE, n);
+ }
+- return p;
++ return memset(p, 0, n);
+ }
+
+ void *realloc(void *p, size_t n)
+@@ -397,10 +388,9 @@ void *realloc(void *p, size_t n)
+ size_t newlen = n + extra;
+ /* Crash on realloc of freed chunk */
+ if (extra & 1) a_crash();
+- if (newlen < PAGE_SIZE && (new = malloc(n))) {
+- memcpy(new, p, n-OVERHEAD);
+- free(p);
+- return new;
++ if (newlen < PAGE_SIZE && (new = malloc(n-OVERHEAD))) {
++ n0 = n;
++ goto copy_free_ret;
+ }
+ newlen = (newlen + PAGE_SIZE-1) & -PAGE_SIZE;
+ if (oldlen == newlen) return p;
+@@ -443,34 +433,20 @@ copy_realloc:
+ /* As a last resort, allocate a new chunk and copy to it. */
+ new = malloc(n-OVERHEAD);
+ if (!new) return 0;
++copy_free_ret:
+ memcpy(new, p, n0-OVERHEAD);
+ free(CHUNK_TO_MEM(self));
+ return new;
+ }
+
+-void free(void *p)
++void __bin_chunk(struct chunk *self)
+ {
+- struct chunk *self, *next;
++ struct chunk *next = NEXT_CHUNK(self);
+ size_t final_size, new_size, size;
+ int reclaim=0;
+ int i;
+
+- if (!p) return;
+-
+- self = MEM_TO_CHUNK(p);
+-
+- if (IS_MMAPPED(self)) {
+- size_t extra = self->psize;
+- char *base = (char *)self - extra;
+- size_t len = CHUNK_SIZE(self) + extra;
+- /* Crash on double free */
+- if (extra & 1) a_crash();
+- __munmap(base, len);
+- return;
+- }
+-
+ final_size = new_size = CHUNK_SIZE(self);
+- next = NEXT_CHUNK(self);
+
+ /* Crash on corrupted footer (likely from buffer overflow) */
+ if (next->psize != self->csize) a_crash();
+@@ -531,3 +507,44 @@ void free(void *p)
+
+ unlock_bin(i);
+ }
++
++static void unmap_chunk(struct chunk *self)
++{
++ size_t extra = self->psize;
++ char *base = (char *)self - extra;
++ size_t len = CHUNK_SIZE(self) + extra;
++ /* Crash on double free */
++ if (extra & 1) a_crash();
++ __munmap(base, len);
++}
++
++void free(void *p)
++{
++ if (!p) return;
++
++ struct chunk *self = MEM_TO_CHUNK(p);
++
++ if (IS_MMAPPED(self))
++ unmap_chunk(self);
++ else
++ __bin_chunk(self);
++}
++
++void __malloc_donate(char *start, char *end)
++{
++ size_t align_start_up = (SIZE_ALIGN-1) & (-(uintptr_t)start - OVERHEAD);
++ size_t align_end_down = (SIZE_ALIGN-1) & (uintptr_t)end;
++
++ /* Getting past this condition ensures that the padding for alignment
++ * and header overhead will not overflow and will leave a nonzero
++ * multiple of SIZE_ALIGN bytes between start and end. */
++ if (end - start <= OVERHEAD + align_start_up + align_end_down)
++ return;
++ start += align_start_up + OVERHEAD;
++ end -= align_end_down;
++
++ struct chunk *c = MEM_TO_CHUNK(start), *n = MEM_TO_CHUNK(end);
++ c->psize = n->csize = C_INUSE;
++ c->csize = n->psize = C_INUSE | (end-start);
++ __bin_chunk(c);
++}
+diff --git a/src/malloc/memalign.c b/src/malloc/memalign.c
+index 006bd21c..8a6152f4 100644
+--- a/src/malloc/memalign.c
++++ b/src/malloc/memalign.c
+@@ -2,55 +2,53 @@
+ #include <stdint.h>
+ #include <errno.h>
+ #include "libc.h"
+-
+-/* This function should work with most dlmalloc-like chunk bookkeeping
+- * systems, but it's only guaranteed to work with the native implementation
+- * used in this library. */
++#include "malloc_impl.h"
+
+ void *__memalign(size_t align, size_t len)
+ {
+- unsigned char *mem, *new, *end;
+- size_t header, footer;
++ unsigned char *mem, *new;
+
+ if ((align & -align) != align) {
+ errno = EINVAL;
+- return NULL;
++ return 0;
+ }
+
+- if (len > SIZE_MAX - align) {
++ if (len > SIZE_MAX - align || __malloc_replaced) {
+ errno = ENOMEM;
+- return NULL;
++ return 0;
+ }
+
+- if (align <= 4*sizeof(size_t)) {
+- if (!(mem = malloc(len)))
+- return NULL;
+- return mem;
+- }
++ if (align <= SIZE_ALIGN)
++ return malloc(len);
+
+ if (!(mem = malloc(len + align-1)))
+- return NULL;
++ return 0;
+
+ new = (void *)((uintptr_t)mem + align-1 & -align);
+ if (new == mem) return mem;
+
+- header = ((size_t *)mem)[-1];
++ struct chunk *c = MEM_TO_CHUNK(mem);
++ struct chunk *n = MEM_TO_CHUNK(new);
+
+- if (!(header & 7)) {
+- ((size_t *)new)[-2] = ((size_t *)mem)[-2] + (new-mem);
+- ((size_t *)new)[-1] = ((size_t *)mem)[-1] - (new-mem);
++ if (IS_MMAPPED(c)) {
++ /* Apply difference between aligned and original
++ * address to the "extra" field of mmapped chunk. */
++ n->psize = c->psize + (new-mem);
++ n->csize = c->csize - (new-mem);
+ return new;
+ }
+
+- end = mem + (header & -8);
+- footer = ((size_t *)end)[-2];
++ struct chunk *t = NEXT_CHUNK(c);
+
+- ((size_t *)mem)[-1] = header&7 | new-mem;
+- ((size_t *)new)[-2] = footer&7 | new-mem;
+- ((size_t *)new)[-1] = header&7 | end-new;
+- ((size_t *)end)[-2] = footer&7 | end-new;
++ /* Split the allocated chunk into two chunks. The aligned part
++ * that will be used has the size in its footer reduced by the
++ * difference between the aligned and original addresses, and
++ * the resulting size copied to its header. A new header and
++ * footer are written for the split-off part to be freed. */
++ n->psize = c->csize = C_INUSE | (new-mem);
++ n->csize = t->psize -= new-mem;
+
+- free(mem);
++ __bin_chunk(c);
+ return new;
+ }
+
+diff --git a/src/math/__fpclassifyl.c b/src/math/__fpclassifyl.c
+index 481c0b94..e41781b6 100644
+--- a/src/math/__fpclassifyl.c
++++ b/src/math/__fpclassifyl.c
+@@ -13,10 +13,18 @@ int __fpclassifyl(long double x)
+ int msb = u.i.m>>63;
+ if (!e && !msb)
+ return u.i.m ? FP_SUBNORMAL : FP_ZERO;
++ if (e == 0x7fff) {
++ /* The x86 variant of 80-bit extended precision only admits
++ * one representation of each infinity, with the mantissa msb
++ * necessarily set. The version with it clear is invalid/nan.
++ * The m68k variant, however, allows either, and tooling uses
++ * the version with it clear. */
++ if (__BYTE_ORDER == __LITTLE_ENDIAN && !msb)
++ return FP_NAN;
++ return u.i.m << 1 ? FP_NAN : FP_INFINITE;
++ }
+ if (!msb)
+ return FP_NAN;
+- if (e == 0x7fff)
+- return u.i.m << 1 ? FP_NAN : FP_INFINITE;
+ return FP_NORMAL;
+ }
+ #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
+diff --git a/src/math/fmaf.c b/src/math/fmaf.c
+index aa57feb6..80f5cd8a 100644
+--- a/src/math/fmaf.c
++++ b/src/math/fmaf.c
+@@ -50,7 +50,7 @@ float fmaf(float x, float y, float z)
+ /* Common case: The double precision result is fine. */
+ if ((u.i & 0x1fffffff) != 0x10000000 || /* not a halfway case */
+ e == 0x7ff || /* NaN */
+- result - xy == z || /* exact */
++ (result - xy == z && result - z == xy) || /* exact */
+ fegetround() != FE_TONEAREST) /* not round-to-nearest */
+ {
+ /*
+diff --git a/src/misc/getentropy.c b/src/misc/getentropy.c
+new file mode 100644
+index 00000000..4c61ae26
+--- /dev/null
++++ b/src/misc/getentropy.c
+@@ -0,0 +1,31 @@
++#include <sys/random.h>
++#include <pthread.h>
++#include <errno.h>
++
++int getentropy(void *buffer, size_t len)
++{
++ int cs, ret;
++ char *pos = buffer;
++
++ if (len > 256) {
++ errno = EIO;
++ return -1;
++ }
++
++ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
++
++ while (len) {
++ ret = getrandom(pos, len, 0);
++ if (ret < 0) {
++ if (errno == EINTR) continue;
++ else break;
++ }
++ pos += ret;
++ len -= ret;
++ ret = 0;
++ }
++
++ pthread_setcancelstate(cs, 0);
++
++ return ret;
++}
+diff --git a/src/misc/gethostid.c b/src/misc/gethostid.c
+index ea65611a..25bb35db 100644
+--- a/src/misc/gethostid.c
++++ b/src/misc/gethostid.c
+@@ -1,3 +1,5 @@
++#include <unistd.h>
++
+ long gethostid()
+ {
+ return 0;
+diff --git a/src/misc/getopt.c b/src/misc/getopt.c
+index e9bab41c..e921a60e 100644
+--- a/src/misc/getopt.c
++++ b/src/misc/getopt.c
+@@ -77,7 +77,7 @@ int getopt(int argc, char * const argv[], const char *optstring)
+ if (l>0) i+=l; else i++;
+ } while (l && d != c);
+
+- if (d != c) {
++ if (d != c || c == ':') {
+ optopt = c;
+ if (optstring[0] != ':' && opterr)
+ __getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
+diff --git a/src/misc/getopt_long.c b/src/misc/getopt_long.c
+index 008b747c..ddcef949 100644
+--- a/src/misc/getopt_long.c
++++ b/src/misc/getopt_long.c
+@@ -1,5 +1,7 @@
+ #define _GNU_SOURCE
+ #include <stddef.h>
++#include <stdlib.h>
++#include <limits.h>
+ #include <getopt.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -58,10 +60,10 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring
+ {
+ int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
+ int i, cnt, match;
+- char *arg, *opt;
++ char *arg, *opt, *start = argv[optind]+1;
+ for (cnt=i=0; longopts[i].name; i++) {
+ const char *name = longopts[i].name;
+- opt = argv[optind]+1;
++ opt = start;
+ if (*opt == '-') opt++;
+ while (*opt && *opt != '=' && *opt == *name)
+ name++, opt++;
+@@ -74,6 +76,17 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring
+ }
+ cnt++;
+ }
++ if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) {
++ int l = arg-start;
++ for (i=0; optstring[i]; i++) {
++ int j;
++ for (j=0; j<l && start[j]==optstring[i+j]; j++);
++ if (j==l) {
++ cnt++;
++ break;
++ }
++ }
++ }
+ if (cnt==1) {
+ i = match;
+ opt = arg;
+diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c
+index b9439f77..ba26847a 100644
+--- a/src/network/getaddrinfo.c
++++ b/src/network/getaddrinfo.c
+@@ -3,6 +3,10 @@
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #include <string.h>
++#include <pthread.h>
++#include <unistd.h>
++#include <endian.h>
++#include <errno.h>
+ #include "lookup.h"
+
+ int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res)
+@@ -43,6 +47,41 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
+ }
+ }
+
++ if (flags & AI_ADDRCONFIG) {
++ /* Define the "an address is configured" condition for address
++ * families via ability to create a socket for the family plus
++ * routability of the loopback address for the family. */
++ static const struct sockaddr_in lo4 = {
++ .sin_family = AF_INET, .sin_port = 65535,
++ .sin_addr.s_addr = __BYTE_ORDER == __BIG_ENDIAN
++ ? 0x7f000001 : 0x0100007f
++ };
++ static const struct sockaddr_in6 lo6 = {
++ .sin6_family = AF_INET6, .sin6_port = 65535,
++ .sin6_addr = IN6ADDR_LOOPBACK_INIT
++ };
++ int tf[2] = { AF_INET, AF_INET6 };
++ const void *ta[2] = { &lo4, &lo6 };
++ socklen_t tl[2] = { sizeof lo4, sizeof lo6 };
++ for (i=0; i<2; i++) {
++ if (family==tf[1-i]) continue;
++ int s = socket(tf[i], SOCK_CLOEXEC|SOCK_DGRAM,
++ IPPROTO_UDP);
++ if (s>=0) {
++ int cs;
++ pthread_setcancelstate(
++ PTHREAD_CANCEL_DISABLE, &cs);
++ int r = connect(s, ta[i], tl[i]);
++ pthread_setcancelstate(cs, 0);
++ close(s);
++ if (!r) continue;
++ }
++ if (errno != EAFNOSUPPORT) return EAI_SYSTEM;
++ if (family == tf[i]) return EAI_NONAME;
++ family = tf[1-i];
++ }
++ }
++
+ nservs = __lookup_serv(ports, serv, proto, socktype, flags);
+ if (nservs < 0) return nservs;
+
+diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c
+index 14f9f4c4..4bfef2c5 100644
+--- a/src/network/inet_ntop.c
++++ b/src/network/inet_ntop.c
+@@ -36,7 +36,7 @@ const char *inet_ntop(int af, const void *restrict a0, char *restrict s, socklen
+ j = strspn(buf+i, ":0");
+ if (j>max) best=i, max=j;
+ }
+- if (max>2) {
++ if (max>3) {
+ buf[best] = buf[best+1] = ':';
+ memmove(buf+best+2, buf+best+max, i-best-max+1);
+ }
+diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c
+index 209c20f0..0e6db9ef 100644
+--- a/src/network/lookup_name.c
++++ b/src/network/lookup_name.c
+@@ -184,6 +184,10 @@ static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[
+ for (dots=l=0; name[l]; l++) if (name[l]=='.') dots++;
+ if (dots >= conf.ndots || name[l-1]=='.') *search = 0;
+
++ /* Strip final dot for canon, fail if multiple trailing dots. */
++ if (name[l-1]=='.') l--;
++ if (!l || name[l-1]=='.') return EAI_NONAME;
++
+ /* This can never happen; the caller already checked length. */
+ if (l >= 256) return EAI_NONAME;
+
+@@ -351,36 +355,53 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c
+ * excessive runtime and code size cost and dubious benefit.
+ * So far the label/precedence table cannot be customized. */
+ for (i=0; i<cnt; i++) {
++ int family = buf[i].family;
+ int key = 0;
+- struct sockaddr_in6 sa, da = {
++ struct sockaddr_in6 sa6 = { 0 }, da6 = {
+ .sin6_family = AF_INET6,
+ .sin6_scope_id = buf[i].scopeid,
+ .sin6_port = 65535
+ };
+- if (buf[i].family == AF_INET6) {
+- memcpy(da.sin6_addr.s6_addr, buf[i].addr, 16);
++ struct sockaddr_in sa4 = { 0 }, da4 = {
++ .sin_family = AF_INET,
++ .sin_port = 65535
++ };
++ void *sa, *da;
++ socklen_t salen, dalen;
++ if (family == AF_INET6) {
++ memcpy(da6.sin6_addr.s6_addr, buf[i].addr, 16);
++ da = &da6; dalen = sizeof da6;
++ sa = &sa6; salen = sizeof sa6;
+ } else {
+- memcpy(da.sin6_addr.s6_addr,
++ memcpy(sa6.sin6_addr.s6_addr,
++ "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
++ memcpy(da6.sin6_addr.s6_addr+12, buf[i].addr, 4);
++ memcpy(da6.sin6_addr.s6_addr,
+ "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
+- memcpy(da.sin6_addr.s6_addr+12, buf[i].addr, 4);
++ memcpy(da6.sin6_addr.s6_addr+12, buf[i].addr, 4);
++ memcpy(&da4.sin_addr, buf[i].addr, 4);
++ da = &da4; dalen = sizeof da4;
++ sa = &sa4; salen = sizeof sa4;
+ }
+- const struct policy *dpolicy = policyof(&da.sin6_addr);
+- int dscope = scopeof(&da.sin6_addr);
++ const struct policy *dpolicy = policyof(&da6.sin6_addr);
++ int dscope = scopeof(&da6.sin6_addr);
+ int dlabel = dpolicy->label;
+ int dprec = dpolicy->prec;
+ int prefixlen = 0;
+- int fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP);
++ int fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP);
+ if (fd >= 0) {
+- if (!connect(fd, (void *)&da, sizeof da)) {
++ if (!connect(fd, da, dalen)) {
+ key |= DAS_USABLE;
+- if (!getsockname(fd, (void *)&sa,
+- &(socklen_t){sizeof sa})) {
+- if (dscope == scopeof(&sa.sin6_addr))
++ if (!getsockname(fd, sa, &salen)) {
++ if (family == AF_INET) memcpy(
++ &sa6.sin6_addr.s6_addr+12,
++ &sa4.sin_addr, 4);
++ if (dscope == scopeof(&sa6.sin6_addr))
+ key |= DAS_MATCHINGSCOPE;
+- if (dlabel == labelof(&sa.sin6_addr))
++ if (dlabel == labelof(&sa6.sin6_addr))
+ key |= DAS_MATCHINGLABEL;
+- prefixlen = prefixmatch(&sa.sin6_addr,
+- &da.sin6_addr);
++ prefixlen = prefixmatch(&sa6.sin6_addr,
++ &da6.sin6_addr);
+ }
+ }
+ close(fd);
+diff --git a/src/process/execlp.c b/src/process/execlp.c
+index 5eed886e..f6da398b 100644
+--- a/src/process/execlp.c
++++ b/src/process/execlp.c
+@@ -1,6 +1,9 @@
+ #include <unistd.h>
++#include <errno.h>
+ #include <stdarg.h>
+
++extern int __execsh(const char *, char *const []);
++
+ int execlp(const char *file, const char *argv0, ...)
+ {
+ int argc;
+@@ -17,6 +20,11 @@ int execlp(const char *file, const char *argv0, ...)
+ argv[i] = va_arg(ap, char *);
+ argv[i] = NULL;
+ va_end(ap);
+- return execvp(file, argv);
++ execvp(file, argv);
++ if (errno == ENOEXEC) {
++ errno = 0;
++ return __execsh(file, argv);
++ }
++ return -1;
+ }
+ }
+diff --git a/src/process/execsh.c b/src/process/execsh.c
+new file mode 100644
+index 00000000..180bb2aa
+--- /dev/null
++++ b/src/process/execsh.c
+@@ -0,0 +1,18 @@
++#include <unistd.h>
++#include <errno.h>
++#include "libc.h"
++
++int
++__execsh(const char *file, char *const argv[])
++{
++ int i, argc;
++ char **p;
++
++ for (argc=1, p=(char **)argv; *p; ++argc, ++p);
++
++ char *nargv[argc+1];
++ nargv[0] = (char *)file;
++ for (i=0; i<argc; ++i)
++ nargv[i+1] = argv[i];
++ return execv("/bin/sh", nargv);
++}
+diff --git a/src/process/execvp.c b/src/process/execvp.c
+index 2dddeddb..fdd0ca48 100644
+--- a/src/process/execvp.c
++++ b/src/process/execvp.c
+@@ -6,6 +6,7 @@
+ #include "libc.h"
+
+ extern char **__environ;
++extern int __execsh(const char *, char *const []);
+
+ int __execvpe(const char *file, char *const argv[], char *const envp[])
+ {
+@@ -56,7 +57,12 @@ int __execvpe(const char *file, char *const argv[], char *const envp[])
+
+ int execvp(const char *file, char *const argv[])
+ {
+- return __execvpe(file, argv, __environ);
++ __execvpe(file, argv, __environ);
++ if (errno == ENOEXEC) {
++ errno = 0;
++ return __execsh(file, argv);
++ }
++ return -1;
+ }
+
+ weak_alias(__execvpe, execvpe);
+diff --git a/src/process/system.c b/src/process/system.c
+index 8cbdda06..0569461c 100644
+--- a/src/process/system.c
++++ b/src/process/system.c
+@@ -19,7 +19,9 @@ int system(const char *cmd)
+
+ pthread_testcancel();
+
+- if (!cmd) return 1;
++ if (!cmd) {
++ return (access("/bin/sh", X_OK) == 0);
++ }
+
+ sigaction(SIGINT, &sa, &oldint);
+ sigaction(SIGQUIT, &sa, &oldquit);
+diff --git a/src/setjmp/m68k/longjmp.s b/src/setjmp/m68k/longjmp.s
+new file mode 100644
+index 00000000..cdb05fb5
+--- /dev/null
++++ b/src/setjmp/m68k/longjmp.s
+@@ -0,0 +1,14 @@
++.global _longjmp
++.global longjmp
++.type _longjmp,@function
++.type longjmp,@function
++_longjmp:
++longjmp:
++ movea.l 4(%sp),%a0
++ move.l 8(%sp),%d0
++ bne 1f
++ move.l #1,%d0
++1: movem.l (%a0),%d2-%d7/%a2-%a7
++ fmovem.x 52(%a0),%fp2-%fp7
++ move.l 48(%a0),(%sp)
++ rts
+diff --git a/src/setjmp/m68k/setjmp.s b/src/setjmp/m68k/setjmp.s
+new file mode 100644
+index 00000000..15e549b0
+--- /dev/null
++++ b/src/setjmp/m68k/setjmp.s
+@@ -0,0 +1,18 @@
++.global ___setjmp
++.hidden ___setjmp
++.global __setjmp
++.global _setjmp
++.global setjmp
++.type __setjmp,@function
++.type _setjmp,@function
++.type setjmp,@function
++___setjmp:
++__setjmp:
++_setjmp:
++setjmp:
++ movea.l 4(%sp),%a0
++ movem.l %d2-%d7/%a2-%a7,(%a0)
++ move.l (%sp),48(%a0)
++ fmovem.x %fp2-%fp7,52(%a0)
++ clr.l %d0
++ rts
+diff --git a/src/signal/m68k/sigsetjmp.s b/src/signal/m68k/sigsetjmp.s
+new file mode 100644
+index 00000000..09bfa646
+--- /dev/null
++++ b/src/signal/m68k/sigsetjmp.s
+@@ -0,0 +1,29 @@
++.global sigsetjmp
++.global __sigsetjmp
++.type sigsetjmp,@function
++.type __sigsetjmp,@function
++sigsetjmp:
++__sigsetjmp:
++ move.l 8(%sp),%d0
++ beq 1f
++
++ movea.l 4(%sp),%a1
++ move.l (%sp)+,156(%a1)
++ move.l %a2,156+4+8(%a1)
++ movea.l %a1,%a2
++
++.hidden ___setjmp
++ lea ___setjmp-.-8,%a1
++ jsr (%pc,%a1)
++
++ move.l 156(%a2),-(%sp)
++ move.l %a2,4(%sp)
++ move.l %d0,8(%sp)
++ movea.l 156+4+8(%a2),%a2
++
++.hidden __sigsetjmp_tail
++ lea __sigsetjmp_tail-.-8,%a1
++ jmp (%pc,%a1)
++
++1: lea ___setjmp-.-8,%a1
++ jmp (%pc,%a1)
+diff --git a/src/signal/sigisemptyset.c b/src/signal/sigisemptyset.c
+index 312c66cf..68b86624 100644
+--- a/src/signal/sigisemptyset.c
++++ b/src/signal/sigisemptyset.c
+@@ -4,6 +4,7 @@
+
+ int sigisemptyset(const sigset_t *set)
+ {
+- static const unsigned long zeroset[_NSIG/8/sizeof(long)];
+- return !memcmp(set, &zeroset, _NSIG/8);
++ for (size_t i=0; i<_NSIG/8/sizeof *set->__bits; i++)
++ if (set->__bits[i]) return 0;
++ return 1;
+ }
+diff --git a/src/signal/sigrtmin.c b/src/signal/sigrtmin.c
+index d0e769bb..c5a1fd92 100644
+--- a/src/signal/sigrtmin.c
++++ b/src/signal/sigrtmin.c
+@@ -1,3 +1,5 @@
++#include <signal.h>
++
+ int __libc_current_sigrtmin()
+ {
+ return 35;
+diff --git a/src/stdio/__lockfile.c b/src/stdio/__lockfile.c
+index 9d967d6e..2ff75d8a 100644
+--- a/src/stdio/__lockfile.c
++++ b/src/stdio/__lockfile.c
+@@ -1,28 +1,25 @@
+ #include "stdio_impl.h"
+ #include "pthread_impl.h"
+
++#define MAYBE_WAITERS 0x40000000
++
+ int __lockfile(FILE *f)
+ {
+- int owner, tid = __pthread_self()->tid;
+- if (f->lock == tid)
++ int owner = f->lock, tid = __pthread_self()->tid;
++ if ((owner & ~MAYBE_WAITERS) == tid)
+ return 0;
+- while ((owner = a_cas(&f->lock, 0, tid)))
+- __wait(&f->lock, &f->waiters, owner, 1);
++ for (;;) {
++ owner = a_cas(&f->lock, 0, tid);
++ if (!owner) return 1;
++ if (a_cas(&f->lock, owner, owner|MAYBE_WAITERS)==owner) break;
++ }
++ while ((owner = a_cas(&f->lock, 0, tid|MAYBE_WAITERS)))
++ __futexwait(&f->lock, owner, 1);
+ return 1;
+ }
+
+ void __unlockfile(FILE *f)
+ {
+- a_store(&f->lock, 0);
+-
+- /* The following read is technically invalid under situations
+- * of self-synchronized destruction. Another thread may have
+- * called fclose as soon as the above store has completed.
+- * Nonetheless, since FILE objects always live in memory
+- * obtained by malloc from the heap, it's safe to assume
+- * the dereferences below will not fault. In the worst case,
+- * a spurious syscall will be made. If the implementation of
+- * malloc changes, this assumption needs revisiting. */
+-
+- if (f->waiters) __wake(&f->lock, 1, 1);
++ if (a_swap(&f->lock, 0) & MAYBE_WAITERS)
++ __wake(&f->lock, 1, 1);
+ }
+diff --git a/src/stdio/__stdio_read.c b/src/stdio/__stdio_read.c
+index f8fa6d3b..ea675da3 100644
+--- a/src/stdio/__stdio_read.c
++++ b/src/stdio/__stdio_read.c
+@@ -9,10 +9,11 @@ size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
+ };
+ ssize_t cnt;
+
+- cnt = syscall(SYS_readv, f->fd, iov, 2);
++ cnt = iov[0].iov_len ? syscall(SYS_readv, f->fd, iov, 2)
++ : syscall(SYS_read, f->fd, iov[1].iov_base, iov[1].iov_len);
+ if (cnt <= 0) {
+- f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt);
+- return cnt;
++ f->flags |= cnt ? F_ERR : F_EOF;
++ return 0;
+ }
+ if (cnt <= iov[0].iov_len) return cnt;
+ cnt -= iov[0].iov_len;
+diff --git a/src/stdio/__towrite.c b/src/stdio/__towrite.c
+index 0a69d926..b022cbca 100644
+--- a/src/stdio/__towrite.c
++++ b/src/stdio/__towrite.c
+@@ -3,7 +3,7 @@
+ int __towrite(FILE *f)
+ {
+ f->mode |= f->mode-1;
+- if (f->flags & (F_NOWR)) {
++ if (f->flags & F_NOWR) {
+ f->flags |= F_ERR;
+ return EOF;
+ }
+diff --git a/src/stdio/fclose.c b/src/stdio/fclose.c
+index d687a877..c675413d 100644
+--- a/src/stdio/fclose.c
++++ b/src/stdio/fclose.c
+@@ -24,7 +24,7 @@ int fclose(FILE *f)
+ r = fflush(f);
+ r |= f->close(f);
+
+- if (f->getln_buf) free(f->getln_buf);
++ free(f->getln_buf);
+ if (!perm) free(f);
+ else FUNLOCK(f);
+
+diff --git a/src/stdio/fgetpos.c b/src/stdio/fgetpos.c
+index c3fa0eb0..6eb361e1 100644
+--- a/src/stdio/fgetpos.c
++++ b/src/stdio/fgetpos.c
+@@ -4,7 +4,7 @@ int fgetpos(FILE *restrict f, fpos_t *restrict pos)
+ {
+ off_t off = __ftello(f);
+ if (off < 0) return -1;
+- *(off_t *)pos = off;
++ *(long long *)pos = off;
+ return 0;
+ }
+
+diff --git a/src/stdio/flockfile.c b/src/stdio/flockfile.c
+index a196c1ef..6806cf8b 100644
+--- a/src/stdio/flockfile.c
++++ b/src/stdio/flockfile.c
+@@ -1,10 +1,11 @@
+ #include "stdio_impl.h"
+ #include "pthread_impl.h"
+
++void __register_locked_file(FILE *, pthread_t);
++
+ void flockfile(FILE *f)
+ {
+- while (ftrylockfile(f)) {
+- int owner = f->lock;
+- if (owner) __wait(&f->lock, &f->waiters, owner, 1);
+- }
++ if (!ftrylockfile(f)) return;
++ __lockfile(f);
++ __register_locked_file(f, __pthread_self());
+ }
+diff --git a/src/stdio/fmemopen.c b/src/stdio/fmemopen.c
+index 2ce43d32..fb2656e3 100644
+--- a/src/stdio/fmemopen.c
++++ b/src/stdio/fmemopen.c
+@@ -9,6 +9,12 @@ struct cookie {
+ int mode;
+ };
+
++struct mem_FILE {
++ FILE f;
++ struct cookie c;
++ unsigned char buf[UNGET+BUFSIZ], buf2[];
++};
++
+ static off_t mseek(FILE *f, off_t off, int whence)
+ {
+ ssize_t base;
+@@ -72,8 +78,7 @@ static int mclose(FILE *m)
+
+ FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode)
+ {
+- FILE *f;
+- struct cookie *c;
++ struct mem_FILE *f;
+ int plus = !!strchr(mode, '+');
+
+ if (!size || !strchr("rwa", *mode)) {
+@@ -86,29 +91,34 @@ FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode)
+ return 0;
+ }
+
+- f = calloc(sizeof *f + sizeof *c + UNGET + BUFSIZ + (buf?0:size), 1);
++ f = malloc(sizeof *f + (buf?0:size));
+ if (!f) return 0;
+- f->cookie = c = (void *)(f+1);
+- f->fd = -1;
+- f->lbf = EOF;
+- f->buf = (unsigned char *)(c+1) + UNGET;
+- f->buf_size = BUFSIZ;
+- if (!buf) buf = f->buf + BUFSIZ;
++ memset(&f->f, 0, sizeof f->f);
++ f->f.cookie = &f->c;
++ f->f.fd = -1;
++ f->f.lbf = EOF;
++ f->f.buf = f->buf + UNGET;
++ f->f.buf_size = sizeof f->buf - UNGET;
++ if (!buf) {
++ buf = f->buf2;;
++ memset(buf, 0, size);
++ }
+
+- c->buf = buf;
+- c->size = size;
+- c->mode = *mode;
++ memset(&f->c, 0, sizeof f->c);
++ f->c.buf = buf;
++ f->c.size = size;
++ f->c.mode = *mode;
+
+- if (!plus) f->flags = (*mode == 'r') ? F_NOWR : F_NORD;
+- if (*mode == 'r') c->len = size;
+- else if (*mode == 'a') c->len = c->pos = strnlen(buf, size);
++ if (!plus) f->f.flags = (*mode == 'r') ? F_NOWR : F_NORD;
++ if (*mode == 'r') f->c.len = size;
++ else if (*mode == 'a') f->c.len = f->c.pos = strnlen(buf, size);
+
+- f->read = mread;
+- f->write = mwrite;
+- f->seek = mseek;
+- f->close = mclose;
++ f->f.read = mread;
++ f->f.write = mwrite;
++ f->f.seek = mseek;
++ f->f.close = mclose;
+
+- if (!libc.threaded) f->lock = -1;
++ if (!libc.threaded) f->f.lock = -1;
+
+- return __ofl_add(f);
++ return __ofl_add(&f->f);
+ }
+diff --git a/src/stdio/fopencookie.c b/src/stdio/fopencookie.c
+index 2f46dd53..da042fe8 100644
+--- a/src/stdio/fopencookie.c
++++ b/src/stdio/fopencookie.c
+@@ -116,15 +116,12 @@ FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t iofuncs)
+
+ /* Set up our fcookie */
+ f->fc.cookie = cookie;
+- f->fc.iofuncs.read = iofuncs.read;
+- f->fc.iofuncs.write = iofuncs.write;
+- f->fc.iofuncs.seek = iofuncs.seek;
+- f->fc.iofuncs.close = iofuncs.close;
++ f->fc.iofuncs = iofuncs;
+
+ f->f.fd = -1;
+ f->f.cookie = &f->fc;
+ f->f.buf = f->buf + UNGET;
+- f->f.buf_size = BUFSIZ;
++ f->f.buf_size = sizeof f->buf - UNGET;
+ f->f.lbf = EOF;
+
+ /* Initialize op ptrs. No problem if some are unneeded. */
+diff --git a/src/stdio/fread.c b/src/stdio/fread.c
+index aef75f73..733d3716 100644
+--- a/src/stdio/fread.c
++++ b/src/stdio/fread.c
+@@ -25,7 +25,7 @@ size_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f)
+ /* Read the remainder directly */
+ for (; l; l-=k, dest+=k) {
+ k = __toread(f) ? 0 : f->read(f, dest, l);
+- if (k+1<=1) {
++ if (!k) {
+ FUNLOCK(f);
+ return (len-l)/size;
+ }
+diff --git a/src/stdio/fsetpos.c b/src/stdio/fsetpos.c
+index 5d76c8cd..6310424e 100644
+--- a/src/stdio/fsetpos.c
++++ b/src/stdio/fsetpos.c
+@@ -2,7 +2,7 @@
+
+ int fsetpos(FILE *f, const fpos_t *pos)
+ {
+- return __fseeko(f, *(const off_t *)pos, SEEK_SET);
++ return __fseeko(f, *(const long long *)pos, SEEK_SET);
+ }
+
+ LFS64(fsetpos);
+diff --git a/src/stdio/ftrylockfile.c b/src/stdio/ftrylockfile.c
+index eb13c839..3b97807a 100644
+--- a/src/stdio/ftrylockfile.c
++++ b/src/stdio/ftrylockfile.c
+@@ -2,6 +2,8 @@
+ #include "pthread_impl.h"
+ #include <limits.h>
+
++#define MAYBE_WAITERS 0x40000000
++
+ void __do_orphaned_stdio_locks()
+ {
+ FILE *f;
+@@ -18,23 +20,29 @@ void __unlist_locked_file(FILE *f)
+ }
+ }
+
++void __register_locked_file(FILE *f, pthread_t self)
++{
++ f->lockcount = 1;
++ f->prev_locked = 0;
++ f->next_locked = self->stdio_locks;
++ if (f->next_locked) f->next_locked->prev_locked = f;
++ self->stdio_locks = f;
++}
++
+ int ftrylockfile(FILE *f)
+ {
+ pthread_t self = __pthread_self();
+ int tid = self->tid;
+- if (f->lock == tid) {
++ int owner = f->lock;
++ if ((owner & ~MAYBE_WAITERS) == tid) {
+ if (f->lockcount == LONG_MAX)
+ return -1;
+ f->lockcount++;
+ return 0;
+ }
+- if (f->lock < 0) f->lock = 0;
+- if (f->lock || a_cas(&f->lock, 0, tid))
++ if (owner < 0) f->lock = owner = 0;
++ if (owner || a_cas(&f->lock, 0, tid))
+ return -1;
+- f->lockcount = 1;
+- f->prev_locked = 0;
+- f->next_locked = self->stdio_locks;
+- if (f->next_locked) f->next_locked->prev_locked = f;
+- self->stdio_locks = f;
++ __register_locked_file(f, self);
+ return 0;
+ }
+diff --git a/src/stdio/getdelim.c b/src/stdio/getdelim.c
+index 1ccd8029..d4b23882 100644
+--- a/src/stdio/getdelim.c
++++ b/src/stdio/getdelim.c
+@@ -3,8 +3,6 @@
+ #include <inttypes.h>
+ #include <errno.h>
+
+-#define MIN(a,b) ((a)<(b) ? (a) : (b))
+-
+ ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restrict f)
+ {
+ char *tmp;
+diff --git a/src/stdio/open_memstream.c b/src/stdio/open_memstream.c
+index eab024da..ee834234 100644
+--- a/src/stdio/open_memstream.c
++++ b/src/stdio/open_memstream.c
+@@ -12,6 +12,12 @@ struct cookie {
+ size_t space;
+ };
+
++struct ms_FILE {
++ FILE f;
++ struct cookie c;
++ unsigned char buf[BUFSIZ];
++};
++
+ static off_t ms_seek(FILE *f, off_t off, int whence)
+ {
+ ssize_t base;
+@@ -57,34 +63,34 @@ static int ms_close(FILE *f)
+
+ FILE *open_memstream(char **bufp, size_t *sizep)
+ {
+- FILE *f;
+- struct cookie *c;
++ struct ms_FILE *f;
+ char *buf;
+
+- if (!(f=malloc(sizeof *f + sizeof *c + BUFSIZ))) return 0;
++ if (!(f=malloc(sizeof *f))) return 0;
+ if (!(buf=malloc(sizeof *buf))) {
+ free(f);
+ return 0;
+ }
+- memset(f, 0, sizeof *f + sizeof *c);
+- f->cookie = c = (void *)(f+1);
++ memset(&f->f, 0, sizeof f->f);
++ memset(&f->c, 0, sizeof f->c);
++ f->f.cookie = &f->c;
+
+- c->bufp = bufp;
+- c->sizep = sizep;
+- c->pos = c->len = c->space = *sizep = 0;
+- c->buf = *bufp = buf;
++ f->c.bufp = bufp;
++ f->c.sizep = sizep;
++ f->c.pos = f->c.len = f->c.space = *sizep = 0;
++ f->c.buf = *bufp = buf;
+ *buf = 0;
+
+- f->flags = F_NORD;
+- f->fd = -1;
+- f->buf = (void *)(c+1);
+- f->buf_size = BUFSIZ;
+- f->lbf = EOF;
+- f->write = ms_write;
+- f->seek = ms_seek;
+- f->close = ms_close;
++ f->f.flags = F_NORD;
++ f->f.fd = -1;
++ f->f.buf = f->buf;
++ f->f.buf_size = sizeof f->buf;
++ f->f.lbf = EOF;
++ f->f.write = ms_write;
++ f->f.seek = ms_seek;
++ f->f.close = ms_close;
+
+- if (!libc.threaded) f->lock = -1;
++ if (!libc.threaded) f->f.lock = -1;
+
+- return __ofl_add(f);
++ return __ofl_add(&f->f);
+ }
+diff --git a/src/stdio/open_wmemstream.c b/src/stdio/open_wmemstream.c
+index 4d90cd97..cb693ea7 100644
+--- a/src/stdio/open_wmemstream.c
++++ b/src/stdio/open_wmemstream.c
+@@ -14,6 +14,12 @@ struct cookie {
+ mbstate_t mbs;
+ };
+
++struct wms_FILE {
++ FILE f;
++ struct cookie c;
++ unsigned char buf[1];
++};
++
+ static off_t wms_seek(FILE *f, off_t off, int whence)
+ {
+ ssize_t base;
+@@ -59,34 +65,34 @@ static int wms_close(FILE *f)
+
+ FILE *open_wmemstream(wchar_t **bufp, size_t *sizep)
+ {
+- FILE *f;
+- struct cookie *c;
++ struct wms_FILE *f;
+ wchar_t *buf;
+
+- if (!(f=malloc(sizeof *f + sizeof *c))) return 0;
++ if (!(f=malloc(sizeof *f))) return 0;
+ if (!(buf=malloc(sizeof *buf))) {
+ free(f);
+ return 0;
+ }
+- memset(f, 0, sizeof *f + sizeof *c);
+- f->cookie = c = (void *)(f+1);
++ memset(&f->f, 0, sizeof f->f);
++ memset(&f->c, 0, sizeof f->c);
++ f->f.cookie = &f->c;
+
+- c->bufp = bufp;
+- c->sizep = sizep;
+- c->pos = c->len = c->space = *sizep = 0;
+- c->buf = *bufp = buf;
++ f->c.bufp = bufp;
++ f->c.sizep = sizep;
++ f->c.pos = f->c.len = f->c.space = *sizep = 0;
++ f->c.buf = *bufp = buf;
+ *buf = 0;
+
+- f->flags = F_NORD;
+- f->fd = -1;
+- f->buf = (void *)(c+1);
+- f->buf_size = 0;
+- f->lbf = EOF;
+- f->write = wms_write;
+- f->seek = wms_seek;
+- f->close = wms_close;
++ f->f.flags = F_NORD;
++ f->f.fd = -1;
++ f->f.buf = f->buf;
++ f->f.buf_size = 0;
++ f->f.lbf = EOF;
++ f->f.write = wms_write;
++ f->f.seek = wms_seek;
++ f->f.close = wms_close;
+
+- if (!libc.threaded) f->lock = -1;
++ if (!libc.threaded) f->f.lock = -1;
+
+- return __ofl_add(f);
++ return __ofl_add(&f->f);
+ }
+diff --git a/src/stdio/setvbuf.c b/src/stdio/setvbuf.c
+index 541a125f..06ea296c 100644
+--- a/src/stdio/setvbuf.c
++++ b/src/stdio/setvbuf.c
+@@ -1,22 +1,25 @@
+ #include "stdio_impl.h"
+
+-/* This function makes no attempt to protect the user from his/her own
+- * stupidity. If called any time but when then ISO C standard specifically
+- * allows it, all hell can and will break loose, especially with threads!
+- *
+- * This implementation ignores all arguments except the buffering type,
+- * and uses the existing buffer allocated alongside the FILE object.
+- * In the case of stderr where the preexisting buffer is length 1, it
+- * is not possible to set line buffering or full buffering. */
++/* The behavior of this function is undefined except when it is the first
++ * operation on the stream, so the presence or absence of locking is not
++ * observable in a program whose behavior is defined. Thus no locking is
++ * performed here. No allocation of buffers is performed, but a buffer
++ * provided by the caller is used as long as it is suitably sized. */
+
+ int setvbuf(FILE *restrict f, char *restrict buf, int type, size_t size)
+ {
+ f->lbf = EOF;
+
+- if (type == _IONBF)
++ if (type == _IONBF) {
+ f->buf_size = 0;
+- else if (type == _IOLBF)
+- f->lbf = '\n';
++ } else {
++ if (buf && size >= UNGET) {
++ f->buf = (void *)(buf + UNGET);
++ f->buf_size = size - UNGET;
++ }
++ if (type == _IOLBF && f->buf_size)
++ f->lbf = '\n';
++ }
+
+ f->flags |= F_SVB;
+
+diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
+index 50fb55c1..5e7be717 100644
+--- a/src/stdio/vfprintf.c
++++ b/src/stdio/vfprintf.c
+@@ -220,6 +220,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
+ else re=LDBL_MANT_DIG/4-1-p;
+
+ if (re) {
++ round *= 1<<(LDBL_MANT_DIG%4);
+ while (re--) round*=16;
+ if (*prefix=='-') {
+ y=-y;
+diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c
+index e87ad42a..9d774fcc 100644
+--- a/src/stdio/vfwprintf.c
++++ b/src/stdio/vfwprintf.c
+@@ -255,8 +255,11 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
+ }
+ continue;
+ case 'c':
++ if (w<1) w=1;
++ if (w>1 && !(fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, "");
+ fputwc(btowc(arg.i), f);
+- l = 1;
++ if (w>1 && (fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, "");
++ l = w;
+ continue;
+ case 'C':
+ fputwc(arg.i, f);
+diff --git a/src/stdio/vswprintf.c b/src/stdio/vswprintf.c
+index 6eb2f6ac..38efed65 100644
+--- a/src/stdio/vswprintf.c
++++ b/src/stdio/vswprintf.c
+@@ -1,6 +1,5 @@
+ #include "stdio_impl.h"
+ #include <limits.h>
+-#include <string.h>
+ #include <errno.h>
+ #include <stdint.h>
+ #include <wchar.h>
+@@ -37,17 +36,17 @@ static size_t sw_write(FILE *f, const unsigned char *s, size_t l)
+ 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/abs.c b/src/stdlib/abs.c
+index 4806d629..e721fdc2 100644
+--- a/src/stdlib/abs.c
++++ b/src/stdlib/abs.c
+@@ -1,3 +1,5 @@
++#include <stdlib.h>
++
+ int abs(int a)
+ {
+ return a>0 ? a : -a;
+diff --git a/src/stdlib/bsearch.c b/src/stdlib/bsearch.c
+index 61d89367..fe050ea3 100644
+--- a/src/stdlib/bsearch.c
++++ b/src/stdlib/bsearch.c
+@@ -7,13 +7,13 @@ void *bsearch(const void *key, const void *base, size_t nel, size_t width, int (
+ while (nel > 0) {
+ try = (char *)base + width*(nel/2);
+ sign = cmp(key, try);
+- if (!sign) return try;
+- else if (nel == 1) break;
+- else if (sign < 0)
++ if (sign < 0) {
+ nel /= 2;
+- else {
+- base = try;
+- nel -= nel/2;
++ } else if (sign > 0) {
++ base = (char *)try + width;
++ nel -= nel/2+1;
++ } else {
++ return try;
+ }
+ }
+ return NULL;
+diff --git a/src/stdlib/labs.c b/src/stdlib/labs.c
+index 675b95b8..83ddb147 100644
+--- a/src/stdlib/labs.c
++++ b/src/stdlib/labs.c
+@@ -1,3 +1,5 @@
++#include <stdlib.h>
++
+ long labs(long a)
+ {
+ return a>0 ? a : -a;
+diff --git a/src/stdlib/llabs.c b/src/stdlib/llabs.c
+index bec4a03d..9dfaf5cf 100644
+--- a/src/stdlib/llabs.c
++++ b/src/stdlib/llabs.c
+@@ -1,3 +1,5 @@
++#include <stdlib.h>
++
+ long long llabs(long long a)
+ {
+ return a>0 ? a : -a;
+diff --git a/src/string/explicit_bzero.c b/src/string/explicit_bzero.c
+new file mode 100644
+index 00000000..f2e12f23
+--- /dev/null
++++ b/src/string/explicit_bzero.c
+@@ -0,0 +1,8 @@
++#define _BSD_SOURCE
++#include <string.h>
++
++void explicit_bzero(void *d, size_t n)
++{
++ d = memset(d, 0, n);
++ __asm__ __volatile__ ("" : : "r"(d) : "memory");
++}
+diff --git a/src/thread/default_attr.c b/src/thread/default_attr.c
+new file mode 100644
+index 00000000..46fe98ee
+--- /dev/null
++++ b/src/thread/default_attr.c
+@@ -0,0 +1,4 @@
++#include "pthread_impl.h"
++
++size_t __default_stacksize = DEFAULT_STACK_SIZE;
++size_t __default_guardsize = DEFAULT_GUARD_SIZE;
+diff --git a/src/thread/m68k/__m68k_read_tp.s b/src/thread/m68k/__m68k_read_tp.s
+new file mode 100644
+index 00000000..86886da8
+--- /dev/null
++++ b/src/thread/m68k/__m68k_read_tp.s
+@@ -0,0 +1,8 @@
++.text
++.global __m68k_read_tp
++.type __m68k_read_tp,@function
++__m68k_read_tp:
++ move.l #333,%d0
++ trap #0
++ move.l %d0,%a0
++ rts
+diff --git a/src/thread/m68k/clone.s b/src/thread/m68k/clone.s
+new file mode 100644
+index 00000000..5b61b6fa
+--- /dev/null
++++ b/src/thread/m68k/clone.s
+@@ -0,0 +1,24 @@
++.text
++.global __clone
++.type __clone,@function
++__clone:
++ movem.l %d2-%d5,-(%sp)
++ move.l #120,%d0
++ move.l 28(%sp),%d1
++ move.l 24(%sp),%d2
++ and.l #-16,%d2
++ move.l 36(%sp),%d3
++ move.l 44(%sp),%d4
++ move.l 40(%sp),%d5
++ move.l 20(%sp),%a0
++ move.l 32(%sp),%a1
++ trap #0
++ tst.l %d0
++ beq 1f
++ movem.l (%sp)+,%d2-%d5
++ rts
++1: move.l %a1,-(%sp)
++ jsr (%a0)
++ move.l #1,%d0
++ trap #0
++ clr.b 0
+diff --git a/src/thread/m68k/syscall_cp.s b/src/thread/m68k/syscall_cp.s
+new file mode 100644
+index 00000000..5628a896
+--- /dev/null
++++ b/src/thread/m68k/syscall_cp.s
+@@ -0,0 +1,26 @@
++.text
++.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:
++ movem.l %d2-%d5,-(%sp)
++ movea.l 20(%sp),%a0
++__cp_begin:
++ move.l (%a0),%d0
++ bne __cp_cancel
++ movem.l 24(%sp),%d0-%d5/%a0
++ trap #0
++__cp_end:
++ movem.l (%sp)+,%d2-%d5
++ rts
++__cp_cancel:
++ movem.l (%sp)+,%d2-%d5
++ move.l __cancel-.-8,%a1
++ jmp (%pc,%a1)
+diff --git a/src/thread/mips/clone.s b/src/thread/mips/clone.s
+index 37dddf57..30a0146b 100644
+--- a/src/thread/mips/clone.s
++++ b/src/thread/mips/clone.s
+@@ -28,5 +28,8 @@ __clone:
+ nop
+ 1: lw $25, 0($sp)
+ lw $4, 4($sp)
+- jr $25
++ jalr $25
+ nop
++ move $4, $2
++ li $2, 4001
++ syscall
+diff --git a/src/thread/mips64/clone.s b/src/thread/mips64/clone.s
+index 229d2677..1b71e07c 100644
+--- a/src/thread/mips64/clone.s
++++ b/src/thread/mips64/clone.s
+@@ -26,5 +26,8 @@ __clone:
+ nop
+ 1: ld $25, 0($sp) # function pointer
+ ld $4, 8($sp) # argument pointer
+- jr $25 # call the user's function
++ jalr $25 # call the user's function
+ nop
++ move $4, $2
++ li $2, 5058
++ syscall
+diff --git a/src/thread/mipsn32/clone.s b/src/thread/mipsn32/clone.s
+index 51035852..ebf5dbea 100644
+--- a/src/thread/mipsn32/clone.s
++++ b/src/thread/mipsn32/clone.s
+@@ -26,5 +26,8 @@ __clone:
+ nop
+ 1: lw $25, 0($sp) # function pointer
+ lw $4, 4($sp) # argument pointer
+- jr $25 # call the user's function
++ jalr $25 # call the user's function
+ nop
++ move $4, $2
++ li $2, 6058
++ syscall
+diff --git a/src/thread/pthread_attr_init.c b/src/thread/pthread_attr_init.c
+index 8f6e3374..a962b460 100644
+--- a/src/thread/pthread_attr_init.c
++++ b/src/thread/pthread_attr_init.c
+@@ -1,9 +1,12 @@
+ #include "pthread_impl.h"
+
++extern size_t __default_stacksize;
++extern size_t __default_guardsize;
++
+ int pthread_attr_init(pthread_attr_t *a)
+ {
+ *a = (pthread_attr_t){0};
+- a->_a_stacksize = DEFAULT_STACK_SIZE;
+- a->_a_guardsize = DEFAULT_GUARD_SIZE;
++ a->_a_stacksize = __default_stacksize;
++ a->_a_guardsize = __default_guardsize;
+ return 0;
+ }
+diff --git a/src/thread/pthread_attr_setinheritsched.c b/src/thread/pthread_attr_setinheritsched.c
+index c91d8f83..e540e846 100644
+--- a/src/thread/pthread_attr_setinheritsched.c
++++ b/src/thread/pthread_attr_setinheritsched.c
+@@ -1,4 +1,25 @@
+ #include "pthread_impl.h"
++#include "syscall.h"
++
++__attribute__((__visibility__("hidden")))
++void *__start_sched(void *p)
++{
++ struct start_sched_args *ssa = p;
++ void *start_arg = ssa->start_arg;
++ void *(*start_fn)(void *) = ssa->start_fn;
++ pthread_t self = __pthread_self();
++
++ int ret = -__syscall(SYS_sched_setscheduler, self->tid,
++ ssa->attr->_a_policy, &ssa->attr->_a_prio);
++ if (!ret) __restore_sigs(&ssa->mask);
++ a_store(&ssa->futex, ret);
++ __wake(&ssa->futex, 1, 1);
++ if (ret) {
++ self->detach_state = DT_DYNAMIC;
++ return 0;
++ }
++ return start_fn(start_arg);
++}
+
+ int pthread_attr_setinheritsched(pthread_attr_t *a, int inherit)
+ {
+diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
+index 439ee363..27ace2c6 100644
+--- a/src/thread/pthread_create.c
++++ b/src/thread/pthread_create.c
+@@ -19,6 +19,12 @@ weak_alias(dummy_0, __pthread_tsd_run_dtors);
+ weak_alias(dummy_0, __do_orphaned_stdio_locks);
+ weak_alias(dummy_0, __dl_thread_cleanup);
+
++static void *dummy_1(void *p)
++{
++ return 0;
++}
++weak_alias(dummy_1, __start_sched);
++
+ _Noreturn void __pthread_exit(void *result)
+ {
+ pthread_t self = __pthread_self();
+@@ -37,11 +43,11 @@ _Noreturn void __pthread_exit(void *result)
+
+ __pthread_tsd_run_dtors();
+
+- LOCK(self->exitlock);
+-
+- /* Mark this thread dead before decrementing count */
++ /* Access to target the exiting thread with syscalls that use
++ * its kernel tid is controlled by killlock. For detached threads,
++ * any use past this point would have undefined behavior, but for
++ * joinable threads it's a valid usage that must be handled. */
+ LOCK(self->killlock);
+- self->dead = 1;
+
+ /* Block all signals before decrementing the live thread count.
+ * This is important to ensure that dynamically allocated TLS
+@@ -49,20 +55,14 @@ _Noreturn void __pthread_exit(void *result)
+ * reasons as well. */
+ __block_all_sigs(&set);
+
+- /* Wait to unlock the kill lock, which governs functions like
+- * pthread_kill which target a thread id, until signals have
+- * been blocked. This precludes observation of the thread id
+- * as a live thread (with application code running in it) after
+- * the thread was reported dead by ESRCH being returned. */
+- UNLOCK(self->killlock);
+-
+ /* It's impossible to determine whether this is "the last thread"
+ * until performing the atomic decrement, since multiple threads
+ * could exit at the same time. For the last thread, revert the
+- * decrement and unblock signals to give the atexit handlers and
+- * stdio cleanup code a consistent state. */
++ * decrement, restore the tid, and unblock signals to give the
++ * atexit handlers and stdio cleanup code a consistent state. */
+ if (a_fetch_add(&libc.threads_minus_1, -1)==0) {
+ libc.threads_minus_1 = 0;
++ UNLOCK(self->killlock);
+ __restore_sigs(&set);
+ exit(0);
+ }
+@@ -89,15 +89,19 @@ _Noreturn void __pthread_exit(void *result)
+ __do_orphaned_stdio_locks();
+ __dl_thread_cleanup();
+
+- if (self->detached && self->map_base) {
++ /* This atomic potentially competes with a concurrent pthread_detach
++ * call; the loser is responsible for freeing thread resources. */
++ int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
++
++ if (state>=DT_DETACHED && self->map_base) {
+ /* Detached threads must avoid the kernel clear_child_tid
+ * feature, since the virtual address will have been
+ * unmapped and possibly already reused by a new mapping
+ * at the time the kernel would perform the write. In
+ * the case of threads that started out detached, the
+ * initial clone flags are correct, but if the thread was
+- * detached later (== 2), we need to clear it here. */
+- if (self->detached == 2) __syscall(SYS_set_tid_address, 0);
++ * detached later, we need to clear it here. */
++ if (state == DT_DYNAMIC) __syscall(SYS_set_tid_address, 0);
+
+ /* Robust list will no longer be valid, and was already
+ * processed above, so unregister it with the kernel. */
+@@ -113,6 +117,12 @@ _Noreturn void __pthread_exit(void *result)
+ __unmapself(self->map_base, self->map_size);
+ }
+
++ /* 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);
+ }
+
+@@ -131,19 +141,6 @@ void __do_cleanup_pop(struct __ptcb *cb)
+ static int start(void *p)
+ {
+ pthread_t self = p;
+- /* States for startlock:
+- * 0 = no need for start sync
+- * 1 = waiting for parent to do work
+- * 2 = failure in parent, child must abort
+- * 3 = success in parent, child must restore sigmask */
+- if (self->startlock[0]) {
+- __wait(self->startlock, 0, 1, 1);
+- if (self->startlock[0] == 2) {
+- self->detached = 2;
+- pthread_exit(0);
+- }
+- __restore_sigs(self->sigmask);
+- }
+ if (self->unblock_cancel)
+ __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
+ SIGPT_SET, 0, _NSIG/8);
+@@ -168,8 +165,8 @@ static void *dummy_tsd[1] = { 0 };
+ weak_alias(dummy_tsd, __pthread_tsd_main);
+
+ volatile int __block_new_threads = 0;
+-size_t __default_stacksize = DEFAULT_STACK_SIZE;
+-size_t __default_guardsize = DEFAULT_GUARD_SIZE;
++extern size_t __default_stacksize;
++extern size_t __default_guardsize;
+
+ static FILE *volatile dummy_file = 0;
+ weak_alias(dummy_file, __stdin_used);
+@@ -194,6 +191,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
+ | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED;
+ int do_sched = 0;
+ pthread_attr_t attr = { 0 };
++ struct start_sched_args ssa;
+
+ if (!libc.can_do_threads) return ENOSYS;
+ self = __pthread_self();
+@@ -272,24 +270,32 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
+ new->tsd = (void *)tsd;
+ new->locale = &libc.global_locale;
+ if (attr._a_detach) {
+- new->detached = 1;
++ new->detach_state = DT_DETACHED;
+ flags -= CLONE_CHILD_CLEARTID;
++ } else {
++ new->detach_state = DT_JOINABLE;
+ }
+ if (attr._a_sched) {
+- do_sched = new->startlock[0] = 1;
+- __block_app_sigs(new->sigmask);
++ do_sched = 1;
++ ssa.futex = -1;
++ ssa.start_fn = new->start;
++ ssa.start_arg = new->start_arg;
++ ssa.attr = &attr;
++ new->start = __start_sched;
++ new->start_arg = &ssa;
++ __block_app_sigs(&ssa.mask);
+ }
+ new->robust_list.head = &new->robust_list.head;
+ new->unblock_cancel = self->cancel;
+ new->CANARY = self->CANARY;
+
+ a_inc(&libc.threads_minus_1);
+- ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->tid);
++ ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->detach_state);
+
+ __release_ptc();
+
+ if (do_sched) {
+- __restore_sigs(new->sigmask);
++ __restore_sigs(&ssa.mask);
+ }
+
+ if (ret < 0) {
+@@ -299,11 +305,9 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
+ }
+
+ if (do_sched) {
+- ret = __syscall(SYS_sched_setscheduler, new->tid,
+- attr._a_policy, &attr._a_prio);
+- a_store(new->startlock, ret<0 ? 2 : 3);
+- __wake(new->startlock, 1, 1);
+- if (ret < 0) return -ret;
++ __futexwait(&ssa.futex, -1, 1);
++ ret = ssa.futex;
++ if (ret) return ret;
+ }
+
+ *res = new;
+diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c
+index 692bbaf9..9cee7a89 100644
+--- a/src/thread/pthread_detach.c
++++ b/src/thread/pthread_detach.c
+@@ -5,11 +5,10 @@ int __pthread_join(pthread_t, void **);
+
+ static int __pthread_detach(pthread_t t)
+ {
+- /* Cannot detach a thread that's already exiting */
+- if (a_cas(t->exitlock, 0, INT_MIN + 1))
++ /* 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_DYNAMIC) != DT_JOINABLE)
+ return __pthread_join(t, 0);
+- t->detached = 2;
+- UNLOCK(t->exitlock);
+ return 0;
+ }
+
+diff --git a/src/thread/pthread_getattr_np.c b/src/thread/pthread_getattr_np.c
+index 29a209bd..2881831f 100644
+--- a/src/thread/pthread_getattr_np.c
++++ b/src/thread/pthread_getattr_np.c
+@@ -6,7 +6,7 @@
+ int pthread_getattr_np(pthread_t t, pthread_attr_t *a)
+ {
+ *a = (pthread_attr_t){0};
+- a->_a_detach = !!t->detached;
++ a->_a_detach = t->detach_state>=DT_DETACHED;
+ a->_a_guardsize = t->guard_size;
+ if (t->stack) {
+ a->_a_stackaddr = (uintptr_t)t->stack;
+diff --git a/src/thread/pthread_getschedparam.c b/src/thread/pthread_getschedparam.c
+index a994b637..05be4242 100644
+--- a/src/thread/pthread_getschedparam.c
++++ b/src/thread/pthread_getschedparam.c
+@@ -4,7 +4,7 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param
+ {
+ int r;
+ LOCK(t->killlock);
+- if (t->dead) {
++ if (!t->tid) {
+ r = ESRCH;
+ } else {
+ r = -__syscall(SYS_sched_getparam, t->tid, param);
+diff --git a/src/thread/pthread_join.c b/src/thread/pthread_join.c
+index b7175c09..18264da6 100644
+--- a/src/thread/pthread_join.c
++++ b/src/thread/pthread_join.c
+@@ -7,13 +7,14 @@ int __pthread_setcancelstate(int, int *);
+
+ int __pthread_timedjoin_np(pthread_t t, void **res, const struct timespec *at)
+ {
+- int tmp, cs, r = 0;
++ int state, cs, r = 0;
+ __pthread_testcancel();
+ __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+ if (cs == PTHREAD_CANCEL_ENABLE) __pthread_setcancelstate(cs, 0);
+- if (t->detached) a_crash();
+- while ((tmp = t->tid) && r != ETIMEDOUT && r != EINVAL)
+- r = __timedwait_cp(&t->tid, tmp, CLOCK_REALTIME, at, 0);
++ while ((state = t->detach_state) && r != ETIMEDOUT && r != EINVAL) {
++ if (state >= DT_DETACHED) a_crash();
++ r = __timedwait_cp(&t->detach_state, state, CLOCK_REALTIME, at, 0);
++ }
+ __pthread_setcancelstate(cs, 0);
+ if (r == ETIMEDOUT || r == EINVAL) return r;
+ a_barrier();
+@@ -29,7 +30,7 @@ int __pthread_join(pthread_t t, void **res)
+
+ int __pthread_tryjoin_np(pthread_t t, void **res)
+ {
+- return t->tid ? EBUSY : __pthread_join(t, res);
++ return t->detach_state==DT_JOINABLE ? EBUSY : __pthread_join(t, res);
+ }
+
+ weak_alias(__pthread_tryjoin_np, pthread_tryjoin_np);
+diff --git a/src/thread/pthread_kill.c b/src/thread/pthread_kill.c
+index f0903420..6d70e626 100644
+--- a/src/thread/pthread_kill.c
++++ b/src/thread/pthread_kill.c
+@@ -4,7 +4,8 @@ int pthread_kill(pthread_t t, int sig)
+ {
+ int r;
+ LOCK(t->killlock);
+- r = t->dead ? ESRCH : -__syscall(SYS_tkill, t->tid, sig);
++ r = t->tid ? -__syscall(SYS_tkill, t->tid, sig)
++ : (sig+0U >= _NSIG ? EINVAL : 0);
+ UNLOCK(t->killlock);
+ return r;
+ }
+diff --git a/src/thread/pthread_setschedparam.c b/src/thread/pthread_setschedparam.c
+index 9e2fa456..ab45f2ff 100644
+--- a/src/thread/pthread_setschedparam.c
++++ b/src/thread/pthread_setschedparam.c
+@@ -4,7 +4,7 @@ int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *par
+ {
+ int r;
+ LOCK(t->killlock);
+- r = t->dead ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param);
++ r = !t->tid ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param);
+ UNLOCK(t->killlock);
+ return r;
+ }
+diff --git a/src/thread/pthread_setschedprio.c b/src/thread/pthread_setschedprio.c
+index dc745b42..c353f6b5 100644
+--- a/src/thread/pthread_setschedprio.c
++++ b/src/thread/pthread_setschedprio.c
+@@ -4,7 +4,7 @@ int pthread_setschedprio(pthread_t t, int prio)
+ {
+ int r;
+ LOCK(t->killlock);
+- r = t->dead ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio);
++ r = !t->tid ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio);
+ UNLOCK(t->killlock);
+ return r;
+ }
+diff --git a/src/time/strftime.c b/src/time/strftime.c
+index 708875ee..d3f2add9 100644
+--- a/src/time/strftime.c
++++ b/src/time/strftime.c
+@@ -181,9 +181,8 @@ 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",
+- (tm->__tm_gmtoff)/3600,
+- abs(tm->__tm_gmtoff%3600)/60);
++ *l = snprintf(*s, sizeof *s, "%+.4ld",
++ tm->__tm_gmtoff/3600*100 + tm->__tm_gmtoff%3600/60);
+ return *s;
+ case 'Z':
+ if (tm->tm_isdst < 0) {
+diff --git a/src/time/timespec_get.c b/src/time/timespec_get.c
+index 03c5a77b..c423b825 100644
+--- a/src/time/timespec_get.c
++++ b/src/time/timespec_get.c
+@@ -6,7 +6,7 @@ int __clock_gettime(clockid_t, struct timespec *);
+ * are considered erroneous. */
+ int timespec_get(struct timespec * ts, int base)
+ {
+- if (base != TIME_UTC) return 0;
++ if (base != 1) return 0;
+ int ret = __clock_gettime(CLOCK_REALTIME, ts);
+ return ret < 0 ? 0 : base;
+ }
+diff --git a/src/time/wcsftime.c b/src/time/wcsftime.c
+index 638e64f6..23500cc8 100644
+--- a/src/time/wcsftime.c
++++ b/src/time/wcsftime.c
+@@ -4,7 +4,7 @@
+ #include "locale_impl.h"
+ #include "libc.h"
+
+-const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc);
++const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc, int pad);
+
+ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, const struct tm *restrict tm, locale_t loc)
+ {
+@@ -14,7 +14,7 @@ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, co
+ wchar_t *p;
+ const char *t_mb;
+ const wchar_t *t;
+- int plus;
++ int pad, plus;
+ unsigned long width;
+ for (l=0; l<n; f++) {
+ if (!*f) {
+@@ -26,6 +26,8 @@ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, co
+ continue;
+ }
+ f++;
++ pad = 0;
++ if (*f == '-' || *f == '_' || *f == '0') pad = *f++;
+ if ((plus = (*f == '+'))) f++;
+ width = wcstoul(f, &p, 10);
+ if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') {
+@@ -35,7 +37,7 @@ size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, co
+ }
+ f = p;
+ if (*f == 'E' || *f == 'O') f++;
+- t_mb = __strftime_fmt_1(&buf, &k, *f, tm, loc);
++ t_mb = __strftime_fmt_1(&buf, &k, *f, tm, loc, pad);
+ if (!t_mb) break;
+ k = mbstowcs(wbuf, t_mb, sizeof wbuf / sizeof *wbuf);
+ if (k == (size_t)-1) return 0;
+diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c
+index 103fbbb5..f407ffe0 100644
+--- a/src/unistd/getcwd.c
++++ b/src/unistd/getcwd.c
+@@ -6,10 +6,10 @@
+
+ char *getcwd(char *buf, size_t size)
+ {
+- char tmp[PATH_MAX];
++ char tmp[buf ? 1 : PATH_MAX];
+ if (!buf) {
+ buf = tmp;
+- size = PATH_MAX;
++ size = sizeof tmp;
+ } else if (!size) {
+ errno = EINVAL;
+ return 0;
+diff --git a/src/unistd/gethostname.c b/src/unistd/gethostname.c
+index f984b7dd..633ef571 100644
+--- a/src/unistd/gethostname.c
++++ b/src/unistd/gethostname.c
+@@ -8,6 +8,6 @@ int gethostname(char *name, size_t len)
+ if (uname(&uts)) return -1;
+ if (len > sizeof uts.nodename) len = sizeof uts.nodename;
+ for (i=0; i<len && (name[i] = uts.nodename[i]); i++);
+- if (i==len) name[i-1] = 0;
++ if (i && i==len) name[i-1] = 0;
+ return 0;
+ }
+diff --git a/src/unistd/nice.c b/src/unistd/nice.c
+index da569967..6c25c8c3 100644
+--- a/src/unistd/nice.c
++++ b/src/unistd/nice.c
+@@ -1,12 +1,16 @@
+ #include <unistd.h>
+ #include <sys/resource.h>
++#include <limits.h>
+ #include "syscall.h"
+
+ int nice(int inc)
+ {
+-#ifdef SYS_nice
+- return syscall(SYS_nice, inc);
+-#else
+- return setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS, 0)+inc);
+-#endif
++ int prio = inc;
++ // Only query old priority if it can affect the result.
++ // This also avoids issues with integer overflow.
++ if (inc > -2*NZERO && inc < 2*NZERO)
++ 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;
+ }
+diff --git a/tools/musl-gcc.specs.sh b/tools/musl-gcc.specs.sh
+index 294e24f7..30492574 100644
+--- a/tools/musl-gcc.specs.sh
++++ b/tools/musl-gcc.specs.sh
+@@ -17,10 +17,10 @@ cat <<EOF
+ libgcc.a%s %:if-exists(libgcc_eh.a%s)
+
+ *startfile:
+-%{!shared: $libdir/%{pie:S}crt1.o} $libdir/crti.o %{shared|pie:crtbeginS.o%s;:crtbegin.o%s}
++%{!shared: $libdir/Scrt1.o} $libdir/crti.o crtbeginS.o%s
+
+ *endfile:
+-%{shared|pie:crtendS.o%s;:crtend.o%s} $libdir/crtn.o
++crtendS.o%s $libdir/crtn.o
+
+ *link:
+ -dynamic-linker $ldso -nostdlib %{shared:-shared} %{static:-static} %{rdynamic:-export-dynamic}