diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 13:54:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 13:54:38 +0000 |
commit | 8c1ab65c0f548d20b7f177bdb736daaf603340e1 (patch) | |
tree | df55b7e75bf43f2bf500845b105afe3ac3a5157e /libc-top-half/musl/src/internal | |
parent | Initial commit. (diff) | |
download | wasi-libc-8c1ab65c0f548d20b7f177bdb736daaf603340e1.tar.xz wasi-libc-8c1ab65c0f548d20b7f177bdb736daaf603340e1.zip |
Adding upstream version 0.0~git20221206.8b7148f.upstream/0.0_git20221206.8b7148f
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libc-top-half/musl/src/internal')
29 files changed, 2664 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/internal/aio_impl.h b/libc-top-half/musl/src/internal/aio_impl.h new file mode 100644 index 0000000..a865766 --- /dev/null +++ b/libc-top-half/musl/src/internal/aio_impl.h @@ -0,0 +1,9 @@ +#ifndef AIO_IMPL_H +#define AIO_IMPL_H + +extern hidden volatile int __aio_fut; + +extern hidden int __aio_close(int); +extern hidden void __aio_atfork(int); + +#endif diff --git a/libc-top-half/musl/src/internal/atomic.h b/libc-top-half/musl/src/internal/atomic.h new file mode 100644 index 0000000..96c1552 --- /dev/null +++ b/libc-top-half/musl/src/internal/atomic.h @@ -0,0 +1,333 @@ +#ifndef _ATOMIC_H +#define _ATOMIC_H + +#include <stdint.h> + +#include "atomic_arch.h" + +#ifdef a_ll + +#ifndef a_pre_llsc +#define a_pre_llsc() +#endif + +#ifndef a_post_llsc +#define a_post_llsc() +#endif + +#ifndef a_cas +#define a_cas a_cas +static inline int a_cas(volatile int *p, int t, int s) +{ + int old; + a_pre_llsc(); + do old = a_ll(p); + while (old==t && !a_sc(p, s)); + a_post_llsc(); + return old; +} +#endif + +#ifndef a_swap +#define a_swap a_swap +static inline int a_swap(volatile int *p, int v) +{ + int old; + a_pre_llsc(); + do old = a_ll(p); + while (!a_sc(p, v)); + a_post_llsc(); + return old; +} +#endif + +#ifndef a_fetch_add +#define a_fetch_add a_fetch_add +static inline int a_fetch_add(volatile int *p, int v) +{ + int old; + a_pre_llsc(); + do old = a_ll(p); + while (!a_sc(p, (unsigned)old + v)); + a_post_llsc(); + return old; +} +#endif + +#ifndef a_fetch_and +#define a_fetch_and a_fetch_and +static inline int a_fetch_and(volatile int *p, int v) +{ + int old; + a_pre_llsc(); + do old = a_ll(p); + while (!a_sc(p, old & v)); + a_post_llsc(); + return old; +} +#endif + +#ifndef a_fetch_or +#define a_fetch_or a_fetch_or +static inline int a_fetch_or(volatile int *p, int v) +{ + int old; + a_pre_llsc(); + do old = a_ll(p); + while (!a_sc(p, old | v)); + a_post_llsc(); + return old; +} +#endif + +#endif + +#ifdef a_ll_p + +#ifndef a_cas_p +#define a_cas_p a_cas_p +static inline void *a_cas_p(volatile void *p, void *t, void *s) +{ + void *old; + a_pre_llsc(); + do old = a_ll_p(p); + while (old==t && !a_sc_p(p, s)); + a_post_llsc(); + return old; +} +#endif + +#endif + +#ifndef a_cas +#error missing definition of a_cas +#endif + +#ifndef a_swap +#define a_swap a_swap +static inline int a_swap(volatile int *p, int v) +{ + int old; + do old = *p; + while (a_cas(p, old, v) != old); + return old; +} +#endif + +#ifndef a_fetch_add +#define a_fetch_add a_fetch_add +static inline int a_fetch_add(volatile int *p, int v) +{ + int old; + do old = *p; + while (a_cas(p, old, (unsigned)old+v) != old); + return old; +} +#endif + +#ifndef a_fetch_and +#define a_fetch_and a_fetch_and +static inline int a_fetch_and(volatile int *p, int v) +{ + int old; + do old = *p; + while (a_cas(p, old, old&v) != old); + return old; +} +#endif +#ifndef a_fetch_or +#define a_fetch_or a_fetch_or +static inline int a_fetch_or(volatile int *p, int v) +{ + int old; + do old = *p; + while (a_cas(p, old, old|v) != old); + return old; +} +#endif + +#ifndef a_and +#define a_and a_and +static inline void a_and(volatile int *p, int v) +{ + a_fetch_and(p, v); +} +#endif + +#ifndef a_or +#define a_or a_or +static inline void a_or(volatile int *p, int v) +{ + a_fetch_or(p, v); +} +#endif + +#ifndef a_inc +#define a_inc a_inc +static inline void a_inc(volatile int *p) +{ + a_fetch_add(p, 1); +} +#endif + +#ifndef a_dec +#define a_dec a_dec +static inline void a_dec(volatile int *p) +{ + a_fetch_add(p, -1); +} +#endif + +#ifndef a_store +#define a_store a_store +static inline void a_store(volatile int *p, int v) +{ +#ifdef a_barrier + a_barrier(); + *p = v; + a_barrier(); +#else + a_swap(p, v); +#endif +} +#endif + +#ifndef a_barrier +#define a_barrier a_barrier +static void a_barrier() +{ + volatile int tmp = 0; + a_cas(&tmp, 0, 0); +} +#endif + +#ifndef a_spin +#define a_spin a_barrier +#endif + +#ifndef a_and_64 +#define a_and_64 a_and_64 +static inline void a_and_64(volatile uint64_t *p, uint64_t v) +{ + union { uint64_t v; uint32_t r[2]; } u = { v }; + if (u.r[0]+1) a_and((int *)p, u.r[0]); + if (u.r[1]+1) a_and((int *)p+1, u.r[1]); +} +#endif + +#ifndef a_or_64 +#define a_or_64 a_or_64 +static inline void a_or_64(volatile uint64_t *p, uint64_t v) +{ + union { uint64_t v; uint32_t r[2]; } u = { v }; + if (u.r[0]) a_or((int *)p, u.r[0]); + if (u.r[1]) a_or((int *)p+1, u.r[1]); +} +#endif + +#ifndef a_cas_p +typedef char a_cas_p_undefined_but_pointer_not_32bit[-sizeof(char) == 0xffffffff ? 1 : -1]; +#define a_cas_p a_cas_p +static inline void *a_cas_p(volatile void *p, void *t, void *s) +{ + return (void *)a_cas((volatile int *)p, (int)t, (int)s); +} +#endif + +#ifndef a_or_l +#define a_or_l a_or_l +static inline void a_or_l(volatile void *p, long v) +{ + if (sizeof(long) == sizeof(int)) a_or(p, v); + else a_or_64(p, v); +} +#endif + +#ifndef a_crash +#define a_crash a_crash +static inline void a_crash() +{ + *(volatile char *)0=0; +} +#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) +{ + static const char debruijn64[64] = { + 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, + 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, + 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 + }; + if (sizeof(long) < 8) { + uint32_t y = x; + if (!y) { + y = x>>32; + return 32 + a_ctz_32(y); + } + 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) +{ +#ifdef a_clz_32 + if (x>>32) + return a_clz_32(x>>32); + return a_clz_32(x) + 32; +#else + uint32_t y; + int r; + if (x>>32) y=x>>32, r=0; else y=x, r=32; + if (y>>16) y>>=16; else r |= 16; + if (y>>8) y>>=8; else r |= 8; + if (y>>4) y>>=4; else r |= 4; + if (y>>2) y>>=2; else r |= 2; + return r | !(y>>1); +#endif +} +#endif + +#ifndef a_clz_32 +#define a_clz_32 a_clz_32 +static inline int a_clz_32(uint32_t x) +{ + x >>= 1; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + return 31-a_ctz_32(x); +} +#endif + +#endif diff --git a/libc-top-half/musl/src/internal/complex_impl.h b/libc-top-half/musl/src/internal/complex_impl.h new file mode 100644 index 0000000..51fb298 --- /dev/null +++ b/libc-top-half/musl/src/internal/complex_impl.h @@ -0,0 +1,22 @@ +#ifndef _COMPLEX_IMPL_H +#define _COMPLEX_IMPL_H + +#include <complex.h> +#include "libm.h" + +#undef __CMPLX +#undef CMPLX +#undef CMPLXF +#undef CMPLXL + +#define __CMPLX(x, y, t) \ + ((union { _Complex t __z; t __xy[2]; }){.__xy = {(x),(y)}}.__z) + +#define CMPLX(x, y) __CMPLX(x, y, double) +#define CMPLXF(x, y) __CMPLX(x, y, float) +#define CMPLXL(x, y) __CMPLX(x, y, long double) + +hidden double complex __ldexp_cexp(double complex,int); +hidden float complex __ldexp_cexpf(float complex,int); + +#endif diff --git a/libc-top-half/musl/src/internal/defsysinfo.c b/libc-top-half/musl/src/internal/defsysinfo.c new file mode 100644 index 0000000..6d4117d --- /dev/null +++ b/libc-top-half/musl/src/internal/defsysinfo.c @@ -0,0 +1,3 @@ +#include "libc.h" + +size_t __sysinfo; diff --git a/libc-top-half/musl/src/internal/dynlink.h b/libc-top-half/musl/src/internal/dynlink.h new file mode 100644 index 0000000..51c0639 --- /dev/null +++ b/libc-top-half/musl/src/internal/dynlink.h @@ -0,0 +1,113 @@ +#ifndef _INTERNAL_RELOC_H +#define _INTERNAL_RELOC_H + +#include <features.h> +#include <elf.h> +#include <stdint.h> +#include <stddef.h> +#include <stdarg.h> + +#if UINTPTR_MAX == 0xffffffff +typedef Elf32_Ehdr Ehdr; +typedef Elf32_Phdr Phdr; +typedef Elf32_Sym Sym; +#define R_TYPE(x) ((x)&255) +#define R_SYM(x) ((x)>>8) +#define R_INFO ELF32_R_INFO +#else +typedef Elf64_Ehdr Ehdr; +typedef Elf64_Phdr Phdr; +typedef Elf64_Sym Sym; +#define R_TYPE(x) ((x)&0x7fffffff) +#define R_SYM(x) ((x)>>32) +#define R_INFO ELF64_R_INFO +#endif + +/* These enum constants provide unmatchable default values for + * any relocation type the arch does not use. */ +enum { + REL_NONE = 0, + REL_SYMBOLIC = -100, + REL_USYMBOLIC, + REL_GOT, + REL_PLT, + REL_RELATIVE, + REL_OFFSET, + REL_OFFSET32, + REL_COPY, + REL_SYM_OR_REL, + REL_DTPMOD, + REL_DTPOFF, + REL_TPOFF, + REL_TPOFF_NEG, + REL_TLSDESC, + REL_FUNCDESC, + REL_FUNCDESC_VAL, +}; + +struct fdpic_loadseg { + uintptr_t addr, p_vaddr, p_memsz; +}; + +struct fdpic_loadmap { + unsigned short version, nsegs; + struct fdpic_loadseg segs[]; +}; + +struct fdpic_dummy_loadmap { + unsigned short version, nsegs; + struct fdpic_loadseg segs[1]; +}; + +#include "reloc.h" + +#ifndef FDPIC_CONSTDISP_FLAG +#define FDPIC_CONSTDISP_FLAG 0 +#endif + +#ifndef DL_FDPIC +#define DL_FDPIC 0 +#endif + +#ifndef DL_NOMMU_SUPPORT +#define DL_NOMMU_SUPPORT 0 +#endif + +#if !DL_FDPIC +#define IS_RELATIVE(x,s) ( \ + (R_TYPE(x) == REL_RELATIVE) || \ + (R_TYPE(x) == REL_SYM_OR_REL && !R_SYM(x)) ) +#else +#define IS_RELATIVE(x,s) ( ( \ + (R_TYPE(x) == REL_FUNCDESC_VAL) || \ + (R_TYPE(x) == REL_SYMBOLIC) ) \ + && (((s)[R_SYM(x)].st_info & 0xf) == STT_SECTION) ) +#endif + +#ifndef NEED_MIPS_GOT_RELOCS +#define NEED_MIPS_GOT_RELOCS 0 +#endif + +#ifndef DT_DEBUG_INDIRECT +#define DT_DEBUG_INDIRECT 0 +#endif + +#define AUX_CNT 32 +#define DYN_CNT 32 + +typedef void (*stage2_func)(unsigned char *, size_t *); + +hidden void *__dlsym(void *restrict, const char *restrict, void *restrict); + +hidden void __dl_seterr(const char *, ...); +hidden int __dl_invalid_handle(void *); +hidden void __dl_vseterr(const char *, va_list); + +hidden ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic(); + +hidden extern int __malloc_replaced; +hidden extern int __aligned_alloc_replaced; +hidden void __malloc_donate(char *, char *); +hidden int __malloc_allzerop(void *); + +#endif diff --git a/libc-top-half/musl/src/internal/fdpic_crt.h b/libc-top-half/musl/src/internal/fdpic_crt.h new file mode 100644 index 0000000..7e9632b --- /dev/null +++ b/libc-top-half/musl/src/internal/fdpic_crt.h @@ -0,0 +1,28 @@ +#include <stdint.h> +#include <features.h> + +hidden void *__fdpic_fixup(void *map, uintptr_t *a, uintptr_t *z) +{ + /* If map is a null pointer, the program was loaded by a + * non-FDPIC-aware ELF loader, and fixups are not needed, + * but the value for the GOT pointer is. */ + if (!map) return (void *)z[-1]; + + struct { + unsigned short version, nsegs; + struct fdpic_loadseg { + uintptr_t addr, p_vaddr, p_memsz; + } segs[]; + } *lm = map; + int nsegs = lm->nsegs, rseg = 0, vseg = 0; + for (;;) { + while (*a-lm->segs[rseg].p_vaddr >= lm->segs[rseg].p_memsz) + if (++rseg == nsegs) rseg = 0; + uintptr_t *r = (uintptr_t *) + (*a + lm->segs[rseg].addr - lm->segs[rseg].p_vaddr); + if (++a == z) return r; + while (*r-lm->segs[vseg].p_vaddr >= lm->segs[vseg].p_memsz) + if (++vseg == nsegs) vseg = 0; + *r += lm->segs[vseg].addr - lm->segs[vseg].p_vaddr; + } +} diff --git a/libc-top-half/musl/src/internal/floatscan.c b/libc-top-half/musl/src/internal/floatscan.c new file mode 100644 index 0000000..ec50fe0 --- /dev/null +++ b/libc-top-half/musl/src/internal/floatscan.c @@ -0,0 +1,556 @@ +#include <stdint.h> +#include <stdio.h> +#include <math.h> +#include <float.h> +#include <limits.h> +#include <errno.h> +#include <ctype.h> +#ifdef __wasilibc_unmodified_upstream // Changes to optimize printf/scanf when long double isn't needed +#else +#include "printscan.h" +#endif + +#include "shgetc.h" +#include "floatscan.h" + +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 + +#define LD_B1B_DIG 2 +#define LD_B1B_MAX 9007199, 254740991 +#define KMAX 128 + +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 + +#define LD_B1B_DIG 3 +#define LD_B1B_MAX 18, 446744073, 709551615 +#define KMAX 2048 + +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 + +#define LD_B1B_DIG 4 +#define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191 +#define KMAX 2048 + +#else +#error Unsupported long double representation +#endif + +#define MASK (KMAX-1) + +static long long scanexp(FILE *f, int pok) +{ + int c; + int x; + long long y; + int neg = 0; + + c = shgetc(f); + if (c=='+' || c=='-') { + neg = (c=='-'); + c = shgetc(f); + if (c-'0'>=10U && pok) shunget(f); + } + if (c-'0'>=10U) { + shunget(f); + return LLONG_MIN; + } + for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f)) + x = 10*x + c-'0'; + for (y=x; c-'0'<10U && y<LLONG_MAX/100; c = shgetc(f)) + y = 10*y + c-'0'; + for (; c-'0'<10U; c = shgetc(f)); + shunget(f); + return neg ? -y : y; +} + + +#if defined(__wasilibc_printscan_no_long_double) +static long_double decfloat(FILE *f, int c, int bits, int emin, int sign, int pok) +#else +static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int pok) +#endif +{ + uint32_t x[KMAX]; + static const uint32_t th[] = { LD_B1B_MAX }; + int i, j, k, a, z; + long long lrp=0, dc=0; + long long e10=0; + int lnz = 0; + int gotdig = 0, gotrad = 0; + int rp; + int e2; + int emax = -emin-bits+3; + int denormal = 0; +#if defined(__wasilibc_printscan_no_long_double) + long_double y; + long_double frac=0; + long_double bias=0; +#else + long double y; + long double frac=0; + long double bias=0; +#endif + static const int p10s[] = { 10, 100, 1000, 10000, + 100000, 1000000, 10000000, 100000000 }; + + j=0; + k=0; + + /* Don't let leading zeros consume buffer space */ + for (; c=='0'; c = shgetc(f)) gotdig=1; + if (c=='.') { + gotrad = 1; + for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--; + } + + x[0] = 0; + for (; c-'0'<10U || c=='.'; c = shgetc(f)) { + if (c == '.') { + if (gotrad) break; + gotrad = 1; + lrp = dc; + } else if (k < KMAX-3) { + dc++; + if (c!='0') lnz = dc; + if (j) x[k] = x[k]*10 + c-'0'; + else x[k] = c-'0'; + if (++j==9) { + k++; + j=0; + } + gotdig=1; + } else { + dc++; + if (c!='0') { + lnz = (KMAX-4)*9; + x[KMAX-4] |= 1; + } + } + } + if (!gotrad) lrp=dc; + + if (gotdig && (c|32)=='e') { + e10 = scanexp(f, pok); + if (e10 == LLONG_MIN) { + if (pok) { + shunget(f); + } else { + shlim(f, 0); + return 0; + } + e10 = 0; + } + lrp += e10; + } else if (c>=0) { + shunget(f); + } + if (!gotdig) { + errno = EINVAL; + shlim(f, 0); + return 0; + } + + /* Handle zero specially to avoid nasty special cases later */ + if (!x[0]) return sign * 0.0; + + /* Optimize small integers (w/no exponent) and over/under-flow */ + if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) +#if defined(__wasilibc_printscan_no_long_double) + return sign * (long_double)x[0]; +#else + return sign * (long double)x[0]; +#endif + if (lrp > -emin/2) { + errno = ERANGE; + return sign * LDBL_MAX * LDBL_MAX; + } + if (lrp < emin-2*LDBL_MANT_DIG) { + errno = ERANGE; + return sign * LDBL_MIN * LDBL_MIN; + } + + /* Align incomplete final B1B digit */ + if (j) { + for (; j<9; j++) x[k]*=10; + k++; + j=0; + } + + a = 0; + z = k; + e2 = 0; + rp = lrp; + + /* Optimize small to mid-size integers (even in exp. notation) */ + if (lnz<9 && lnz<=rp && rp < 18) { +#if defined(__wasilibc_printscan_no_long_double) + if (rp == 9) return sign * (long_double)x[0]; + if (rp < 9) return sign * (long_double)x[0] / p10s[8-rp]; +#else + if (rp == 9) return sign * (long double)x[0]; + if (rp < 9) return sign * (long double)x[0] / p10s[8-rp]; +#endif + int bitlim = bits-3*(int)(rp-9); + if (bitlim>30 || x[0]>>bitlim==0) +#if defined(__wasilibc_printscan_no_long_double) + return sign * (long_double)x[0] * p10s[rp-10]; +#else + return sign * (long double)x[0] * p10s[rp-10]; +#endif + } + + /* Drop trailing zeros */ + for (; !x[z-1]; z--); + + /* Align radix point to B1B digit boundary */ + if (rp % 9) { + int rpm9 = rp>=0 ? rp%9 : rp%9+9; + int p10 = p10s[8-rpm9]; + uint32_t carry = 0; + for (k=a; k!=z; k++) { + uint32_t tmp = x[k] % p10; + x[k] = x[k]/p10 + carry; + carry = 1000000000/p10 * tmp; + if (k==a && !x[k]) { + a = (a+1 & MASK); + rp -= 9; + } + } + if (carry) x[z++] = carry; + rp += 9-rpm9; + } + + /* Upscale until desired number of bits are left of radix point */ + while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) { + uint32_t carry = 0; + e2 -= 29; + for (k=(z-1 & MASK); ; k=(k-1 & MASK)) { + uint64_t tmp = ((uint64_t)x[k] << 29) + carry; + if (tmp > 1000000000) { + carry = tmp / 1000000000; + x[k] = tmp % 1000000000; + } else { + carry = 0; + x[k] = tmp; + } + if (k==(z-1 & MASK) && k!=a && !x[k]) z = k; + if (k==a) break; + } + if (carry) { + rp += 9; + a = (a-1 & MASK); + if (a == z) { + z = (z-1 & MASK); + x[z-1 & MASK] |= x[z]; + } + x[a] = carry; + } + } + + /* Downscale until exactly number of bits are left of radix point */ + for (;;) { + uint32_t carry = 0; + int sh = 1; + for (i=0; i<LD_B1B_DIG; i++) { + k = (a+i & MASK); + if (k == z || x[k] < th[i]) { + i=LD_B1B_DIG; + break; + } + if (x[a+i & MASK] > th[i]) break; + } + if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break; + /* FIXME: find a way to compute optimal sh */ + if (rp > 9+9*LD_B1B_DIG) sh = 9; + e2 += sh; + for (k=a; k!=z; k=(k+1 & MASK)) { + uint32_t tmp = x[k] & (1<<sh)-1; + x[k] = (x[k]>>sh) + carry; + carry = (1000000000>>sh) * tmp; + if (k==a && !x[k]) { + a = (a+1 & MASK); + i--; + rp -= 9; + } + } + if (carry) { + if ((z+1 & MASK) != a) { + x[z] = carry; + z = (z+1 & MASK); + } else x[z-1 & MASK] |= 1; + } + } + + /* Assemble desired bits into floating point variable */ + for (y=i=0; i<LD_B1B_DIG; i++) { + if ((a+i & MASK)==z) x[(z=(z+1 & MASK))-1] = 0; +#if defined(__wasilibc_printscan_no_long_double) + y = 1000000000.0 * y + x[a+i & MASK]; +#else + y = 1000000000.0L * y + x[a+i & MASK]; +#endif + } + + y *= sign; + + /* Limit precision for denormal results */ + if (bits > LDBL_MANT_DIG+e2-emin) { + bits = LDBL_MANT_DIG+e2-emin; + if (bits<0) bits=0; + denormal = 1; + } + + /* Calculate bias term to force rounding, move out lower bits */ + if (bits < LDBL_MANT_DIG) { + bias = copysignl(scalbn(1, 2*LDBL_MANT_DIG-bits-1), y); + frac = fmodl(y, scalbn(1, LDBL_MANT_DIG-bits)); + y -= frac; + y += bias; + } + + /* Process tail of decimal input so it can affect rounding */ + if ((a+i & MASK) != z) { + uint32_t t = x[a+i & MASK]; + if (t < 500000000 && (t || (a+i+1 & MASK) != z)) + frac += 0.25*sign; + else if (t > 500000000) + frac += 0.75*sign; + else if (t == 500000000) { + if ((a+i+1 & MASK) == z) + frac += 0.5*sign; + else + frac += 0.75*sign; + } + if (LDBL_MANT_DIG-bits >= 2 && !fmodl(frac, 1)) + frac++; + } + + y += frac; + y -= bias; + + if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { + if (fabsl(y) >= 2/LDBL_EPSILON) { + if (denormal && bits==LDBL_MANT_DIG+e2-emin) + denormal = 0; + y *= 0.5; + e2++; + } + if (e2+LDBL_MANT_DIG>emax || (denormal && frac)) + errno = ERANGE; + } + + return scalbnl(y, e2); +} + +#if defined(__wasilibc_printscan_no_long_double) +static long_double hexfloat(FILE *f, int bits, int emin, int sign, int pok) +#else +static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) +#endif +{ + uint32_t x = 0; +#if defined(__wasilibc_printscan_no_long_double) + long_double y = 0; + long_double scale = 1; + long_double bias = 0; +#else + long double y = 0; + long double scale = 1; + long double bias = 0; +#endif + int gottail = 0, gotrad = 0, gotdig = 0; + long long rp = 0; + long long dc = 0; + long long e2 = 0; + int d; + int c; + + c = shgetc(f); + + /* Skip leading zeros */ + for (; c=='0'; c = shgetc(f)) gotdig = 1; + + if (c=='.') { + gotrad = 1; + c = shgetc(f); + /* Count zeros after the radix point before significand */ + for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1; + } + + for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) { + if (c=='.') { + if (gotrad) break; + rp = dc; + gotrad = 1; + } else { + gotdig = 1; + if (c > '9') d = (c|32)+10-'a'; + else d = c-'0'; + if (dc<8) { + x = x*16 + d; + } else if (dc < LDBL_MANT_DIG/4+1) { + y += d*(scale/=16); + } else if (d && !gottail) { + y += 0.5*scale; + gottail = 1; + } + dc++; + } + } + if (!gotdig) { + shunget(f); + if (pok) { + shunget(f); + if (gotrad) shunget(f); + } else { + shlim(f, 0); + } + return sign * 0.0; + } + if (!gotrad) rp = dc; + while (dc<8) x *= 16, dc++; + if ((c|32)=='p') { + e2 = scanexp(f, pok); + if (e2 == LLONG_MIN) { + if (pok) { + shunget(f); + } else { + shlim(f, 0); + return 0; + } + e2 = 0; + } + } else { + shunget(f); + } + e2 += 4*rp - 32; + + if (!x) return sign * 0.0; + if (e2 > -emin) { + errno = ERANGE; + return sign * LDBL_MAX * LDBL_MAX; + } + if (e2 < emin-2*LDBL_MANT_DIG) { + errno = ERANGE; + return sign * LDBL_MIN * LDBL_MIN; + } + + while (x < 0x80000000) { + if (y>=0.5) { + x += x + 1; + y += y - 1; + } else { + x += x; + y += y; + } + e2--; + } + + if (bits > 32+e2-emin) { + bits = 32+e2-emin; + if (bits<0) bits=0; + } + + if (bits < LDBL_MANT_DIG) + bias = copysignl(scalbn(1, 32+LDBL_MANT_DIG-bits-1), sign); + + if (bits<32 && y && !(x&1)) x++, y=0; + +#if defined(__wasilibc_printscan_no_long_double) + y = bias + sign*(long_double)x + sign*y; +#else + y = bias + sign*(long double)x + sign*y; +#endif + y -= bias; + + if (!y) errno = ERANGE; + + return scalbnl(y, e2); +} + +#if defined(__wasilibc_printscan_no_long_double) +long_double __floatscan(FILE *f, int prec, int pok) +#else +long double __floatscan(FILE *f, int prec, int pok) +#endif +{ + int sign = 1; + size_t i; + int bits; + int emin; + int c; + + switch (prec) { + case 0: + bits = FLT_MANT_DIG; + emin = FLT_MIN_EXP-bits; + break; + case 1: + bits = DBL_MANT_DIG; + emin = DBL_MIN_EXP-bits; + break; + case 2: + bits = LDBL_MANT_DIG; + emin = LDBL_MIN_EXP-bits; + break; + default: + return 0; + } + + while (isspace((c=shgetc(f)))); + + if (c=='+' || c=='-') { + sign -= 2*(c=='-'); + c = shgetc(f); + } + + for (i=0; i<8 && (c|32)=="infinity"[i]; i++) + if (i<7) c = shgetc(f); + if (i==3 || i==8 || (i>3 && pok)) { + if (i!=8) { + shunget(f); + if (pok) for (; i>3; i--) shunget(f); + } + return sign * INFINITY; + } + if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) + if (i<2) c = shgetc(f); + if (i==3) { + if (shgetc(f) != '(') { + shunget(f); + return NAN; + } + for (i=1; ; i++) { + c = shgetc(f); + if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_') + continue; + if (c==')') return NAN; + shunget(f); + if (!pok) { + errno = EINVAL; + shlim(f, 0); + return 0; + } + while (i--) shunget(f); + return NAN; + } + return NAN; + } + + if (i) { + shunget(f); + errno = EINVAL; + shlim(f, 0); + return 0; + } + + if (c=='0') { + c = shgetc(f); + if ((c|32) == 'x') + return hexfloat(f, bits, emin, sign, pok); + shunget(f); + c = '0'; + } + + return decfloat(f, c, bits, emin, sign, pok); +} diff --git a/libc-top-half/musl/src/internal/floatscan.h b/libc-top-half/musl/src/internal/floatscan.h new file mode 100644 index 0000000..8febd46 --- /dev/null +++ b/libc-top-half/musl/src/internal/floatscan.h @@ -0,0 +1,12 @@ +#ifndef FLOATSCAN_H +#define FLOATSCAN_H + +#include <stdio.h> + +#if defined(__wasilibc_printscan_no_long_double) +hidden long_double __floatscan(FILE *, int, int); +#else +hidden long double __floatscan(FILE *, int, int); +#endif + +#endif diff --git a/libc-top-half/musl/src/internal/fork_impl.h b/libc-top-half/musl/src/internal/fork_impl.h new file mode 100644 index 0000000..f6b3aa0 --- /dev/null +++ b/libc-top-half/musl/src/internal/fork_impl.h @@ -0,0 +1,21 @@ +#include <features.h> + +#ifdef __wasilibc_unmodified_upstream +extern hidden volatile int *const __at_quick_exit_lockptr; +extern hidden volatile int *const __atexit_lockptr; +extern hidden volatile int *const __dlerror_lockptr; +extern hidden volatile int *const __gettext_lockptr; +extern hidden volatile int *const __locale_lockptr; +extern hidden volatile int *const __random_lockptr; +extern hidden volatile int *const __sem_open_lockptr; +extern hidden volatile int *const __stdio_ofl_lockptr; +extern hidden volatile int *const __syslog_lockptr; +extern hidden volatile int *const __timezone_lockptr; + +extern hidden volatile int *const __bump_lockptr; + +extern hidden volatile int *const __vmlock_lockptr; + +hidden void __malloc_atfork(int); +hidden void __ldso_atfork(int); +#endif diff --git a/libc-top-half/musl/src/internal/futex.h b/libc-top-half/musl/src/internal/futex.h new file mode 100644 index 0000000..dafbc24 --- /dev/null +++ b/libc-top-half/musl/src/internal/futex.h @@ -0,0 +1,19 @@ +#ifndef _INTERNAL_FUTEX_H +#define _INTERNAL_FUTEX_H + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_FD 2 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 + +#define FUTEX_PRIVATE 128 + +#define FUTEX_CLOCK_REALTIME 256 + +#endif diff --git a/libc-top-half/musl/src/internal/i386/defsysinfo.s b/libc-top-half/musl/src/internal/i386/defsysinfo.s new file mode 100644 index 0000000..f1b5b0f --- /dev/null +++ b/libc-top-half/musl/src/internal/i386/defsysinfo.s @@ -0,0 +1,9 @@ +1: int $128 + ret + +.data +.align 4 +.hidden __sysinfo +.global __sysinfo +__sysinfo: + .long 1b diff --git a/libc-top-half/musl/src/internal/intscan.c b/libc-top-half/musl/src/internal/intscan.c new file mode 100644 index 0000000..a4a5ae8 --- /dev/null +++ b/libc-top-half/musl/src/internal/intscan.c @@ -0,0 +1,100 @@ +#include <limits.h> +#include <errno.h> +#include <ctype.h> +#include "shgetc.h" + +/* Lookup table for digit values. -1==255>=36 -> invalid */ +static const unsigned char table[] = { -1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, +-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, +25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, +-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, +25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +}; + +unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim) +{ + const unsigned char *val = table+1; + int c, neg=0; + unsigned x; + unsigned long long y; + if (base > 36 || base == 1) { + errno = EINVAL; + return 0; + } + while (isspace((c=shgetc(f)))); + if (c=='+' || c=='-') { + neg = -(c=='-'); + c = shgetc(f); + } + if ((base == 0 || base == 16) && c=='0') { + c = shgetc(f); + if ((c|32)=='x') { + c = shgetc(f); + if (val[c]>=16) { + shunget(f); + if (pok) shunget(f); + else shlim(f, 0); + return 0; + } + base = 16; + } else if (base == 0) { + base = 8; + } + } else { + if (base == 0) base = 10; + if (val[c] >= base) { + shunget(f); + shlim(f, 0); + errno = EINVAL; + return 0; + } + } + if (base == 10) { + for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) + x = x*10 + (c-'0'); + for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f)) + y = y*10 + (c-'0'); + if (c-'0'>=10U) goto done; + } else if (!(base & base-1)) { + int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7]; + for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f)) + x = x<<bs | val[c]; + for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f)) + y = y<<bs | val[c]; + } else { + for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f)) + x = x*base + val[c]; + for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f)) + y = y*base + val[c]; + } + if (val[c]<base) { + for (; val[c]<base; c=shgetc(f)); + errno = ERANGE; + y = lim; + if (lim&1) neg = 0; + } +done: + shunget(f); + if (y>=lim) { + if (!(lim&1) && !neg) { + errno = ERANGE; + return lim-1; + } else if (y>lim) { + errno = ERANGE; + return lim; + } + } + return (y^neg)-neg; +} diff --git a/libc-top-half/musl/src/internal/intscan.h b/libc-top-half/musl/src/internal/intscan.h new file mode 100644 index 0000000..ccf9f11 --- /dev/null +++ b/libc-top-half/musl/src/internal/intscan.h @@ -0,0 +1,8 @@ +#ifndef INTSCAN_H +#define INTSCAN_H + +#include <stdio.h> + +hidden unsigned long long __intscan(FILE *, unsigned, int, unsigned long long); + +#endif diff --git a/libc-top-half/musl/src/internal/ksigaction.h b/libc-top-half/musl/src/internal/ksigaction.h new file mode 100644 index 0000000..8ebd593 --- /dev/null +++ b/libc-top-half/musl/src/internal/ksigaction.h @@ -0,0 +1,13 @@ +#include <features.h> + +/* This is the structure used for the rt_sigaction syscall on most archs, + * but it can be overridden by a file with the same name in the top-level + * arch dir for a given arch, if necessary. */ +struct k_sigaction { + void (*handler)(int); + unsigned long flags; + void (*restorer)(void); + unsigned mask[2]; +}; + +hidden void __restore(), __restore_rt(); diff --git a/libc-top-half/musl/src/internal/libc.c b/libc-top-half/musl/src/internal/libc.c new file mode 100644 index 0000000..cb05181 --- /dev/null +++ b/libc-top-half/musl/src/internal/libc.c @@ -0,0 +1,9 @@ +#include "libc.h" + +struct __libc __libc; + +size_t __hwcap; +char *__progname=0, *__progname_full=0; + +weak_alias(__progname, program_invocation_short_name); +weak_alias(__progname_full, program_invocation_name); diff --git a/libc-top-half/musl/src/internal/libc.h b/libc-top-half/musl/src/internal/libc.h new file mode 100644 index 0000000..355c3a4 --- /dev/null +++ b/libc-top-half/musl/src/internal/libc.h @@ -0,0 +1,76 @@ +#ifndef LIBC_H +#define LIBC_H + +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> + +struct __locale_map; + +struct __locale_struct { + const struct __locale_map *cat[6]; +}; + +struct tls_module { + struct tls_module *next; + void *image; + size_t len, size, align, offset; +}; + +struct __libc { +#ifdef __wasilibc_unmodified_upstream + char can_do_threads; +#endif +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) + char threaded; +#endif +#ifdef __wasilibc_unmodified_upstream // WASI doesn't currently use any code that needs "secure" mode + char secure; +#endif +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) + volatile signed char need_locks; + int threads_minus_1; +#endif +#ifdef __wasilibc_unmodified_upstream // WASI has no auxv + size_t *auxv; +#endif +#ifdef __wasilibc_unmodified_upstream // WASI use different TLS implement + struct tls_module *tls_head; + size_t tls_size, tls_align, tls_cnt; +#endif +#ifdef __wasilibc_unmodified_upstream // WASI doesn't get the page size from auxv + size_t page_size; +#endif + struct __locale_struct global_locale; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +#else + struct __locale_struct *current_locale; +#endif +}; + +#ifndef PAGE_SIZE +#define PAGE_SIZE libc.page_size +#endif + +extern hidden struct __libc __libc; +#define libc __libc + +hidden void __init_libc(char **, char *); +hidden void __init_tls(size_t *); +hidden void __init_ssp(void *); +hidden void __libc_start_init(void); +hidden void __funcs_on_exit(void); +hidden void __funcs_on_quick_exit(void); +hidden void __libc_exit_fini(void); +hidden void __fork_handler(int); + +extern hidden size_t __hwcap; +extern hidden size_t __sysinfo; +extern char *__progname, *__progname_full; + +extern hidden const char __libc_version[]; + +hidden void __synccall(void (*)(void *), void *); +hidden int __setxid(int, int, int, int); + +#endif diff --git a/libc-top-half/musl/src/internal/libm.h b/libc-top-half/musl/src/internal/libm.h new file mode 100644 index 0000000..2b06ac4 --- /dev/null +++ b/libc-top-half/musl/src/internal/libm.h @@ -0,0 +1,292 @@ +#ifndef _LIBM_H +#define _LIBM_H + +#include <stdint.h> +#include <float.h> +#include <math.h> +#include <endian.h> +#include "fp_arch.h" + +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t m; + 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; + struct { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct { + uint64_t lo; + uint64_t hi; + } i2; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t top; + uint32_t mid; + uint64_t lo; + } i; + struct { + uint64_t hi; + uint64_t lo; + } i2; +}; +#else +#error Unsupported long double representation +#endif + +/* Support non-nearest rounding mode. */ +#ifdef __wasilibc_unmodified_upstream // Wasm doesn't have alternate rounding modes +#define WANT_ROUNDING 1 +#else +#define WANT_ROUNDING 0 +#endif +/* Support signaling NaNs. */ +#define WANT_SNAN 0 + +#if WANT_SNAN +#error SNaN is unsupported +#else +#define issignalingf_inline(x) 0 +#define issignaling_inline(x) 0 +#endif + +#ifndef TOINT_INTRINSICS +#define TOINT_INTRINSICS 0 +#endif + +#if TOINT_INTRINSICS +/* Round x to nearest int in all rounding modes, ties have to be rounded + consistently with converttoint so the results match. If the result + would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ +static double_t roundtoint(double_t); + +/* Convert x to nearest int in all rounding modes, ties have to be rounded + consistently with roundtoint. If the result is not representible in an + int32_t then the semantics is unspecified. */ +static int32_t converttoint(double_t); +#endif + +/* Helps static branch prediction so hot path can be better optimized. */ +#ifdef __GNUC__ +#define predict_true(x) __builtin_expect(!!(x), 1) +#define predict_false(x) __builtin_expect(x, 0) +#else +#define predict_true(x) (x) +#define predict_false(x) (x) +#endif + +/* Evaluate an expression as the specified type. With standard excess + precision handling a type cast or assignment is enough (with + -ffloat-store an assignment is required, in old compilers argument + passing and return statement may not drop excess precision). */ + +static inline float eval_as_float(float x) +{ + float y = x; + return y; +} + +static inline double eval_as_double(double x) +{ + double y = x; + return y; +} + +/* fp_barrier returns its input, but limits code transformations + as if it had a side-effect (e.g. observable io) and returned + an arbitrary value. */ + +#ifndef fp_barrierf +#define fp_barrierf fp_barrierf +static inline float fp_barrierf(float x) +{ + volatile float y = x; + return y; +} +#endif + +#ifndef fp_barrier +#define fp_barrier fp_barrier +static inline double fp_barrier(double x) +{ + volatile double y = x; + return y; +} +#endif + +#ifndef fp_barrierl +#define fp_barrierl fp_barrierl +static inline long double fp_barrierl(long double x) +{ + volatile long double y = x; + return y; +} +#endif + +/* fp_force_eval ensures that the input value is computed when that's + otherwise unused. To prevent the constant folding of the input + expression, an additional fp_barrier may be needed or a compilation + mode that does so (e.g. -frounding-math in gcc). Then it can be + used to evaluate an expression for its fenv side-effects only. */ + +#ifndef fp_force_evalf +#define fp_force_evalf fp_force_evalf +static inline void fp_force_evalf(float x) +{ + volatile float y; + y = x; +} +#endif + +#ifndef fp_force_eval +#define fp_force_eval fp_force_eval +static inline void fp_force_eval(double x) +{ + volatile double y; + y = x; +} +#endif + +#ifndef fp_force_evall +#define fp_force_evall fp_force_evall +static inline void fp_force_evall(long double x) +{ + volatile long double y; + y = x; +} +#endif + +#ifdef __wasilibc_unmodified_upstream // WASI has no floating-point status flags +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else if (sizeof(x) == sizeof(double)) { \ + fp_force_eval(x); \ + } else { \ + fp_force_evall(x); \ + } \ +} while(0) +#else +/* WebAssembly doesn't have floating-point status flags, so there's no reason + * to force evaluations. */ +#define FORCE_EVAL(x) ((void)(x)) +#endif + +#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i +#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f +#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i +#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f + +#define EXTRACT_WORDS(hi,lo,d) \ +do { \ + uint64_t __u = asuint64(d); \ + (hi) = __u >> 32; \ + (lo) = (uint32_t)__u; \ +} while (0) + +#define GET_HIGH_WORD(hi,d) \ +do { \ + (hi) = asuint64(d) >> 32; \ +} while (0) + +#define GET_LOW_WORD(lo,d) \ +do { \ + (lo) = (uint32_t)asuint64(d); \ +} while (0) + +#define INSERT_WORDS(d,hi,lo) \ +do { \ + (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ +} while (0) + +#define SET_HIGH_WORD(d,hi) \ + INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) + +#define SET_LOW_WORD(d,lo) \ + INSERT_WORDS(d, asuint64(d)>>32, lo) + +#define GET_FLOAT_WORD(w,d) \ +do { \ + (w) = asuint(d); \ +} while (0) + +#define SET_FLOAT_WORD(d,w) \ +do { \ + (d) = asfloat(w); \ +} while (0) + +hidden int __rem_pio2_large(double*,double*,int,int,int); + +hidden int __rem_pio2(double,double*); +hidden double __sin(double,double,int); +hidden double __cos(double,double); +hidden double __tan(double,double,int); +#ifdef __wasilibc_unmodified_upstream // Wasm doesn't have alternate rounding modes +hidden double __expo2(double,double); +#else +hidden double __expo2(double); +#endif + +hidden int __rem_pio2f(float,double*); +hidden float __sindf(double); +hidden float __cosdf(double); +hidden float __tandf(double,int); +#ifdef __wasilibc_unmodified_upstream // Wasm doesn't have alternate rounding modes +hidden float __expo2f(float,float); +#else +hidden float __expo2f(float); +#endif + +hidden int __rem_pio2l(long double, long double *); +hidden long double __sinl(long double, long double, int); +hidden long double __cosl(long double, long double); +hidden long double __tanl(long double, long double, int); + +hidden long double __polevll(long double, const long double *, int); +hidden long double __p1evll(long double, const long double *, int); + +extern int __signgam; +hidden double __lgamma_r(double, int *); +hidden float __lgammaf_r(float, int *); + +/* error handling functions */ +hidden float __math_xflowf(uint32_t, float); +hidden float __math_uflowf(uint32_t); +hidden float __math_oflowf(uint32_t); +hidden float __math_divzerof(uint32_t); +hidden float __math_invalidf(float); +hidden double __math_xflow(uint32_t, double); +hidden double __math_uflow(uint32_t); +hidden double __math_oflow(uint32_t); +hidden double __math_divzero(uint32_t); +hidden double __math_invalid(double); +#if LDBL_MANT_DIG != DBL_MANT_DIG +hidden long double __math_invalidl(long double); +#endif + +#endif diff --git a/libc-top-half/musl/src/internal/locale_impl.h b/libc-top-half/musl/src/internal/locale_impl.h new file mode 100644 index 0000000..7f79b7f --- /dev/null +++ b/libc-top-half/musl/src/internal/locale_impl.h @@ -0,0 +1,65 @@ +#ifndef _LOCALE_IMPL_H +#define _LOCALE_IMPL_H + +#include <locale.h> +#include <stdlib.h> +#include "libc.h" +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +#include "pthread_impl.h" +#endif + +#define LOCALE_NAME_MAX 23 + +struct __locale_map { + const void *map; + size_t map_size; + char name[LOCALE_NAME_MAX+1]; + const struct __locale_map *next; +}; + +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +extern hidden volatile int __locale_lock[1]; +#endif + +extern hidden const struct __locale_map __c_dot_utf8; +extern hidden const struct __locale_struct __c_locale; +extern hidden const struct __locale_struct __c_dot_utf8_locale; + +hidden const struct __locale_map *__get_locale(int, const char *); +hidden const char *__mo_lookup(const void *, size_t, const char *); +hidden const char *__lctrans(const char *, const struct __locale_map *); +hidden const char *__lctrans_cur(const char *); +hidden const char *__lctrans_impl(const char *, const struct __locale_map *); +hidden int __loc_is_allocated(locale_t); +hidden char *__gettextdomain(void); + +#define LOC_MAP_FAILED ((const struct __locale_map *)-1) + +#define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)]) +#define LCTRANS_CUR(msg) __lctrans_cur(msg) + +#define C_LOCALE ((locale_t)&__c_locale) +#define UTF8_LOCALE ((locale_t)&__c_dot_utf8_locale) + +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +#define CURRENT_LOCALE (__pthread_self()->locale) + +#define CURRENT_UTF8 (!!__pthread_self()->locale->cat[LC_CTYPE]) +#else +// If we haven't set up the current_local field yet, do so. Then return an +// lvalue for the current_locale field. +#define CURRENT_LOCALE \ + (*({ \ + if (!libc.current_locale) { \ + libc.current_locale = &libc.global_locale; \ + } \ + &libc.current_locale; \ + })) + +#define CURRENT_UTF8 (!!libc.global_locale.cat[LC_CTYPE]) +#endif + +#undef MB_CUR_MAX +#define MB_CUR_MAX (CURRENT_UTF8 ? 4 : 1) + +#endif diff --git a/libc-top-half/musl/src/internal/lock.h b/libc-top-half/musl/src/internal/lock.h new file mode 100644 index 0000000..29787fb --- /dev/null +++ b/libc-top-half/musl/src/internal/lock.h @@ -0,0 +1,15 @@ +#ifndef LOCK_H +#define LOCK_H + +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +hidden void __lock(volatile int *); +hidden void __unlock(volatile int *); +#define LOCK(x) __lock(x) +#define UNLOCK(x) __unlock(x) +#else +// No locking needed. +#define LOCK(x) ((void)0) +#define UNLOCK(x) ((void)0) +#endif + +#endif diff --git a/libc-top-half/musl/src/internal/procfdname.c b/libc-top-half/musl/src/internal/procfdname.c new file mode 100644 index 0000000..fd7306a --- /dev/null +++ b/libc-top-half/musl/src/internal/procfdname.c @@ -0,0 +1,15 @@ +#include "syscall.h" + +void __procfdname(char *buf, unsigned fd) +{ + unsigned i, j; + for (i=0; (buf[i] = "/proc/self/fd/"[i]); i++); + if (!fd) { + buf[i] = '0'; + buf[i+1] = 0; + return; + } + for (j=fd; j; j/=10, i++); + buf[i] = 0; + for (; fd; fd/=10) buf[--i] = '0' + fd%10; +} diff --git a/libc-top-half/musl/src/internal/pthread_impl.h b/libc-top-half/musl/src/internal/pthread_impl.h new file mode 100644 index 0000000..a6d188b --- /dev/null +++ b/libc-top-half/musl/src/internal/pthread_impl.h @@ -0,0 +1,226 @@ +#ifndef _PTHREAD_IMPL_H +#define _PTHREAD_IMPL_H + +#include <pthread.h> +#ifdef __wasilibc_unmodified_upstream +#include <signal.h> +#endif +#include <errno.h> +#include <limits.h> +#ifdef __wasilibc_unmodified_upstream +#include <sys/mman.h> +#endif +#include "libc.h" +#ifdef __wasilibc_unmodified_upstream +#include "syscall.h" +#endif +#include "atomic.h" +#include "futex.h" + +#include "pthread_arch.h" + +#define pthread __pthread + +struct pthread { + /* Part 1 -- these fields may be external or + * internal (accessed via asm) ABI. Do not change. */ + struct pthread *self; +#ifdef __wasilibc_unmodified_upstream +#ifndef TLS_ABOVE_TP + uintptr_t *dtv; +#endif +#endif + struct pthread *prev, *next; /* non-ABI */ + uintptr_t sysinfo; +#ifndef TLS_ABOVE_TP +#ifdef CANARY_PAD + uintptr_t canary_pad; +#endif + uintptr_t canary; +#endif + + /* Part 2 -- implementation details, non-ABI. */ + int tid; + int errno_val; + volatile int detach_state; + volatile int cancel; + volatile unsigned char canceldisable, cancelasync; + unsigned char tsd_used: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 *result; + struct __ptcb *cancelbuf; + void **tsd; + struct { + volatile void *volatile head; + long off; + volatile void *volatile pending; + } robust_list; + int h_errno_val; + volatile int timer_id; + locale_t locale; + volatile int killlock[1]; + char *dlerror_buf; + void *stdio_locks; + + /* Part 3 -- the positions of these fields relative to + * the end of the structure is external and internal ABI. */ +#ifdef TLS_ABOVE_TP + uintptr_t canary; + uintptr_t *dtv; +#endif +}; + +enum { + DT_EXITED = 0, + DT_EXITING, + DT_JOINABLE, + DT_DETACHED, +}; + +#define __SU (sizeof(size_t)/sizeof(int)) + +#define _a_stacksize __u.__s[0] +#define _a_guardsize __u.__s[1] +#define _a_stackaddr __u.__s[2] +#define _a_detach __u.__i[3*__SU+0] +#define _a_sched __u.__i[3*__SU+1] +#define _a_policy __u.__i[3*__SU+2] +#define _a_prio __u.__i[3*__SU+3] +#define _m_type __u.__i[0] +#define _m_lock __u.__vi[1] +#define _m_waiters __u.__vi[2] +#define _m_prev __u.__p[3] +#define _m_next __u.__p[4] +#define _m_count __u.__i[5] +#define _c_shared __u.__p[0] +#define _c_seq __u.__vi[2] +#define _c_waiters __u.__vi[3] +#define _c_clock __u.__i[4] +#define _c_lock __u.__vi[8] +#define _c_head __u.__p[1] +#define _c_tail __u.__p[5] +#define _rw_lock __u.__vi[0] +#define _rw_waiters __u.__vi[1] +#define _rw_shared __u.__i[2] +#define _b_lock __u.__vi[0] +#define _b_waiters __u.__vi[1] +#define _b_limit __u.__i[2] +#define _b_count __u.__vi[3] +#define _b_waiters2 __u.__vi[4] +#define _b_inst __u.__p[3] + +#ifndef TP_OFFSET +#define TP_OFFSET 0 +#endif + +#ifndef DTP_OFFSET +#define DTP_OFFSET 0 +#endif + +#ifdef TLS_ABOVE_TP +#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + TP_OFFSET) +#define __pthread_self() ((pthread_t)(__get_tp() - sizeof(struct __pthread) - TP_OFFSET)) +#else +#define TP_ADJ(p) (p) +#define __pthread_self() ((pthread_t)__get_tp()) +#endif + +#ifndef tls_mod_off_t +#define tls_mod_off_t size_t +#endif + +#define SIGTIMER 32 +#define SIGCANCEL 33 +#define SIGSYNCCALL 34 + +#define SIGALL_SET ((sigset_t *)(const unsigned long long [2]){ -1,-1 }) +#define SIGPT_SET \ + ((sigset_t *)(const unsigned long [_NSIG/8/sizeof(long)]){ \ + [sizeof(long)==4] = 3UL<<(32*(sizeof(long)>4)) }) +#define SIGTIMER_SET \ + ((sigset_t *)(const unsigned long [_NSIG/8/sizeof(long)]){ \ + 0x80000000 }) + +void *__tls_get_addr(tls_mod_off_t *); +hidden int __init_tp(void *); +hidden void *__copy_tls(unsigned char *); +hidden void __reset_tls(); + +hidden void __membarrier_init(void); +hidden void __dl_thread_cleanup(void); +hidden void __testcancel(); +hidden void __do_cleanup_push(struct __ptcb *); +hidden void __do_cleanup_pop(struct __ptcb *); +hidden void __pthread_tsd_run_dtors(); + +hidden void __pthread_key_delete_synccall(void (*)(void *), void *); +hidden int __pthread_key_delete_impl(pthread_key_t); + +extern hidden volatile size_t __pthread_tsd_size; +extern hidden void *__pthread_tsd_main[]; +extern hidden volatile int __eintr_valid_flag; + +hidden int __clone(int (*)(void *), void *, int, void *, ...); +hidden int __set_thread_area(void *); +#ifdef __wasilibc_unmodified_upstream /* WASI has no sigaction */ +hidden int __libc_sigaction(int, const struct sigaction *, struct sigaction *); +#endif +hidden void __unmapself(void *, size_t); + +#ifndef __wasilibc_unmodified_upstream +hidden int __wasilibc_futex_wait(volatile void *, int, int, int64_t); +#endif +hidden int __timedwait(volatile int *, int, clockid_t, const struct timespec *, int); +hidden int __timedwait_cp(volatile int *, int, clockid_t, const struct timespec *, int); +hidden void __wait(volatile int *, volatile int *, int, int); +static inline void __wake(volatile void *addr, int cnt, int priv) +{ + if (priv) priv = FUTEX_PRIVATE; + if (cnt<0) cnt = INT_MAX; +#ifdef __wasilibc_unmodified_upstream + __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS || + __syscall(SYS_futex, addr, FUTEX_WAKE, cnt); +#else + __builtin_wasm_memory_atomic_notify((int*)addr, cnt); +#endif +} +static inline void __futexwait(volatile void *addr, int val, int priv) +{ +#ifdef __wasilibc_unmodified_upstream + if (priv) priv = FUTEX_PRIVATE; + __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS || + __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); +#else + __wait(addr, NULL, val, priv); +#endif +} + +hidden void __acquire_ptc(void); +hidden void __release_ptc(void); +hidden void __inhibit_ptc(void); + +hidden void __tl_lock(void); +hidden void __tl_unlock(void); +hidden void __tl_sync(pthread_t); + +extern hidden volatile int __thread_list_lock; + +extern hidden volatile int __abort_lock[1]; + +extern hidden unsigned __default_stacksize; +extern hidden unsigned __default_guardsize; + +#define DEFAULT_STACK_SIZE 131072 +#define DEFAULT_GUARD_SIZE 8192 + +#define DEFAULT_STACK_MAX (8<<20) +#define DEFAULT_GUARD_MAX (1<<20) + +#define __ATTRP_C11_THREAD ((void*)(uintptr_t)-1) + +#endif diff --git a/libc-top-half/musl/src/internal/sh/__shcall.c b/libc-top-half/musl/src/internal/sh/__shcall.c new file mode 100644 index 0000000..4e073e8 --- /dev/null +++ b/libc-top-half/musl/src/internal/sh/__shcall.c @@ -0,0 +1,6 @@ +#include <features.h> + +hidden int __shcall(void *arg, int (*func)(void *)) +{ + return func(arg); +} diff --git a/libc-top-half/musl/src/internal/shgetc.c b/libc-top-half/musl/src/internal/shgetc.c new file mode 100644 index 0000000..7455d2f --- /dev/null +++ b/libc-top-half/musl/src/internal/shgetc.c @@ -0,0 +1,37 @@ +#include "shgetc.h" + +/* The shcnt field stores the number of bytes read so far, offset by + * the value of buf-rpos at the last function call (__shlim or __shgetc), + * so that between calls the inline shcnt macro can add rpos-buf to get + * the actual count. */ + +void __shlim(FILE *f, off_t lim) +{ + f->shlim = lim; + f->shcnt = f->buf - f->rpos; + /* If lim is nonzero, rend must be a valid pointer. */ + if (lim && f->rend - f->rpos > lim) + f->shend = f->rpos + lim; + else + f->shend = f->rend; +} + +int __shgetc(FILE *f) +{ + int c; + off_t cnt = shcnt(f); + if (f->shlim && cnt >= f->shlim || (c=__uflow(f)) < 0) { + f->shcnt = f->buf - f->rpos + cnt; + f->shend = f->rpos; + f->shlim = -1; + return EOF; + } + cnt++; + if (f->shlim && f->rend - f->rpos > f->shlim - cnt) + f->shend = f->rpos + (f->shlim - cnt); + else + f->shend = f->rend; + f->shcnt = f->buf - f->rpos + cnt; + if (f->rpos <= f->buf) f->rpos[-1] = c; + return c; +} diff --git a/libc-top-half/musl/src/internal/shgetc.h b/libc-top-half/musl/src/internal/shgetc.h new file mode 100644 index 0000000..9435381 --- /dev/null +++ b/libc-top-half/musl/src/internal/shgetc.h @@ -0,0 +1,32 @@ +#include "stdio_impl.h" + +/* Scan helper "stdio" functions for use by scanf-family and strto*-family + * functions. These accept either a valid stdio FILE, or a minimal pseudo + * FILE whose buffer pointers point into a null-terminated string. In the + * latter case, the sh_fromstring macro should be used to setup the FILE; + * the rest of the structure can be left uninitialized. + * + * To begin using these functions, shlim must first be called on the FILE + * to set a field width limit, or 0 for no limit. For string pseudo-FILEs, + * a nonzero limit is not valid and produces undefined behavior. After that, + * shgetc, shunget, and shcnt are valid as long as no other stdio functions + * are called on the stream. + * + * When used with a real FILE object, shunget has only one byte of pushback + * available. Further shunget (up to a limit of the stdio UNGET buffer size) + * will adjust the position but will not restore the data to be read again. + * This functionality is needed for the wcsto*-family functions, where it's + * okay because the FILE will be discarded immediately anyway. When used + * with string pseudo-FILEs, shunget has unlimited pushback, back to the + * beginning of the string. */ + +hidden void __shlim(FILE *, off_t); +hidden int __shgetc(FILE *); + +#define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf)) +#define shlim(f, lim) __shlim((f), (lim)) +#define shgetc(f) (((f)->rpos != (f)->shend) ? *(f)->rpos++ : __shgetc(f)) +#define shunget(f) ((f)->shlim>=0 ? (void)(f)->rpos-- : (void)0) + +#define sh_fromstring(f, s) \ + ((f)->buf = (f)->rpos = (void *)(s), (f)->rend = (void*)-1) diff --git a/libc-top-half/musl/src/internal/stdio_impl.h b/libc-top-half/musl/src/internal/stdio_impl.h new file mode 100644 index 0000000..7f19dd9 --- /dev/null +++ b/libc-top-half/musl/src/internal/stdio_impl.h @@ -0,0 +1,137 @@ +#ifndef _STDIO_IMPL_H +#define _STDIO_IMPL_H + +#include <stdio.h> +#if defined(__wasilibc_unmodified_upstream) +#include "syscall.h" +#endif + +#define UNGET 8 + +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +#define FFINALLOCK(f) ((f)->lock>=0 ? __lockfile((f)) : 0) +#define FLOCK(f) int __need_unlock = ((f)->lock>=0 ? __lockfile((f)) : 0) +#define FUNLOCK(f) do { if (__need_unlock) __unlockfile((f)); } while (0) +#else +// No locking needed. +#define FFINALLOCK(f) ((void)(f)) +#define FLOCK(f) ((void)(f)) +#define FUNLOCK(f) ((void)(f)) +#endif + +#define F_PERM 1 +#define F_NORD 4 +#define F_NOWR 8 +#define F_EOF 16 +#define F_ERR 32 +#define F_SVB 64 +#define F_APP 128 + +struct _IO_FILE { + unsigned flags; + unsigned char *rpos, *rend; + int (*close)(FILE *); + unsigned char *wend, *wpos; +#ifdef __wasilibc_unmodified_upstream // WASI doesn't need backwards-compatibility fields. + unsigned char *mustbezero_1; +#endif + unsigned char *wbase; + size_t (*read)(FILE *, unsigned char *, size_t); + size_t (*write)(FILE *, const unsigned char *, size_t); + off_t (*seek)(FILE *, off_t, int); + unsigned char *buf; + size_t buf_size; + FILE *prev, *next; + int fd; +#ifdef __wasilibc_unmodified_upstream // WASI has no popen + int pipe_pid; +#endif +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) + long lockcount; +#endif + int mode; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) + volatile int lock; +#endif + int lbf; + void *cookie; + off_t off; + char *getln_buf; +#ifdef __wasilibc_unmodified_upstream // WASI doesn't need backwards-compatibility fields. + void *mustbezero_2; +#endif + unsigned char *shend; + off_t shlim, shcnt; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) + FILE *prev_locked, *next_locked; +#endif + struct __locale_struct *locale; +}; + +extern hidden FILE *volatile __stdin_used; +extern hidden FILE *volatile __stdout_used; +extern hidden FILE *volatile __stderr_used; + +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +hidden int __lockfile(FILE *); +hidden void __unlockfile(FILE *); +#endif + +hidden size_t __stdio_read(FILE *, unsigned char *, size_t); +hidden size_t __stdio_write(FILE *, const unsigned char *, size_t); +hidden size_t __stdout_write(FILE *, const unsigned char *, size_t); +hidden off_t __stdio_seek(FILE *, off_t, int); +hidden int __stdio_close(FILE *); + +hidden int __toread(FILE *); +hidden int __towrite(FILE *); + +hidden void __stdio_exit(void); +hidden void __stdio_exit_needed(void); + +#ifdef __wasilibc_unmodified_upstream // wasm has no "protected" visibility +#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303) +__attribute__((visibility("protected"))) +#endif +#endif +int __overflow(FILE *, int), __uflow(FILE *); + +hidden int __fseeko(FILE *, off_t, int); +hidden int __fseeko_unlocked(FILE *, off_t, int); +hidden off_t __ftello(FILE *); +hidden off_t __ftello_unlocked(FILE *); +hidden size_t __fwritex(const unsigned char *, size_t, FILE *); +hidden int __putc_unlocked(int, FILE *); + +hidden FILE *__fdopen(int, const char *); +hidden int __fmodeflags(const char *); + +hidden FILE *__ofl_add(FILE *f); +hidden FILE **__ofl_lock(void); +hidden void __ofl_unlock(void); + +struct __pthread; +hidden void __register_locked_file(FILE *, struct __pthread *); +hidden void __unlist_locked_file(FILE *); +hidden void __do_orphaned_stdio_locks(void); + +#define MAYBE_WAITERS 0x40000000 + +hidden void __getopt_msg(const char *, const char *, const char *, size_t); + +#define feof(f) ((f)->flags & F_EOF) +#define ferror(f) ((f)->flags & F_ERR) + +#define getc_unlocked(f) \ + ( ((f)->rpos != (f)->rend) ? *(f)->rpos++ : __uflow((f)) ) + +#define putc_unlocked(c, f) \ + ( (((unsigned char)(c)!=(f)->lbf && (f)->wpos!=(f)->wend)) \ + ? *(f)->wpos++ = (unsigned char)(c) \ + : __overflow((f),(unsigned char)(c)) ) + +/* Caller-allocated FILE * operations */ +hidden FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t); +hidden int __fclose_ca(FILE *); + +#endif diff --git a/libc-top-half/musl/src/internal/syscall.h b/libc-top-half/musl/src/internal/syscall.h new file mode 100644 index 0000000..32e0e8a --- /dev/null +++ b/libc-top-half/musl/src/internal/syscall.h @@ -0,0 +1,400 @@ +#ifdef __wasilibc_unmodified_upstream +#ifndef _INTERNAL_SYSCALL_H +#define _INTERNAL_SYSCALL_H + +#include <features.h> +#include <errno.h> +#include <sys/syscall.h> +#include "syscall_arch.h" + +#ifndef SYSCALL_RLIM_INFINITY +#define SYSCALL_RLIM_INFINITY (~0ULL) +#endif + +#ifndef SYSCALL_MMAP2_UNIT +#define SYSCALL_MMAP2_UNIT 4096ULL +#endif + +#ifndef __SYSCALL_LL_PRW +#define __SYSCALL_LL_PRW(x) __SYSCALL_LL_O(x) +#endif + +#ifndef __scc +#define __scc(X) ((long) (X)) +typedef long syscall_arg_t; +#endif + +hidden long __syscall_ret(unsigned long), + __syscall_cp(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, + syscall_arg_t, syscall_arg_t, syscall_arg_t); + +#define __syscall1(n,a) __syscall1(n,__scc(a)) +#define __syscall2(n,a,b) __syscall2(n,__scc(a),__scc(b)) +#define __syscall3(n,a,b,c) __syscall3(n,__scc(a),__scc(b),__scc(c)) +#define __syscall4(n,a,b,c,d) __syscall4(n,__scc(a),__scc(b),__scc(c),__scc(d)) +#define __syscall5(n,a,b,c,d,e) __syscall5(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) +#define __syscall6(n,a,b,c,d,e,f) __syscall6(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) +#define __syscall7(n,a,b,c,d,e,f,g) __syscall7(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) + +#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n +#define __SYSCALL_NARGS(...) __SYSCALL_NARGS_X(__VA_ARGS__,7,6,5,4,3,2,1,0,) +#define __SYSCALL_CONCAT_X(a,b) a##b +#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X(a,b) +#define __SYSCALL_DISP(b,...) __SYSCALL_CONCAT(b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) + +#define __syscall(...) __SYSCALL_DISP(__syscall,__VA_ARGS__) +#define syscall(...) __syscall_ret(__syscall(__VA_ARGS__)) + +#define socketcall(nm,a,b,c,d,e,f) __syscall_ret(__socketcall(nm,a,b,c,d,e,f)) +#define socketcall_cp(nm,a,b,c,d,e,f) __syscall_ret(__socketcall_cp(nm,a,b,c,d,e,f)) + +#define __syscall_cp0(n) (__syscall_cp)(n,0,0,0,0,0,0) +#define __syscall_cp1(n,a) (__syscall_cp)(n,__scc(a),0,0,0,0,0) +#define __syscall_cp2(n,a,b) (__syscall_cp)(n,__scc(a),__scc(b),0,0,0,0) +#define __syscall_cp3(n,a,b,c) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),0,0,0) +#define __syscall_cp4(n,a,b,c,d) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),0,0) +#define __syscall_cp5(n,a,b,c,d,e) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),0) +#define __syscall_cp6(n,a,b,c,d,e,f) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) + +#define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) +#define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) + +static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, long c, long d, long e, long f) +{ + long r; + if (cp) r = __syscall_cp(sys, a, b, c, d, e, f); + else r = __syscall(sys, a, b, c, d, e, f); + if (r != -ENOSYS) return r; +#ifdef SYS_socketcall + if (cp) r = __syscall_cp(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f})); + else r = __syscall(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f})); +#endif + return r; +} +#define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \ + (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) +#define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \ + (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) + +/* fixup legacy 16-bit junk */ + +#ifdef SYS_getuid32 +#undef SYS_lchown +#undef SYS_getuid +#undef SYS_getgid +#undef SYS_geteuid +#undef SYS_getegid +#undef SYS_setreuid +#undef SYS_setregid +#undef SYS_getgroups +#undef SYS_setgroups +#undef SYS_fchown +#undef SYS_setresuid +#undef SYS_getresuid +#undef SYS_setresgid +#undef SYS_getresgid +#undef SYS_chown +#undef SYS_setuid +#undef SYS_setgid +#undef SYS_setfsuid +#undef SYS_setfsgid +#define SYS_lchown SYS_lchown32 +#define SYS_getuid SYS_getuid32 +#define SYS_getgid SYS_getgid32 +#define SYS_geteuid SYS_geteuid32 +#define SYS_getegid SYS_getegid32 +#define SYS_setreuid SYS_setreuid32 +#define SYS_setregid SYS_setregid32 +#define SYS_getgroups SYS_getgroups32 +#define SYS_setgroups SYS_setgroups32 +#define SYS_fchown SYS_fchown32 +#define SYS_setresuid SYS_setresuid32 +#define SYS_getresuid SYS_getresuid32 +#define SYS_setresgid SYS_setresgid32 +#define SYS_getresgid SYS_getresgid32 +#define SYS_chown SYS_chown32 +#define SYS_setuid SYS_setuid32 +#define SYS_setgid SYS_setgid32 +#define SYS_setfsuid SYS_setfsuid32 +#define SYS_setfsgid SYS_setfsgid32 +#endif + + +/* fixup legacy 32-bit-vs-lfs64 junk */ + +#ifdef SYS_fcntl64 +#undef SYS_fcntl +#define SYS_fcntl SYS_fcntl64 +#endif + +#ifdef SYS_getdents64 +#undef SYS_getdents +#define SYS_getdents SYS_getdents64 +#endif + +#ifdef SYS_ftruncate64 +#undef SYS_ftruncate +#undef SYS_truncate +#define SYS_ftruncate SYS_ftruncate64 +#define SYS_truncate SYS_truncate64 +#endif + +#ifdef SYS_stat64 +#undef SYS_stat +#define SYS_stat SYS_stat64 +#endif + +#ifdef SYS_fstat64 +#undef SYS_fstat +#define SYS_fstat SYS_fstat64 +#endif + +#ifdef SYS_lstat64 +#undef SYS_lstat +#define SYS_lstat SYS_lstat64 +#endif + +#ifdef SYS_statfs64 +#undef SYS_statfs +#define SYS_statfs SYS_statfs64 +#endif + +#ifdef SYS_fstatfs64 +#undef SYS_fstatfs +#define SYS_fstatfs SYS_fstatfs64 +#endif + +#if defined(SYS_newfstatat) +#undef SYS_fstatat +#define SYS_fstatat SYS_newfstatat +#elif defined(SYS_fstatat64) +#undef SYS_fstatat +#define SYS_fstatat SYS_fstatat64 +#endif + +#ifdef SYS_ugetrlimit +#undef SYS_getrlimit +#define SYS_getrlimit SYS_ugetrlimit +#endif + +#ifdef SYS__newselect +#undef SYS_select +#define SYS_select SYS__newselect +#endif + +#ifdef SYS_pread64 +#undef SYS_pread +#undef SYS_pwrite +#define SYS_pread SYS_pread64 +#define SYS_pwrite SYS_pwrite64 +#endif + +#ifdef SYS_fadvise64_64 +#undef SYS_fadvise +#define SYS_fadvise SYS_fadvise64_64 +#elif defined(SYS_fadvise64) +#undef SYS_fadvise +#define SYS_fadvise SYS_fadvise64 +#endif + +#ifdef SYS_sendfile64 +#undef SYS_sendfile +#define SYS_sendfile SYS_sendfile64 +#endif + +#ifndef SYS_timer_settime +#define SYS_timer_settime SYS_timer_settime32 +#endif + +#ifndef SYS_timer_gettime +#define SYS_timer_gettime SYS_timer_gettime32 +#endif + +#ifndef SYS_timerfd_settime +#define SYS_timerfd_settime SYS_timerfd_settime32 +#endif + +#ifndef SYS_timerfd_gettime +#define SYS_timerfd_gettime SYS_timerfd_gettime32 +#endif + +#ifndef SYS_clock_settime +#define SYS_clock_settime SYS_clock_settime32 +#endif + +#ifndef SYS_clock_gettime +#define SYS_clock_gettime SYS_clock_gettime32 +#endif + +#ifndef SYS_clock_getres +#define SYS_clock_getres SYS_clock_getres_time32 +#endif + +#ifndef SYS_clock_nanosleep +#define SYS_clock_nanosleep SYS_clock_nanosleep_time32 +#endif + +#ifndef SYS_gettimeofday +#define SYS_gettimeofday SYS_gettimeofday_time32 +#endif + +#ifndef SYS_settimeofday +#define SYS_settimeofday SYS_settimeofday_time32 +#endif + +/* Ensure that the plain syscall names are defined even for "time64-only" + * archs. These facilitate callers passing null time arguments, and make + * tests for establishing which to use/fallback-to more consistent when + * they do need to be called with time arguments. */ + +#ifndef SYS_clock_gettime +#define SYS_clock_gettime SYS_clock_gettime64 +#endif + +#ifndef SYS_clock_settime +#define SYS_clock_settime SYS_clock_settime64 +#endif + +#ifndef SYS_clock_adjtime +#define SYS_clock_adjtime SYS_clock_adjtime64 +#endif + +#ifndef SYS_clock_getres +#define SYS_clock_getres SYS_clock_getres_time64 +#endif + +#ifndef SYS_clock_nanosleep +#define SYS_clock_nanosleep SYS_clock_nanosleep_time64 +#endif + +#ifndef SYS_timer_gettime +#define SYS_timer_gettime SYS_timer_gettime64 +#endif + +#ifndef SYS_timer_settime +#define SYS_timer_settime SYS_timer_settime64 +#endif + +#ifndef SYS_timerfd_gettime +#define SYS_timerfd_gettime SYS_timerfd_gettime64 +#endif + +#ifndef SYS_timerfd_settime +#define SYS_timerfd_settime SYS_timerfd_settime64 +#endif + +#ifndef SYS_utimensat +#define SYS_utimensat SYS_utimensat_time64 +#endif + +#ifndef SYS_pselect6 +#define SYS_pselect6 SYS_pselect6_time64 +#endif + +#ifndef SYS_ppoll +#define SYS_ppoll SYS_ppoll_time64 +#endif + +#ifndef SYS_recvmmsg +#define SYS_recvmmsg SYS_recvmmsg_time64 +#endif + +#ifndef SYS_mq_timedsend +#define SYS_mq_timedsend SYS_mq_timedsend_time64 +#endif + +#ifndef SYS_mq_timedreceive +#define SYS_mq_timedreceive SYS_mq_timedreceive_time64 +#endif + +/* SYS_semtimedop omitted because SYS_ipc may provide it */ + +#ifndef SYS_rt_sigtimedwait +#define SYS_rt_sigtimedwait SYS_rt_sigtimedwait_time64 +#endif + +#ifndef SYS_futex +#define SYS_futex SYS_futex_time64 +#endif + +#ifndef SYS_sched_rr_get_interval +#define SYS_sched_rr_get_interval SYS_sched_rr_get_interval_time64 +#endif + + + + +/* socketcall calls */ + +#define __SC_socket 1 +#define __SC_bind 2 +#define __SC_connect 3 +#define __SC_listen 4 +#define __SC_accept 5 +#define __SC_getsockname 6 +#define __SC_getpeername 7 +#define __SC_socketpair 8 +#define __SC_send 9 +#define __SC_recv 10 +#define __SC_sendto 11 +#define __SC_recvfrom 12 +#define __SC_shutdown 13 +#define __SC_setsockopt 14 +#define __SC_getsockopt 15 +#define __SC_sendmsg 16 +#define __SC_recvmsg 17 +#define __SC_accept4 18 +#define __SC_recvmmsg 19 +#define __SC_sendmmsg 20 + +/* This is valid only because all socket syscalls are made via + * socketcall, which always fills unused argument slots with zeros. */ +#ifndef SYS_accept +#define SYS_accept SYS_accept4 +#endif + +#ifndef SO_RCVTIMEO_OLD +#define SO_RCVTIMEO_OLD 20 +#endif +#ifndef SO_SNDTIMEO_OLD +#define SO_SNDTIMEO_OLD 21 +#endif + +#define SO_TIMESTAMP_OLD 29 +#define SO_TIMESTAMPNS_OLD 35 +#define SO_TIMESTAMPING_OLD 37 +#define SCM_TIMESTAMP_OLD SO_TIMESTAMP_OLD +#define SCM_TIMESTAMPNS_OLD SO_TIMESTAMPNS_OLD +#define SCM_TIMESTAMPING_OLD SO_TIMESTAMPING_OLD + +#ifndef SIOCGSTAMP_OLD +#define SIOCGSTAMP_OLD 0x8906 +#endif +#ifndef SIOCGSTAMPNS_OLD +#define SIOCGSTAMPNS_OLD 0x8907 +#endif + +#ifdef SYS_open +#define __sys_open2(x,pn,fl) __syscall2(SYS_open, pn, (fl)|O_LARGEFILE) +#define __sys_open3(x,pn,fl,mo) __syscall3(SYS_open, pn, (fl)|O_LARGEFILE, mo) +#define __sys_open_cp2(x,pn,fl) __syscall_cp2(SYS_open, pn, (fl)|O_LARGEFILE) +#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp3(SYS_open, pn, (fl)|O_LARGEFILE, mo) +#else +#define __sys_open2(x,pn,fl) __syscall3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) +#define __sys_open3(x,pn,fl,mo) __syscall4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) +#define __sys_open_cp2(x,pn,fl) __syscall_cp3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) +#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) +#endif + +#define __sys_open(...) __SYSCALL_DISP(__sys_open,,__VA_ARGS__) +#define sys_open(...) __syscall_ret(__sys_open(__VA_ARGS__)) + +#define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__) +#define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__)) + +hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned); + +hidden void *__vdsosym(const char *, const char *); + +#endif +#endif diff --git a/libc-top-half/musl/src/internal/syscall_ret.c b/libc-top-half/musl/src/internal/syscall_ret.c new file mode 100644 index 0000000..a3f4713 --- /dev/null +++ b/libc-top-half/musl/src/internal/syscall_ret.c @@ -0,0 +1,11 @@ +#include <errno.h> +#include "syscall.h" + +long __syscall_ret(unsigned long r) +{ + if (r > -4096UL) { + errno = -r; + return -1; + } + return r; +} diff --git a/libc-top-half/musl/src/internal/vdso.c b/libc-top-half/musl/src/internal/vdso.c new file mode 100644 index 0000000..d46d322 --- /dev/null +++ b/libc-top-half/musl/src/internal/vdso.c @@ -0,0 +1,93 @@ +#include <elf.h> +#include <link.h> +#include <limits.h> +#include <stdint.h> +#include <string.h> +#include "libc.h" +#include "syscall.h" + +#ifdef VDSO_USEFUL + +#if ULONG_MAX == 0xffffffff +typedef Elf32_Ehdr Ehdr; +typedef Elf32_Phdr Phdr; +typedef Elf32_Sym Sym; +typedef Elf32_Verdef Verdef; +typedef Elf32_Verdaux Verdaux; +#else +typedef Elf64_Ehdr Ehdr; +typedef Elf64_Phdr Phdr; +typedef Elf64_Sym Sym; +typedef Elf64_Verdef Verdef; +typedef Elf64_Verdaux Verdaux; +#endif + +static int checkver(Verdef *def, int vsym, const char *vername, char *strings) +{ + vsym &= 0x7fff; + for (;;) { + if (!(def->vd_flags & VER_FLG_BASE) + && (def->vd_ndx & 0x7fff) == vsym) + break; + if (def->vd_next == 0) + return 0; + def = (Verdef *)((char *)def + def->vd_next); + } + Verdaux *aux = (Verdaux *)((char *)def + def->vd_aux); + return !strcmp(vername, strings + aux->vda_name); +} + +#define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON) +#define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE) + +void *__vdsosym(const char *vername, const char *name) +{ + size_t i; + for (i=0; libc.auxv[i] != AT_SYSINFO_EHDR; i+=2) + if (!libc.auxv[i]) return 0; + if (!libc.auxv[i+1]) return 0; + Ehdr *eh = (void *)libc.auxv[i+1]; + Phdr *ph = (void *)((char *)eh + eh->e_phoff); + size_t *dynv=0, base=-1; + for (i=0; i<eh->e_phnum; i++, ph=(void *)((char *)ph+eh->e_phentsize)) { + if (ph->p_type == PT_LOAD) + base = (size_t)eh + ph->p_offset - ph->p_vaddr; + else if (ph->p_type == PT_DYNAMIC) + dynv = (void *)((char *)eh + ph->p_offset); + } + if (!dynv || base==(size_t)-1) return 0; + + char *strings = 0; + Sym *syms = 0; + Elf_Symndx *hashtab = 0; + uint16_t *versym = 0; + Verdef *verdef = 0; + + for (i=0; dynv[i]; i+=2) { + void *p = (void *)(base + dynv[i+1]); + switch(dynv[i]) { + case DT_STRTAB: strings = p; break; + case DT_SYMTAB: syms = p; break; + case DT_HASH: hashtab = p; break; + case DT_VERSYM: versym = p; break; + case DT_VERDEF: verdef = p; break; + } + } + + if (!strings || !syms || !hashtab) return 0; + if (!verdef) versym = 0; + + for (i=0; i<hashtab[1]; i++) { + if (!(1<<(syms[i].st_info&0xf) & OK_TYPES)) continue; + if (!(1<<(syms[i].st_info>>4) & OK_BINDS)) continue; + if (!syms[i].st_shndx) continue; + if (strcmp(name, strings+syms[i].st_name)) continue; + if (versym && !checkver(verdef, versym[i], vername, strings)) + continue; + return (void *)(base + syms[i].st_value); + } + + return 0; +} + +#endif diff --git a/libc-top-half/musl/src/internal/version.c b/libc-top-half/musl/src/internal/version.c new file mode 100644 index 0000000..08bbf5b --- /dev/null +++ b/libc-top-half/musl/src/internal/version.c @@ -0,0 +1,4 @@ +#include "version.h" +#include "libc.h" + +const char __libc_version[] = VERSION; |