diff options
Diffstat (limited to 'src')
33 files changed, 203 insertions, 45 deletions
diff --git a/src/include/sys/auxv.h b/src/include/sys/auxv.h index 9358a4a..63c5bfe 100644 --- a/src/include/sys/auxv.h +++ b/src/include/sys/auxv.h @@ -5,6 +5,6 @@ #include <features.h> -hidden unsigned long __getauxval(unsigned long); +unsigned long __getauxval(unsigned long); #endif diff --git a/src/ldso/loongarch64/tlsdesc.s b/src/ldso/loongarch64/tlsdesc.s new file mode 100644 index 0000000..4b6ea0e --- /dev/null +++ b/src/ldso/loongarch64/tlsdesc.s @@ -0,0 +1,37 @@ +.text +.global __tlsdesc_static +.hidden __tlsdesc_static +.type __tlsdesc_static,%function +__tlsdesc_static: + ld.d $a0, $a0, 8 + jr $ra +# size_t __tlsdesc_dynamic(size_t *a) +# { +# struct {size_t modidx,off;} *p = (void*)a[1]; +# size_t *dtv = *(size_t**)(tp - 8); +# return dtv[p->modidx] + p->off - tp; +# } +.global __tlsdesc_dynamic +.hidden __tlsdesc_dynamic +.type __tlsdesc_dynamic,%function +__tlsdesc_dynamic: + addi.d $sp, $sp, -16 + st.d $t1, $sp, 0 + st.d $t2, $sp, 8 + + ld.d $t2, $tp, -8 # t2=dtv + + ld.d $a0, $a0, 8 # a0=&{modidx,off} + ld.d $t1, $a0, 8 # t1=off + ld.d $a0, $a0, 0 # a0=modidx + slli.d $a0, $a0, 3 # a0=8*modidx + + add.d $a0, $a0, $t2 # a0=dtv+8*modidx + ld.d $a0, $a0, 0 # a0=dtv[modidx] + add.d $a0, $a0, $t1 # a0=dtv[modidx]+off + sub.d $a0, $a0, $tp # a0=dtv[modidx]+off-tp + + ld.d $t1, $sp, 0 + ld.d $t2, $sp, 8 + addi.d $sp, $sp, 16 + jr $ra diff --git a/src/locale/bind_textdomain_codeset.c b/src/locale/bind_textdomain_codeset.c index 5ebfd5e..240e83e 100644 --- a/src/locale/bind_textdomain_codeset.c +++ b/src/locale/bind_textdomain_codeset.c @@ -5,7 +5,9 @@ char *bind_textdomain_codeset(const char *domainname, const char *codeset) { - if (codeset && strcasecmp(codeset, "UTF-8")) + if (codeset && strcasecmp(codeset, "UTF-8")) { errno = EINVAL; - return NULL; + return 0; + } + return "UTF-8"; } diff --git a/src/locale/iconv.c b/src/locale/iconv.c index 7fb2e1e..5217895 100644 --- a/src/locale/iconv.c +++ b/src/locale/iconv.c @@ -339,6 +339,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri } else if (d-159 <= 252-159) { c++; d -= 159; + } else { + goto ilseq; } if (c>=84) goto ilseq; c = jis0208[c][d]; @@ -500,7 +502,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (c >= 93 || d >= 94) { c += (0xa1-0x81); d += 0xa1; - if (c >= 93 || c>=0xc6-0x81 && d>0x52) + if (c > 0xc6-0x81 || c==0xc6-0x81 && d>0x52) goto ilseq; if (d-'A'<26) d = d-'A'; else if (d-'a'<26) d = d-'a'+26; @@ -543,6 +545,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri if (*outb < k) goto toobig; memcpy(*out, tmp, k); } else k = wctomb_utf8(*out, c); + /* This failure condition should be unreachable, but + * is included to prevent decoder bugs from translating + * into advancement outside the output buffer range. */ + if (k>4) goto ilseq; *out += k; *outb -= k; break; diff --git a/src/misc/mntent.c b/src/misc/mntent.c index ee17a69..76f9c16 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -115,5 +115,13 @@ int addmntent(FILE *f, const struct mntent *mnt) char *hasmntopt(const struct mntent *mnt, const char *opt) { - return strstr(mnt->mnt_opts, opt); + size_t l = strlen(opt); + char *p = mnt->mnt_opts; + for (;;) { + if (!strncmp(p, opt, l) && (!p[l] || p[l]==',' || p[l]=='=')) + return p; + p = strchr(p, ','); + if (!p) return 0; + p++; + } } diff --git a/src/mq/x32/mq_open.c b/src/mq/x32/mq_open.c new file mode 100644 index 0000000..2348195 --- /dev/null +++ b/src/mq/x32/mq_open.c @@ -0,0 +1,22 @@ +#include <mqueue.h> +#include <fcntl.h> +#include <stdarg.h> +#include "syscall.h" + +mqd_t mq_open(const char *name, int flags, ...) +{ + mode_t mode = 0; + struct mq_attr *attr = 0; + long long attrbuf[8]; + if (*name == '/') name++; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, mode_t); + attr = va_arg(ap, struct mq_attr *); + if (attr) for (int i=0; i<8; i++) + attrbuf[i] = *(long *)((char *)attr + i*sizeof(long)); + va_end(ap); + } + return syscall(SYS_mq_open, name, flags, mode, attr?attrbuf:0); +} diff --git a/src/mq/x32/mq_setattr.c b/src/mq/x32/mq_setattr.c new file mode 100644 index 0000000..0c63117 --- /dev/null +++ b/src/mq/x32/mq_setattr.c @@ -0,0 +1,14 @@ +#include <mqueue.h> +#include "syscall.h" + +int mq_setattr(mqd_t mqd, const struct mq_attr *restrict new, struct mq_attr *restrict old) +{ + long long attr[8]; + if (new) for (int i=0; i<8; i++) + attr[i] = *(long *)((char *)new + i*sizeof(long)); + int ret = __syscall(SYS_mq_getsetattr, mqd, new?attr:0, old?attr:0); + if (ret < 0) return __syscall_ret(ret); + if (old) for (int i=0; i<8; i++) + *(long *)((char *)old + i*sizeof(long)) = attr[i]; + return 0; +} diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c index 931192e..47cbdc0 100644 --- a/src/multibyte/mbsnrtowcs.c +++ b/src/multibyte/mbsnrtowcs.c @@ -2,11 +2,13 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, size_t wn, mbstate_t *restrict st) { + static unsigned internal_state; size_t l, cnt=0, n2; wchar_t *ws, wbuf[256]; const char *s = *src; const char *tmp_s; + if (!st) st = (void *)&internal_state; if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf; else ws = wcs; @@ -41,8 +43,8 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, si s = 0; break; } - /* have to roll back partial character */ - *(unsigned *)st = 0; + s += n; + n -= n; break; } s += l; n -= l; diff --git a/src/network/res_msend.c b/src/network/res_msend.c index 86c2fcf..fcb5251 100644 --- a/src/network/res_msend.c +++ b/src/network/res_msend.c @@ -83,8 +83,8 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries, int fd; int timeout, attempts, retry_interval, servfail_retry; union { - struct sockaddr_in sin; struct sockaddr_in6 sin6; + struct sockaddr_in sin; } sa = {0}, ns[MAXNS] = {{0}}; socklen_t sl = sizeof sa.sin; int nns = 0; diff --git a/src/signal/riscv32/restore.s b/src/signal/riscv32/restore.s index 40012c7..5a0af69 100644 --- a/src/signal/riscv32/restore.s +++ b/src/signal/riscv32/restore.s @@ -1,7 +1,9 @@ .global __restore +.hidden __restore .type __restore, %function __restore: .global __restore_rt +.hidden __restore_rt .type __restore_rt, %function __restore_rt: li a7, 139 # SYS_rt_sigreturn diff --git a/src/signal/riscv64/restore.s b/src/signal/riscv64/restore.s index 40012c7..5a0af69 100644 --- a/src/signal/riscv64/restore.s +++ b/src/signal/riscv64/restore.s @@ -1,7 +1,9 @@ .global __restore +.hidden __restore .type __restore, %function __restore: .global __restore_rt +.hidden __restore_rt .type __restore_rt, %function __restore_rt: li a7, 139 # SYS_rt_sigreturn diff --git a/src/signal/sigpause.c b/src/signal/sigpause.c index 363d2fe..1587c39 100644 --- a/src/signal/sigpause.c +++ b/src/signal/sigpause.c @@ -4,6 +4,6 @@ int sigpause(int sig) { sigset_t mask; sigprocmask(0, 0, &mask); - sigdelset(&mask, sig); + if (sigdelset(&mask, sig)) return -1; return sigsuspend(&mask); } diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c index d2d8947..5356553 100644 --- a/src/stdio/__stdio_write.c +++ b/src/stdio/__stdio_write.c @@ -11,6 +11,11 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len) size_t rem = iov[0].iov_len + iov[1].iov_len; int iovcnt = 2; ssize_t cnt; + + if (!iov->iov_len) { + iov++; + iovcnt--; + } for (;;) { cnt = syscall(SYS_writev, f->fd, iov, iovcnt); if (cnt == rem) { diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 7673399..a68edab 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -180,11 +180,11 @@ typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double) static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t, int ps) { - int bufsize = (ps==BIGLPRE) - ? (LDBL_MANT_DIG+28)/29 + 1 + // mantissa expansion - (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9 // exponent expansion - : (DBL_MANT_DIG+28)/29 + 1 + - (DBL_MAX_EXP+DBL_MANT_DIG+28+8)/9; + int max_mant_dig = (ps==BIGLPRE) ? LDBL_MANT_DIG : DBL_MANT_DIG; + int max_exp = (ps==BIGLPRE) ? LDBL_MAX_EXP : DBL_MAX_EXP; + int max_mant_slots = (max_mant_dig+28)/29 + 1; + int max_exp_slots = (max_exp+max_mant_dig+28+8)/9; + int bufsize = max_mant_slots + max_exp_slots; uint32_t big[bufsize]; uint32_t *a, *d, *r, *z; int e2=0, e, i, j, l; @@ -266,7 +266,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t, int ps) if (y) y *= 0x1p28, e2-=28; if (e2<0) a=r=z=big; - else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1; + else a=r=z=big+sizeof(big)/sizeof(*big) - max_mant_slots - 1; do { *z = y; diff --git a/src/string/strcasestr.c b/src/string/strcasestr.c index af109f3..dc598bc 100644 --- a/src/string/strcasestr.c +++ b/src/string/strcasestr.c @@ -4,6 +4,7 @@ char *strcasestr(const char *h, const char *n) { size_t l = strlen(n); + if (!l) return (char *)h; for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h; return 0; } diff --git a/src/termios/cfgetospeed.c b/src/termios/cfgetospeed.c index 55fa6f5..de46a1d 100644 --- a/src/termios/cfgetospeed.c +++ b/src/termios/cfgetospeed.c @@ -9,5 +9,5 @@ speed_t cfgetospeed(const struct termios *tio) speed_t cfgetispeed(const struct termios *tio) { - return cfgetospeed(tio); + return (tio->c_cflag & CIBAUD) / (CIBAUD/CBAUD); } diff --git a/src/termios/cfsetospeed.c b/src/termios/cfsetospeed.c index c9cbdd9..3eab092 100644 --- a/src/termios/cfsetospeed.c +++ b/src/termios/cfsetospeed.c @@ -16,7 +16,11 @@ int cfsetospeed(struct termios *tio, speed_t speed) int cfsetispeed(struct termios *tio, speed_t speed) { - return speed ? cfsetospeed(tio, speed) : 0; + if (speed & ~CBAUD) { + errno = EINVAL; + return -1; + } + tio->c_cflag &= ~CIBAUD; + tio->c_cflag |= speed * (CIBAUD/CBAUD); + return 0; } - -weak_alias(cfsetospeed, cfsetspeed); diff --git a/src/termios/cfsetspeed.c b/src/termios/cfsetspeed.c new file mode 100644 index 0000000..2c369db --- /dev/null +++ b/src/termios/cfsetspeed.c @@ -0,0 +1,11 @@ +#define _BSD_SOURCE +#include <termios.h> +#include <sys/ioctl.h> +#include <errno.h> + +int cfsetspeed(struct termios *tio, speed_t speed) +{ + int r = cfsetospeed(tio, speed); + if (!r) cfsetispeed(tio, 0); + return r; +} diff --git a/src/thread/aarch64/__set_thread_area.c b/src/thread/aarch64/__set_thread_area.c new file mode 100644 index 0000000..2ec788e --- /dev/null +++ b/src/thread/aarch64/__set_thread_area.c @@ -0,0 +1,27 @@ +#include <elf.h> +#include "libc.h" + +#define BITRANGE(a,b) (2*(1UL<<(b))-(1UL<<(a))) + +int __set_thread_area(void *p) +{ + __asm__ __volatile__ ("msr tpidr_el0,%0" : : "r"(p) : "memory"); + + /* Mask off hwcap bits for SME and unknown future features. This is + * necessary because SME is not safe to use without libc support for + * it, and we do not (yet) have such support. */ + for (size_t *v = libc.auxv; *v; v+=2) { + if (v[0]==AT_HWCAP) { + v[1] &= ~BITRANGE(42,63); /* 42-47 are SME */ + } else if (v[0]==AT_HWCAP2) { + v[1] &= ~(BITRANGE(23,30) + | BITRANGE(37,42) + | BITRANGE(57,62)); + } else if (v[0]==AT_HWCAP3 || v[0]==AT_HWCAP4) { + v[0] = AT_IGNORE; + v[1] = 0; + } + } + + return 0; +} diff --git a/src/thread/aarch64/__set_thread_area.s b/src/thread/aarch64/__set_thread_area.s deleted file mode 100644 index fd0df34..0000000 --- a/src/thread/aarch64/__set_thread_area.s +++ /dev/null @@ -1,7 +0,0 @@ -.global __set_thread_area -.hidden __set_thread_area -.type __set_thread_area,@function -__set_thread_area: - msr tpidr_el0,x0 - mov w0,#0 - ret diff --git a/src/thread/aarch64/clone.s b/src/thread/aarch64/clone.s index e3c8339..aff8155 100644 --- a/src/thread/aarch64/clone.s +++ b/src/thread/aarch64/clone.s @@ -24,7 +24,8 @@ __clone: // parent ret // child -1: ldp x1,x0,[sp],#16 +1: mov x29, 0 + ldp x1,x0,[sp],#16 blr x1 mov x8,#93 // SYS_exit svc #0 diff --git a/src/thread/arm/clone.s b/src/thread/arm/clone.s index bb0965d..4ff0c0e 100644 --- a/src/thread/arm/clone.s +++ b/src/thread/arm/clone.s @@ -19,7 +19,8 @@ __clone: ldmfd sp!,{r4,r5,r6,r7} bx lr -1: mov r0,r6 +1: mov fp,#0 + mov r0,r6 bl 3f 2: mov r7,#1 svc 0 diff --git a/src/thread/loongarch64/clone.s b/src/thread/loongarch64/clone.s index a165b36..cb4aacf 100644 --- a/src/thread/loongarch64/clone.s +++ b/src/thread/loongarch64/clone.s @@ -22,6 +22,7 @@ __clone: beqz $a0, 1f # whether child process jirl $zero, $ra, 0 # parent process return 1: + move $fp, $zero ld.d $t8, $sp, 0 # function pointer ld.d $a0, $sp, 8 # argument pointer jirl $ra, $t8, 0 # call the user's function diff --git a/src/thread/m68k/clone.s b/src/thread/m68k/clone.s index f6dfa06..0134cf4 100644 --- a/src/thread/m68k/clone.s +++ b/src/thread/m68k/clone.s @@ -18,7 +18,8 @@ __clone: beq 1f movem.l (%sp)+,%d2-%d5 rts -1: move.l %a1,-(%sp) +1: suba.l %fp,%fp + move.l %a1,-(%sp) jsr (%a0) move.l #1,%d0 trap #0 diff --git a/src/thread/microblaze/clone.s b/src/thread/microblaze/clone.s index b68cc5f..64e3f07 100644 --- a/src/thread/microblaze/clone.s +++ b/src/thread/microblaze/clone.s @@ -22,7 +22,8 @@ __clone: rtsd r15, 8 nop -1: lwi r3, r1, 0 +1: add r19, r0, r0 + lwi r3, r1, 0 lwi r5, r1, 4 brald r15, r3 nop diff --git a/src/thread/mips/clone.s b/src/thread/mips/clone.s index 0446338..229b987 100644 --- a/src/thread/mips/clone.s +++ b/src/thread/mips/clone.s @@ -27,7 +27,8 @@ __clone: addu $sp, $sp, 16 jr $ra nop -1: lw $25, 0($sp) +1: move $fp, $0 + lw $25, 0($sp) lw $4, 4($sp) jalr $25 nop diff --git a/src/thread/mips64/clone.s b/src/thread/mips64/clone.s index 2d86899..8de3db6 100644 --- a/src/thread/mips64/clone.s +++ b/src/thread/mips64/clone.s @@ -25,7 +25,8 @@ __clone: nop jr $ra nop -1: ld $25, 0($sp) # function pointer +1: move $fp, $0 + ld $25, 0($sp) # function pointer ld $4, 8($sp) # argument pointer jalr $25 # call the user's function nop diff --git a/src/thread/mipsn32/clone.s b/src/thread/mipsn32/clone.s index 4d3c8c7..9571231 100644 --- a/src/thread/mipsn32/clone.s +++ b/src/thread/mipsn32/clone.s @@ -25,7 +25,8 @@ __clone: nop jr $ra nop -1: lw $25, 0($sp) # function pointer +1: move $fp, $0 + lw $25, 0($sp) # function pointer lw $4, 4($sp) # argument pointer jalr $25 # call the user's function nop diff --git a/src/thread/or1k/clone.s b/src/thread/or1k/clone.s index 2473ac2..b41488a 100644 --- a/src/thread/or1k/clone.s +++ b/src/thread/or1k/clone.s @@ -6,6 +6,8 @@ .hidden __clone .type __clone,@function __clone: + l.xori r11, r0, -4 + l.and r4, r4, r11 l.addi r4, r4, -8 l.sw 0(r4), r3 l.sw 4(r4), r6 @@ -23,7 +25,8 @@ __clone: l.jr r9 l.nop -1: l.lwz r11, 0(r1) +1: l.ori r2, r0, 0 + l.lwz r11, 0(r1) l.jalr r11 l.lwz r3, 4(r1) diff --git a/src/thread/riscv32/clone.s b/src/thread/riscv32/clone.s index 3102239..e2116e3 100644 --- a/src/thread/riscv32/clone.s +++ b/src/thread/riscv32/clone.s @@ -8,6 +8,7 @@ .type __clone, %function __clone: # Save func and arg to stack + andi a1, a1, -16 addi a1, a1, -16 sw a0, 0(a1) sw a3, 4(a1) diff --git a/src/thread/riscv64/clone.s b/src/thread/riscv64/clone.s index db90824..0e6f41a 100644 --- a/src/thread/riscv64/clone.s +++ b/src/thread/riscv64/clone.s @@ -8,6 +8,7 @@ .type __clone, %function __clone: # Save func and arg to stack + andi a1, a1, -16 addi a1, a1, -16 sd a0, 0(a1) sd a3, 8(a1) diff --git a/src/thread/s390x/__tls_get_offset.s b/src/thread/s390x/__tls_get_offset.s index 8ee92de..405f118 100644 --- a/src/thread/s390x/__tls_get_offset.s +++ b/src/thread/s390x/__tls_get_offset.s @@ -1,17 +1,17 @@ .global __tls_get_offset .type __tls_get_offset,%function __tls_get_offset: - stmg %r14, %r15, 112(%r15) - aghi %r15, -160 + ear %r0, %a0 + sllg %r0, %r0, 32 + ear %r0, %a1 - la %r2, 0(%r2, %r12) - brasl %r14, __tls_get_addr + la %r1, 0(%r2, %r12) - ear %r1, %a0 - sllg %r1, %r1, 32 - ear %r1, %a1 + lg %r3, 0(%r1) + sllg %r4, %r3, 3 + lg %r5, 8(%r0) + lg %r2, 0(%r4, %r5) + ag %r2, 8(%r1) + sgr %r2, %r0 - sgr %r2, %r1 - - lmg %r14, %r15, 272(%r15) br %r14 diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 424c70b..cc6c223 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -22,10 +22,16 @@ static void dummy_0() } weak_alias(dummy_0, __pthread_tsd_run_dtors); +static void timer_handler(int sig, siginfo_t *si, void *ctx) +{ +} + static void cleanup_fromsig(void *p) { pthread_t self = __pthread_self(); __pthread_tsd_run_dtors(); + __block_app_sigs(0); + __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGTIMER_SET, 0, _NSIG/8); self->cancel = 0; self->cancelbuf = 0; self->canceldisable = 0; @@ -98,7 +104,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict break; case SIGEV_THREAD: if (!init) { - struct sigaction sa = { .sa_handler = SIG_DFL }; + struct sigaction sa = { + .sa_sigaction = timer_handler, + .sa_flags = SA_SIGINFO | SA_RESTART + }; __libc_sigaction(SIGTIMER, &sa, 0); a_store(&init, 1); } |