From 32682f0ce77fc24e8a70e3563e20e59300b72844 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Thu, 8 Jun 2023 06:12:26 -0700 Subject: [PATCH] Remove some problematic APIs In order to improve our chances of success building other open source projects we shouldn't define APIs that'll lead any ./configure script astray. For example: - brk() and sbrk() can break mac/windows support - syscall() is a superb way to break portability - arch_prctl() is the greatest of all horror shows --- ape/ape.mk | 2 - libc/calls/calls.h | 28 ++-- libc/calls/getfiledescriptorsize.c | 90 ----------- libc/intrin/describeframe.c | 8 - libc/intrin/kprintf.greg.c | 1 - libc/intrin/segmentation.h | 1 - libc/log/vflogf.c | 4 +- libc/runtime/arch_prctl.c | 243 ---------------------------- libc/runtime/brk.c | 186 --------------------- libc/runtime/brk.internal.h | 16 -- libc/runtime/ezmap.c | 2 +- libc/runtime/finddebugbinary.c | 3 +- libc/runtime/mremap.c | 208 ------------------------ libc/runtime/opensymboltable.greg.c | 2 +- libc/runtime/runtime.h | 3 - libc/str/setlocale.c | 4 +- libc/str/unicode.h | 5 +- libc/x/xslurp.c | 4 +- libc/zipos/get.c | 2 +- test/libc/mem/test.mk | 1 - test/libc/runtime/arch_prctl_test.c | 131 --------------- third_party/make/main.c | 4 - tool/plinko/lib/lib.mk | 1 + tool/plinko/lib/plinko.c | 7 +- 24 files changed, 37 insertions(+), 919 deletions(-) delete mode 100644 libc/calls/getfiledescriptorsize.c delete mode 100644 libc/runtime/arch_prctl.c delete mode 100644 libc/runtime/brk.c delete mode 100644 libc/runtime/brk.internal.h delete mode 100644 libc/runtime/mremap.c delete mode 100644 test/libc/runtime/arch_prctl_test.c diff --git a/ape/ape.mk b/ape/ape.mk index d81eb409e..00618f31c 100644 --- a/ape/ape.mk +++ b/ape/ape.mk @@ -130,7 +130,6 @@ o/$(MODE)/ape/ape-no-modify-self.o: \ libc/runtime/e820.internal.h \ libc/runtime/mman.internal.h \ libc/runtime/pc.internal.h \ - libc/runtime/symbolic.h \ libc/sysv/consts/prot.h \ ape/blink-aarch64.gz \ ape/blink-darwin-arm64.gz \ @@ -160,7 +159,6 @@ o/$(MODE)/ape/ape-copy-self.o: \ libc/runtime/e820.internal.h \ libc/runtime/mman.internal.h \ libc/runtime/pc.internal.h \ - libc/runtime/symbolic.h \ libc/sysv/consts/prot.h \ ape/blink-aarch64.gz \ ape/blink-darwin-arm64.gz diff --git a/libc/calls/calls.h b/libc/calls/calls.h index 18a34fe29..02a835df9 100644 --- a/libc/calls/calls.h +++ b/libc/calls/calls.h @@ -68,13 +68,7 @@ COSMOPOLITAN_C_START_ typedef int sig_atomic_t; -bool fileexists(const char *); -bool isdirectory(const char *); -bool isexecutable(const char *); -bool isregularfile(const char *); -bool issymlink(const char *); bool32 isatty(int) nosideeffect; -bool32 ischardev(int) nosideeffect; char *commandv(const char *, char *, size_t); char *get_current_dir_name(void) dontdiscard; char *getcwd(char *, size_t); @@ -82,7 +76,6 @@ char *realpath(const char *, char *); char *replaceuser(const char *) dontdiscard; char *ttyname(int); int access(const char *, int) dontthrow; -int arch_prctl(); int chdir(const char *); int chmod(const char *, unsigned); int chown(const char *, unsigned, unsigned); @@ -166,7 +159,6 @@ int reboot(int); int remove(const char *); int rename(const char *, const char *); int renameat(int, const char *, int, const char *); -int renameat2(long, const char *, long, const char *, int); int rmdir(const char *); int sched_yield(void); int seccomp(unsigned, unsigned, void *); @@ -214,11 +206,8 @@ int usleep(unsigned); int vfork(void) returnstwice; int wait(int *); int waitpid(int, int *, int); -intptr_t syscall(int, ...); long ptrace(int, ...); ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned); -ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, unsigned); -ssize_t getfiledescriptorsize(int); ssize_t lseek(int, int64_t, int); ssize_t pread(int, void *, size_t, int64_t); ssize_t pwrite(int, const void *, size_t, int64_t); @@ -235,6 +224,23 @@ unsigned getuid(void) libcesque; unsigned umask(unsigned); void sync(void); +#ifdef COSMO +#define fileexists __fileexists +#define isdirectory __isdirectory +#define isexecutable __isexecutable +#define isregularfile __isregularfile +#define issymlink __issymlink +#define ischardev __ischardev +#define copyfd __copyfd +bool fileexists(const char *); +bool isdirectory(const char *); +bool isexecutable(const char *); +bool isregularfile(const char *); +bool issymlink(const char *); +bool32 ischardev(int) nosideeffect; +ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, unsigned); +#endif + COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_ */ diff --git a/libc/calls/getfiledescriptorsize.c b/libc/calls/getfiledescriptorsize.c deleted file mode 100644 index 3e423db4a..000000000 --- a/libc/calls/getfiledescriptorsize.c +++ /dev/null @@ -1,90 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" -#include "libc/calls/internal.h" -#include "libc/calls/metalfile.internal.h" -#include "libc/calls/struct/metastat.internal.h" -#include "libc/calls/struct/stat.h" -#include "libc/calls/syscall-sysv.internal.h" -#include "libc/dce.h" -#include "libc/errno.h" -#include "libc/intrin/strace.internal.h" -#include "libc/intrin/weaken.h" -#include "libc/limits.h" -#include "libc/nt/enum/fileinfobyhandleclass.h" -#include "libc/nt/files.h" -#include "libc/nt/struct/filestandardinformation.h" -#include "libc/sysv/errfuns.h" -#include "libc/zipos/zipos.internal.h" - -/** - * Determines size of open file. - * - * This function is equivalent to: - * - * struct stat st; - * !fstat(fd, &st) ? st.st_size : -1 - * - * Except faster on BSD/Windows and a much smaller link size. - * - * @return file byte length, or -1 w/ errno - * @asyncsignalsafe - */ -ssize_t getfiledescriptorsize(int fd) { - int e; - ssize_t rc; - union metastat st; - struct NtFileStandardInformation info; - e = errno; - if (__isfdkind(fd, kFdZip)) { - if (_weaken(__zipos_fstat)( - (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, &st.cosmo) != - -1) { - rc = st.cosmo.st_size; - } else { - rc = -1; - } - } else if (IsMetal()) { - if (fd < 0 || fd >= g_fds.n) { - rc = ebadf(); - } else if (g_fds.p[fd].kind != kFdFile) { - rc = eacces(); - } else { - struct MetalFile *state = (struct MetalFile *)g_fds.p[fd].handle; - rc = state->size; - } - } else if (!IsWindows()) { - if (!__sys_fstat(fd, &st)) { - rc = METASTAT(st, st_size); - } else { - rc = -1; - } - } else if (__isfdopen(fd)) { - if (GetFileInformationByHandleEx(g_fds.p[fd].handle, kNtFileStandardInfo, - &info, sizeof(info))) { - rc = info.EndOfFile; - } else { - rc = ebadf(); - } - } else { - rc = ebadf(); - } - STRACE("getfiledescriptorsize(%d) → %'zd% m", fd, rc); - return rc; -} diff --git a/libc/intrin/describeframe.c b/libc/intrin/describeframe.c index 217c54922..847e3b707 100644 --- a/libc/intrin/describeframe.c +++ b/libc/intrin/describeframe.c @@ -21,7 +21,6 @@ #include "libc/intrin/kprintf.h" #include "libc/intrin/weaken.h" #include "libc/macros.internal.h" -#include "libc/runtime/brk.internal.h" #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/winargs.internal.h" @@ -29,11 +28,6 @@ #define UNSHADOW(x) ((int64_t)(MAX(0, (x)-0x7fff8000)) << 3) #define FRAME(x) ((int)((x) >> 16)) -forceinline pureconst bool IsBrkFrame(int x) { - unsigned char *p = (unsigned char *)ADDR_32_TO_48(x); - return _weaken(__brk) && p >= _end && p < _weaken(__brk)->p; -} - static const char *GetFrameName(int x) { if (!x) { return "null"; @@ -47,8 +41,6 @@ static const char *GetFrameName(int x) { return "arena"; } else if (IsStaticStackFrame(x)) { return "stack"; - } else if (IsBrkFrame(x)) { - return "brk"; } else if (IsGfdsFrame(x)) { return "g_fds"; } else if (IsZiposFrame(x)) { diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c index bdbd70086..1bd24ddda 100644 --- a/libc/intrin/kprintf.greg.c +++ b/libc/intrin/kprintf.greg.c @@ -45,7 +45,6 @@ #include "libc/nt/runtime.h" #include "libc/nt/thunk/msabi.h" #include "libc/nt/winsock.h" -#include "libc/runtime/brk.internal.h" #include "libc/runtime/internal.h" #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" diff --git a/libc/intrin/segmentation.h b/libc/intrin/segmentation.h index 862519730..c354aaa12 100644 --- a/libc/intrin/segmentation.h +++ b/libc/intrin/segmentation.h @@ -8,7 +8,6 @@ * Reads scalar from memory, offset by segment. * * @return *(MEM) relative to segment - * @see arch_prctl() * @see pushpop() */ #define fs(MEM) __peek("fs", MEM) diff --git a/libc/log/vflogf.c b/libc/log/vflogf.c index 4405ced1a..028c3d63f 100644 --- a/libc/log/vflogf.c +++ b/libc/log/vflogf.c @@ -50,12 +50,12 @@ static struct timespec vflogf_ts; static void vflogf_onfail(FILE *f) { errno_t err; int64_t size; + struct stat st; if (IsTiny()) return; err = ferror_unlocked(f); if (fileno_unlocked(f) != -1 && (err == ENOSPC || err == EDQUOT || err == EFBIG) && - ((size = getfiledescriptorsize(fileno_unlocked(f))) == -1 || - size > kNontrivialSize)) { + (fstat(fileno_unlocked(f), &st) == -1 || st.st_size > kNontrivialSize)) { ftruncate(fileno_unlocked(f), 0); fseeko_unlocked(f, SEEK_SET, 0); f->beg = f->end = 0; diff --git a/libc/runtime/arch_prctl.c b/libc/runtime/arch_prctl.c deleted file mode 100644 index 6e3fee7a7..000000000 --- a/libc/runtime/arch_prctl.c +++ /dev/null @@ -1,243 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" -#include "libc/calls/syscall-sysv.internal.h" -#include "libc/dce.h" -#include "libc/errno.h" -#include "libc/intrin/asan.internal.h" -#include "libc/intrin/asmflag.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/describeflags.internal.h" -#include "libc/intrin/strace.internal.h" -#include "libc/nexgen32e/msr.internal.h" -#include "libc/nexgen32e/x86feature.h" -#include "libc/runtime/pc.internal.h" -#include "libc/sysv/consts/sig.h" -#include "libc/sysv/errfuns.h" -#ifdef __x86_64__ - -#define rdmsr(msr) \ - ({ \ - uint32_t lo, hi; \ - asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); \ - (uint64_t) hi << 32 | lo; \ - }) - -#define wrmsr(msr, val) \ - do { \ - uint64_t val_ = (val); \ - asm volatile("wrmsr" \ - : /* no outputs */ \ - : "c"(msr), "a"((uint32_t)val_), \ - "d"((uint32_t)(val_ >> 32))); \ - } while (0) - -int sys_set_tls(); - -static int arch_prctl_msr(int code, int64_t addr) { - switch (code) { - case ARCH_SET_GS: - wrmsr(MSR_IA32_GS_BASE, addr); - return 0; - case ARCH_SET_FS: - wrmsr(MSR_IA32_FS_BASE, addr); - return 0; - case ARCH_GET_GS: - *(int64_t *)addr = rdmsr(MSR_IA32_GS_BASE); - return 0; - case ARCH_GET_FS: - *(int64_t *)addr = rdmsr(MSR_IA32_FS_BASE); - return 0; - default: - return einval(); - } -} - -static int arch_prctl_freebsd(int code, int64_t addr) { - switch (code) { - case ARCH_GET_FS: - // sysarch(AMD64_GET_FSBASE) - return sys_arch_prctl(128, addr); - case ARCH_SET_FS: - // sysarch(AMD64_SET_FSBASE) - return sys_arch_prctl(129, (intptr_t)&addr); - case ARCH_GET_GS: - // sysarch(AMD64_GET_GSBASE) - return sys_arch_prctl(130, addr); - case ARCH_SET_GS: - // sysarch(AMD64_SET_GSBASE) - return sys_arch_prctl(131, (intptr_t)&addr); - default: - return einval(); - } -} - -static int arch_prctl_netbsd(int code, int64_t addr) { - switch (code) { - case ARCH_GET_FS: - // sysarch(X86_GET_FSBASE) - return sys_arch_prctl(15, addr); - case ARCH_SET_FS: - // we use _lwp_setprivate() instead of sysarch(X86_SET_FSBASE) - // because the latter has a bug where signal handlers cause it - // to be clobbered. please note, this doesn't apply to %gs :-) - return sys_set_tls(addr); - case ARCH_GET_GS: - // sysarch(X86_GET_GSBASE) - return sys_arch_prctl(14, addr); - case ARCH_SET_GS: - // sysarch(X86_SET_GSBASE) - return sys_arch_prctl(16, (intptr_t)&addr); - default: - return einval(); - } -} - -static int arch_prctl_xnu(int code, int64_t addr) { - int e; - switch (code) { - case ARCH_SET_GS: - // thread_fast_set_cthread_self has a weird ABI - e = errno; - sys_set_tls(addr); - errno = e; - return 0; - case ARCH_GET_FS: - case ARCH_SET_FS: - case ARCH_GET_GS: - return enosys(); - default: - return einval(); - } -} - -static dontinline int arch_prctl_openbsd(int code, int64_t addr) { - bool failed; - int64_t rax; - switch (code) { - case ARCH_GET_FS: - asm volatile(CFLAG_ASM("syscall") - : CFLAG_CONSTRAINT(failed), "=a"(rax) - : "1"(0x014a /* __get_tcb */) - : "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "cc", - "memory"); - if (failed) { - errno = rax; - return -1; - } - *(int64_t *)addr = rax; - return 0; - case ARCH_SET_FS: - asm volatile(CFLAG_ASM("syscall") - : CFLAG_CONSTRAINT(failed), "=a"(rax) - : "1"(0x0149 /* __set_tcb */), "D"(addr) - : "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "cc", - "memory"); - if (failed) { - errno = rax; - rax = -1; - } - return rax; - case ARCH_GET_GS: - case ARCH_SET_GS: - return enosys(); - default: - return einval(); - } -} - -/** - * Changes x86 segment registers. - * - * Support for segment registers is spotty across platforms. See the - * table of tested combinations below. - * - * This wrapper has the same weird ABI as the Linux Kernel. The type - * Cosmopolitan type signature of the prototype for this function is - * variadic, so no value safety checking will be performed w/o asan. - * - * Cosmopolitan Libc initializes your process by default, to use the - * segment register %fs, for thread-local storage. To safely disable - * this TLS you need to either set `__tls_enabled` to 0, or you must - * follow the same memory layout assumptions as your C library. When - * TLS is disabled you can't use threads unless you call clone() and - * that's not really a good idea since `errno` won't be thread-safe. - * - * Please note if you're only concerned about running on Linux, then - * consider using Cosmopolitan's fsgsbase macros which don't need to - * issue system calls to change %fs and %gs. See _have_fsgsbase() to - * learn more. - * - * @param code may be - * - `ARCH_SET_FS` works on Linux, FreeBSD, NetBSD, OpenBSD, Metal - * - `ARCH_GET_FS` works on Linux, FreeBSD, NetBSD, OpenBSD, Metal - * - `ARCH_SET_GS` works on Linux, FreeBSD, NetBSD, XNU, Metal - * - `ARCH_GET_GS` works on Linux, FreeBSD, NetBSD, Metal - * @param addr is treated as `intptr_t` when setting a register, and - * is an output parameter (i.e. `intptr_t *`) when reading one - * @raise ENOSYS if operating system didn't support changing `code` - * @raise EINVAL if `code` wasn't valid - * @raise EFAULT if `ARCH_SET_FS` or `ARCH_SET_GS` was used and memory - * pointed to by `addr` was invalid - * @see _have_fsgsbase() - */ -int arch_prctl(int code, int64_t addr) { - int rc; - if (IsAsan() && // - (code == ARCH_GET_FS || // - code == ARCH_GET_GS) && // - !__asan_is_valid((int64_t *)addr, 8)) { - rc = efault(); - } else { - switch (__hostos) { - case _HOSTMETAL: - rc = arch_prctl_msr(code, addr); - break; - case _HOSTFREEBSD: - rc = arch_prctl_freebsd(code, addr); - break; - case _HOSTNETBSD: - rc = arch_prctl_netbsd(code, addr); - break; - case _HOSTOPENBSD: - rc = arch_prctl_openbsd(code, addr); - break; - case _HOSTLINUX: - rc = sys_arch_prctl(code, addr); - break; - case _HOSTXNU: - rc = arch_prctl_xnu(code, addr); - break; - default: - rc = enosys(); - break; - } - } -#ifdef SYSDEBUG - if (!rc && (code == ARCH_GET_FS || code == ARCH_GET_GS)) { - STRACE("arch_prctl(%s, [%p]) → %d% m", DescribeArchPrctlCode(code), - *(int64_t *)addr, rc); - } else { - STRACE("arch_prctl(%s, %p) → %d% m", DescribeArchPrctlCode(code), addr, rc); - } -#endif - return rc; -} - -#endif /* __x86_64__ */ diff --git a/libc/runtime/brk.c b/libc/runtime/brk.c deleted file mode 100644 index 0bcfc3b33..000000000 --- a/libc/runtime/brk.c +++ /dev/null @@ -1,186 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2021 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/assert.h" -#include "libc/calls/calls.h" -#include "libc/calls/syscall-sysv.internal.h" -#include "libc/dce.h" -#include "libc/intrin/directmap.internal.h" -#include "libc/intrin/nopl.internal.h" -#include "libc/intrin/strace.internal.h" -#include "libc/macros.internal.h" -#include "libc/runtime/brk.internal.h" -#include "libc/runtime/memtrack.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/consts/prot.h" -#include "libc/sysv/errfuns.h" -#include "libc/thread/thread.h" -#include "libc/thread/tls.h" - -struct Brk __brk; - -static bool OverlapsMmappedMemory(unsigned char *p, size_t n) { - int a, b, i; - _unassert(n); - a = (intptr_t)p >> 16; - b = (intptr_t)(p + n - 1) >> 16; - i = FindMemoryInterval(&_mmi, a); - if (i < _mmi.i) { - if (a <= _mmi.p[i].x && _mmi.p[i].x <= b) return true; - if (a <= _mmi.p[i].y && _mmi.p[i].y <= b) return true; - if (_mmi.p[i].x <= a && b <= _mmi.p[i].y) return true; - } - return false; -} - -static unsigned char *brk_unlocked(unsigned char *p) { - int rc; - struct DirectMap dm; - _unassert(!((intptr_t)__brk.p & (PAGESIZE - 1))); - if (p >= __brk.p) { - p = (unsigned char *)ROUNDUP((intptr_t)p, PAGESIZE); - } else { - p = (unsigned char *)ROUNDDOWN((intptr_t)p, PAGESIZE); - } - if (IsWindows()) { - rc = enosys(); - } else if (p < _end) { - rc = einval(); - } else if (p > __brk.p) { - if (!OverlapsMmappedMemory(__brk.p, p - __brk.p)) { - // we always polyfill this system call because - // 1. Linux has brk() but its behavior is poorly documented - // 2. FreeBSD has sbrk(int):int but it's foreseeable it could go away - // 3. XNU/OpenBSD/NetBSD have all deleted this interface in the kernel - dm = sys_mmap(__brk.p, p - __brk.p, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); - rc = (int)(intptr_t)dm.addr; // safe b/c __brk.p is page-aligned - } else { - rc = eexist(); - } - } else if (p < __brk.p) { - rc = sys_munmap(p, __brk.p - p); - } else { - rc = 0; - } - if (rc != -1) { - __brk.p = p; - return 0; - } else { - return (unsigned char *)-1; - } -} - -void brk_lock(void) { - pthread_mutex_lock(&__brk.m); -} - -void brk_unlock(void) { - pthread_mutex_unlock(&__brk.m); -} - -void brk_funlock(void) { - pthread_mutex_init(&__brk.m, 0); -} - -__attribute__((__constructor__)) static void brk_init(void) { - brk_funlock(); - pthread_atfork(brk_lock, brk_unlock, brk_funlock); -} - -#ifdef _NOPL0 -#define brk_lock() _NOPL0("__threadcalls", brk_lock) -#define brk_unlock() _NOPL0("__threadcalls", brk_unlock) -#endif - -/** - * Sets end of data section. - * - * Your program break starts right after end of `.bss` as defined - * by the external linker-defined variable `end`. Setting it to a - * higher address will allocate more memory. After using this you - * may dealocate memory by specifying it back to a lower address. - * - * The only virtue of brk(), and sbrk(), aside from compatibility - * with legacy software, is it's tinier than mmap() because since - * this API only supports Unix, we don't bother doing the complex - * memory interval tracking that mmap() does. - * - * @param neu is the new end address of data segment, which shall - * be rounded automatically to a 4096-byte granularity - * @return 0 on success, or -1 w/ errno - * @raise EINVAL if `neu` is less than the `end` of `.bss` - * @raise EEXIST if expanded break would overlap existing mmap() memory - * @raise ENOMEM if `RLIMIT_DATA` / `RLIMIT_AS` / `RLIMIT_RSS` is exceeded - * @raise ENOSYS on Windows because WIN32 puts random stuff after your break - * @threadsafe - */ -int brk(void *neu) { - unsigned char *rc; - brk_lock(); - if (!__brk.p) __brk.p = _end; - rc = brk_unlocked(neu); - brk_unlock(); - STRACE("brk(%p) → %d% m", neu, rc); - return (int)(intptr_t)rc; -} - -/** - * Adjusts end of data section. - * - * This shrinks or increases the program break by delta bytes. On - * success, the previous program break is returned. It's possible - * to pass 0 to this function to obtain the current program break - * which is initially set to the linker-defined external variable - * `end` which is the end of the `.bss` segment. Your allocations - * are rounded automatically to a 4096-byte granularity. - * - * The only virtue of sbrk(), and brk(), aside from compatibility - * with legacy software, is it's tinier than mmap() because since - * this API only supports Unix, we don't bother doing the complex - * memory interval tracking that mmap() does. - * - * @param delta is the number of bytes to allocate (or free if negative) - * noting that your delta may be tuned to a number further from zero - * to accommodate the page size granularity of this allocator - * @return previous break on success, or `(void *)-1` w/ errno - * @raise EINVAL if new break would be less than the `end` of `.bss` - * @raise EEXIST if expanded break would overlap existing mmap() memory - * @raise EOVERFLOW if `delta` added to break overflows the address space - * @raise ENOMEM if `RLIMIT_DATA` / `RLIMIT_AS` / `RLIMIT_RSS` is exceeded - * @raise ENOSYS on Windows because WIN32 puts random stuff after your break - * @threadsafe - */ -void *sbrk(intptr_t delta) { - intptr_t neu; - unsigned char *rc, *old; - brk_lock(); - if (!__brk.p) __brk.p = _end; - old = __brk.p; - if (!__builtin_add_overflow((intptr_t)__brk.p, delta, &neu) && - IsLegalPointer((unsigned char *)neu)) { - rc = brk_unlocked((unsigned char *)neu); - if (!rc) rc = old; - } else { - rc = (void *)eoverflow(); - } - brk_unlock(); - STRACE("sbrk(%'ld) → %p% m", delta, rc); - return rc; -} diff --git a/libc/runtime/brk.internal.h b/libc/runtime/brk.internal.h deleted file mode 100644 index 6f4af2e5d..000000000 --- a/libc/runtime/brk.internal.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_RUNTIME_BRK_INTERNAL_H_ -#define COSMOPOLITAN_LIBC_RUNTIME_BRK_INTERNAL_H_ -#include "libc/thread/thread.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct Brk { - unsigned char *p; - pthread_mutex_t m; -}; - -extern struct Brk __brk; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_RUNTIME_BRK_INTERNAL_H_ */ diff --git a/libc/runtime/ezmap.c b/libc/runtime/ezmap.c index 492114e9f..66a1f5228 100644 --- a/libc/runtime/ezmap.c +++ b/libc/runtime/ezmap.c @@ -31,7 +31,7 @@ _Hide int MapFileRead(const char *filename, struct MappedFile *mf) { mf->addr = MAP_FAILED; if ((mf->fd = open(filename, O_RDONLY)) != -1 && - (mf->size = getfiledescriptorsize(mf->fd)) < INT_MAX && + (mf->size = lseek(mf->fd, 0, SEEK_END)) < INT_MAX && (mf->addr = mf->size ? mmap(NULL, mf->size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, mf->fd, 0) : NULL) != MAP_FAILED) { diff --git a/libc/runtime/finddebugbinary.c b/libc/runtime/finddebugbinary.c index e38be9bb2..501bb4f82 100644 --- a/libc/runtime/finddebugbinary.c +++ b/libc/runtime/finddebugbinary.c @@ -78,8 +78,7 @@ const char *FindDebugBinary(void) { if ((n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) || IsMyDebugBinary(p)) { res = p; - } else if (n > 4 && READ32LE(p + n - 4) == READ32LE(".com") && - n + 4 < ARRAYLEN(buf)) { + } else if (n + 4 < ARRAYLEN(buf)) { mempcpy(mempcpy(buf, p, n), ".dbg", 5); if (IsMyDebugBinary(buf)) { res = buf; diff --git a/libc/runtime/mremap.c b/libc/runtime/mremap.c deleted file mode 100644 index 768b9a61f..000000000 --- a/libc/runtime/mremap.c +++ /dev/null @@ -1,208 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/sysv/consts/mremap.h" -#include "libc/assert.h" -#include "libc/calls/calls.h" -#include "libc/dce.h" -#include "libc/intrin/asan.internal.h" -#include "libc/intrin/describeflags.internal.h" -#include "libc/intrin/directmap.internal.h" -#include "libc/intrin/likely.h" -#include "libc/intrin/strace.internal.h" -#include "libc/intrin/weaken.h" -#include "libc/macros.internal.h" -#include "libc/nt/runtime.h" -#include "libc/runtime/memtrack.internal.h" -#include "libc/runtime/runtime.h" -#include "libc/sysv/consts/map.h" -#include "libc/sysv/errfuns.h" - -#define IP(X) (intptr_t)(X) -#define VIP(X) (void *)IP(X) -#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) -#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000) -#define FRAME(x) ((int)((intptr_t)(x) >> 16)) - -static size_t GetMapSize(size_t i, size_t *j) { - size_t n; - n = (size_t)(_mmi.p[i].y - _mmi.p[i].x + 1) << 16; - while (i + 1 < _mmi.i) { - if (_mmi.p[i + 1].x != _mmi.p[i].y + 1) break; - ++i; - n += (size_t)(_mmi.p[i].y - _mmi.p[i].x + 1) << 16; - } - *j = i; - return n; -} - -static bool MustMoveMap(intptr_t y, size_t j) { - return ADDR_32_TO_48(_mmi.p[j].y) + FRAMESIZE > y || - (j + 1 < _mmi.i && ADDR_32_TO_48(_mmi.p[j + 1].x) < y); -} - -/** - * Extends and/or relocates memory pages. - * - * @param p is old address - * @param n is old size - * @param m is new size - * @param f should have MREMAP_MAYMOVE and may have MAP_FIXED - * @param q is new address - */ -void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) { - enosys(); - return MAP_FAILED; - -#if 0 - va_list va; - void *res, *q; - if (f & MREMAP_FIXED) { - va_start(va, f); - q = va_arg(va, void *); - va_end(va); - } else { - q = 0; - } - enosys(); - res = MAP_FAILED; - STRACE("mremap(%p, %'zu, %'zu, %s, %p) → %p% m", p, n, m, - DescribeRemapFlags(f), q, res); - return res; - - // TODO(jart): perhaps some day? - // probably not a big perf gain at this point :| - size_t i, j, k; - struct DirectMap dm; - int a, b, prot, flags; - _unassert(!__vforked); - if (UNLIKELY(!m)) { - STRACE("m=0"); - return VIP(einval()); - } else if (UNLIKELY(!n)) { - STRACE("n=0"); - return VIP(eopnotsupp()); - } else if (UNLIKELY(!ALIGNED(n))) { - STRACE("n align"); - return VIP(eopnotsupp()); - } else if (UNLIKELY(!ALIGNED(m))) { - STRACE("n align"); - return VIP(eopnotsupp()); - } else if (UNLIKELY(!ALIGNED(p))) { - STRACE("64kb align"); - return VIP(einval()); - } else if (UNLIKELY(!IsLegalSize(n))) { - STRACE("n too big"); - return VIP(enomem()); - } else if (UNLIKELY(!IsLegalSize(m))) { - STRACE("m too big"); - return VIP(enomem()); - } else if (f & ~(MREMAP_MAYMOVE | MREMAP_FIXED)) { - STRACE("bad flag"); - return VIP(einval()); - } else if (!IsMemtracked(FRAME(p), FRAME((intptr_t)p + (n - 1)))) { - STRACE("interval not tracked"); - return VIP(efault()); - } - STRACE("mremap(%p, %'zu, %'zu, %#b)", p, n, m, f); - i = FindMemoryInterval(&_mmi, FRAME(p)); - if (i >= _mmi.i) return VIP(efault()); - flags = _mmi.p[i].flags; - if (!(flags & MAP_ANONYMOUS)) { - return VIP(eopnotsupp()); /* TODO */ - } - if (f & MREMAP_FIXED) { - if (!ALIGNED(q)) return VIP(einval()); - return VIP(eopnotsupp()); /* TODO */ - } - prot = _mmi.p[i].prot; - for (k = i + 1; k <= j; ++k) { - prot |= _mmi.p[k].prot; - if (_mmi.p[k].flags != flags) { - return VIP(enomem()); - } - } - if (m == n) { - return p; - } else if (m < n) { - if (munmap((char *)p + n, m - n) != -1) { - return p; - } else { - return MAP_FAILED; - } - } else if (!MustMoveMap(j, (intptr_t)p + n)) { - dm = sys_mmap((char *)p + n, m - n, prot, flags | MAP_FIXED, -1, 0); - if (dm.addr == MAP_FAILED) return 0; - if (TrackMemoryInterval(&_mmi, ((uintptr_t)p + n) >> 16, - ((uintptr_t)p + m - FRAMESIZE) >> 16, dm.maphandle, - prot, flags, false, false, 0, m - n) != -1) { - if (_weaken(__asan_map_shadow)) { - _weaken(__asan_map_shadow)((uintptr_t)dm.addr, m - n); - } - return p; - } else { - abort(); - } - } else if (!(f & MREMAP_MAYMOVE)) { - return VIP(enomem()); - } else if (IsLinux()) { - a = (uint32_t)(kAutomapStart >> 16); - i = FindMemoryInterval(&_mmi, a); - if (i < _mmi.i) { - for (; i + 1 < _mmi.i; ++i) { - if (((size_t)(_mmi.p[i + 1].x - _mmi.p[i].y - 1) << 16) >= m) { - break; - } - } - if (__builtin_add_overflow(_mmi.p[i].y, 1, &a)) { - return VIP(enomem()); - } - } - if (__builtin_add_overflow(a, (int)((m >> 16) - 1), &b)) { - return VIP(enomem()); - } - q = sys_mremap((void *)p, n, m, MREMAP_MAYMOVE | MREMAP_FIXED, - (void *)ADDR_32_TO_48(a)); - KERNTRACE("sys_mremap(%p, %'zu, %'zu, %#b, %p) → %p", p, n, m, - MREMAP_MAYMOVE | MREMAP_FIXED, ADDR_32_TO_48(a), q); - if (q == MAP_FAILED) return 0; - if (ReleaseMemoryIntervals(&_mmi, (uintptr_t)p >> 16, - ((uintptr_t)p + n - FRAMESIZE) >> 16, 0) != -1 && - TrackMemoryInterval(&_mmi, a, b, -1, prot, flags, false, false, 0, m) != - -1) { - if (_weaken(__asan_poison)) { - if (!OverlapsShadowSpace(p, n)) { - _weaken(__asan_poison)((intptr_t)p, n, kAsanUnmapped); - } - if (!OverlapsShadowSpace(q, m)) { - _weaken(__asan_map_shadow)((intptr_t)q, m); - } - } - return (void *)ADDR_32_TO_48(a); - } else { - abort(); - } - } else if ((q = mmap(0, m, prot, flags, -1, 0)) != MAP_FAILED) { - memcpy(q, p, n); - munmap(p, n); - return q; - } else { - return q; - } -#endif -} diff --git a/libc/runtime/opensymboltable.greg.c b/libc/runtime/opensymboltable.greg.c index 7c067fe4c..4bb858d6d 100644 --- a/libc/runtime/opensymboltable.greg.c +++ b/libc/runtime/opensymboltable.greg.c @@ -51,7 +51,7 @@ static struct SymbolTable *OpenSymbolTableImpl(const char *filename) { ptrdiff_t names_offset, name_base_offset, stp_offset; map = MAP_FAILED; if ((fd = open(filename, O_RDONLY)) == -1) return 0; - if ((filesize = getfiledescriptorsize(fd)) == -1) goto SystemError; + if ((filesize = lseek(fd, 0, SEEK_END)) == -1) goto SystemError; if (filesize > INT_MAX) goto RaiseE2big; if (filesize < 64) goto RaiseEnoexec; elf = map = mmap(0, filesize, PROT_READ, MAP_PRIVATE, fd, 0); diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 5bac430f8..a2df2632b 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -76,14 +76,11 @@ int unsetenv(const char *); int clearenv(void); void fpreset(void); void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t); -void *mremap(void *, size_t, size_t, int, ...); int munmap(void *, uint64_t); int mprotect(void *, uint64_t, int); int msync(void *, size_t, int); int mlock(const void *, size_t); int munlock(const void *, size_t); -void *sbrk(intptr_t); -int brk(void *); long gethostid(void); int sethostid(long); char *getlogin(void); diff --git a/libc/str/setlocale.c b/libc/str/setlocale.c index f2b3e4caf..eadf87ce1 100644 --- a/libc/str/setlocale.c +++ b/libc/str/setlocale.c @@ -29,7 +29,9 @@ */ char *setlocale(int category, const char *locale) { if (!locale || (*locale == '\0')) return "C"; - if (!strcmp(locale, "C") || !strcmp(locale, "POSIX")) { + if (!strcmp(locale, "C") || // + !strcmp(locale, "POSIX") || // + !strcmp(locale, "C.UTF-8")) { return locale; } else { return NULL; diff --git a/libc/str/unicode.h b/libc/str/unicode.h index 07bb280ff..c406a1cc9 100644 --- a/libc/str/unicode.h +++ b/libc/str/unicode.h @@ -32,9 +32,12 @@ struct lconv { int wcwidth(wchar_t) pureconst; int wcswidth(const wchar_t *, size_t) strlenesque; -int wcsnwidth(const wchar_t *, size_t, size_t) strlenesque; struct lconv *localeconv(void); +#ifdef COSMO +int wcsnwidth(const wchar_t *, size_t, size_t) strlenesque; +#endif + COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_STR_UNICODE_H_ */ diff --git a/libc/x/xslurp.c b/libc/x/xslurp.c index 1a1a85e6b..8c2edfeb2 100644 --- a/libc/x/xslurp.c +++ b/libc/x/xslurp.c @@ -38,7 +38,7 @@ void *xslurp(const char *path, size_t *opt_out_size) { ssize_t rc, size; res = NULL; if ((fd = open(path, O_RDONLY)) != -1) { - if ((size = getfiledescriptorsize(fd)) != -1 && + if ((size = lseek(fd, 0, SEEK_END)) != -1 && (res = memalign(PAGESIZE, size + 1))) { if (size > 2 * 1024 * 1024) { fadvise(fd, 0, size, MADV_SEQUENTIAL); @@ -47,7 +47,7 @@ void *xslurp(const char *path, size_t *opt_out_size) { TryAgain: if ((rc = pread(fd, res + i, size - i, i)) != -1) { if (!(got = rc)) { - if (getfiledescriptorsize(fd) == -1) { + if (lseek(fd, 0, SEEK_CUR) == -1) { abort(); // TODO(jart): what is this } } diff --git a/libc/zipos/get.c b/libc/zipos/get.c index 9789511fb..b59cf65f7 100644 --- a/libc/zipos/get.c +++ b/libc/zipos/get.c @@ -81,7 +81,7 @@ struct Zipos *__zipos_get(void) { fd = open(progpath, O_RDONLY); } if (fd != -1) { - if ((size = getfiledescriptorsize(fd)) != -1ul && + if ((size = lseek(fd, 0, SEEK_END)) != -1 && (map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) { if ((base = FindEmbeddedApe(map, size))) { size -= base - map; diff --git a/test/libc/mem/test.mk b/test/libc/mem/test.mk index 135ce3001..273827930 100644 --- a/test/libc/mem/test.mk +++ b/test/libc/mem/test.mk @@ -73,7 +73,6 @@ o/$(MODE)/test/libc/mem/prog/sock.o: \ libc/sock/sock.h \ libc/intrin/bswap.h \ libc/sysv/consts/af.h \ - libc/runtime/symbolic.h \ libc/sysv/consts/sock.h ################################################################################ diff --git a/test/libc/runtime/arch_prctl_test.c b/test/libc/runtime/arch_prctl_test.c deleted file mode 100644 index df8644e75..000000000 --- a/test/libc/runtime/arch_prctl_test.c +++ /dev/null @@ -1,131 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" -#include "libc/calls/struct/sigaction.h" -#include "libc/calls/syscall-sysv.internal.h" -#include "libc/dce.h" -#include "libc/errno.h" -#include "libc/intrin/fsgsbase.h" -#include "libc/intrin/kprintf.h" -#include "libc/intrin/segmentation.h" -#include "libc/nt/version.h" -#include "libc/sysv/consts/sa.h" -#include "libc/sysv/consts/sig.h" -#include "libc/testlib/testlib.h" -#include "libc/thread/tls.h" -#ifdef __x86_64__ - -void SetUpOnce(void) { - __tls_enabled_set(false); - ASSERT_SYS(0, 0, pledge("stdio rpath", 0)); -} - -void OnTrap(int sig, struct siginfo *si, void *vctx) { - struct ucontext *ctx = vctx; -} - -void TriggerSignal(void) { - struct sigaction old; - struct sigaction sig = {.sa_sigaction = OnTrap, .sa_flags = SA_SIGINFO}; - sched_yield(); - sigaction(SIGTRAP, &sig, &old); - asm("int3"); - sigaction(SIGTRAP, &old, 0); - sched_yield(); -} - -TEST(arch_prctl, fs) { - if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd()) { - uint64_t n, x; - x = 0xdeadbeef; - arch_prctl(ARCH_SET_FS, &x); - ASSERT_NE(-1, arch_prctl(ARCH_GET_FS, (intptr_t)&n)); - ASSERT_EQ((intptr_t)&x, n); - ASSERT_EQ(0xdeadbeef, fs((int64_t *)0)); - TriggerSignal(); - ASSERT_EQ(0xdeadbeef, fs((int64_t *)0)); - } -} - -TEST(arch_prctl, pointerRebasingFs) { - if (IsLinux() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) { - unsigned long s[] = {0x0706050403020100, 0x0f0e0d0c0b0a0908}; - ASSERT_EQ(0x0706050403020100, s[0]); - ASSERT_EQ(0, arch_prctl(ARCH_SET_FS, 1)); - ASSERT_EQ(0x0807060504030201, fs(&s[0])); - ASSERT_EQ(0, arch_prctl(ARCH_SET_FS, 2)); - ASSERT_EQ(0x0908070605040302, fs(&s[0])); - intptr_t fs; - ASSERT_EQ(0, arch_prctl(ARCH_GET_FS, &fs)); - ASSERT_EQ(2, fs); - } -} - -TEST(arch_prctl, gs) { - if (IsLinux() || IsFreebsd() || IsNetbsd() || IsXnu()) { - uint64_t n, x; - x = 0xdeadbeef; - arch_prctl(ARCH_SET_GS, &x); - if (!IsXnu()) { - ASSERT_NE(-1, arch_prctl(ARCH_GET_GS, (intptr_t)&n)); - ASSERT_EQ((intptr_t)&x, n); - } - ASSERT_EQ(0xdeadbeef, gs((int64_t *)0)); - TriggerSignal(); - ASSERT_EQ(0xdeadbeef, gs((int64_t *)0)); - } -} - -TEST(arch_prctl, pointerRebasing) { - if (IsLinux() || IsFreebsd() || IsNetbsd() || IsXnu()) { - unsigned long s[] = {0x0706050403020100, 0x0f0e0d0c0b0a0908}; - ASSERT_EQ(0x0706050403020100, s[0]); - ASSERT_EQ(0, arch_prctl(ARCH_SET_GS, 1)); - ASSERT_EQ(0x0807060504030201, gs(&s[0])); - ASSERT_EQ(0, arch_prctl(ARCH_SET_GS, 2)); - ASSERT_EQ(0x0908070605040302, gs(&s[0])); - if (!IsXnu()) { - intptr_t gs; - ASSERT_EQ(0, arch_prctl(ARCH_GET_GS, &gs)); - ASSERT_EQ(2, gs); - } - } -} - -TEST(fsgsbase, fs) { - if (!_have_fsgsbase()) return; - int64_t mem = 0xdeadbeef; - _wrfsbase(&mem); - ASSERT_EQ(&mem, _rdfsbase()); - ASSERT_EQ(0xdeadbeef, fs((int64_t *)0)); - TriggerSignal(); - ASSERT_EQ(0xdeadbeef, fs((int64_t *)0)); -} - -TEST(fsgsbase, gs) { - if (!_have_fsgsbase()) return; - int64_t mem = 0xdeadbeef; - _wrgsbase(&mem); - ASSERT_EQ(&mem, _rdgsbase()); - ASSERT_EQ(0xdeadbeef, gs((int64_t *)0)); - TriggerSignal(); - ASSERT_EQ(0xdeadbeef, gs((int64_t *)0)); -} - -#endif /* __x86_64__ */ diff --git a/third_party/make/main.c b/third_party/make/main.c index d4076199c..5a91ac8c4 100644 --- a/third_party/make/main.c +++ b/third_party/make/main.c @@ -636,13 +636,11 @@ expand_command_line_file (const char *name) /* Toggle -d on receipt of SIGUSR1. */ -#ifdef SIGUSR1 static RETSIGTYPE debug_signal_handler (int sig UNUSED) { db_level = db_level ? DB_NONE : DB_BASIC; } -#endif static void decode_debug_flags (void) @@ -1609,9 +1607,7 @@ main (int argc, char **argv, char **envp) #endif /* Let the user send us SIGUSR1 to toggle the -d flag during the run. */ -#ifdef SIGUSR1 bsd_signal (SIGUSR1, debug_signal_handler); -#endif /* Define the initial list of suffixes for old-style rules. */ set_default_suffixes (); diff --git a/tool/plinko/lib/lib.mk b/tool/plinko/lib/lib.mk index 7a661d9ea..245677d9e 100644 --- a/tool/plinko/lib/lib.mk +++ b/tool/plinko/lib/lib.mk @@ -38,6 +38,7 @@ TOOL_PLINKO_LIB_A_DIRECTDEPS = \ LIBC_STR \ LIBC_STUBS \ LIBC_SYSV \ + LIBC_SYSV_CALLS \ THIRD_PARTY_COMPILER_RT \ THIRD_PARTY_GETOPT diff --git a/tool/plinko/lib/plinko.c b/tool/plinko/lib/plinko.c index db33560de..a34c94d29 100644 --- a/tool/plinko/lib/plinko.c +++ b/tool/plinko/lib/plinko.c @@ -16,8 +16,10 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "tool/plinko/lib/plinko.h" #include "libc/calls/calls.h" #include "libc/calls/struct/sigaction.h" +#include "libc/calls/syscall-sysv.internal.h" #include "libc/errno.h" #include "libc/intrin/likely.h" #include "libc/intrin/strace.internal.h" @@ -43,7 +45,6 @@ #include "tool/plinko/lib/gc.h" #include "tool/plinko/lib/histo.h" #include "tool/plinko/lib/index.h" -#include "tool/plinko/lib/plinko.h" #include "tool/plinko/lib/print.h" #include "tool/plinko/lib/printf.h" #include "tool/plinko/lib/stack.h" @@ -935,8 +936,8 @@ int Plinko(int argc, char *argv[]) { } } - if (arch_prctl(ARCH_SET_FS, 0x200000000000) == -1 || - arch_prctl(ARCH_SET_GS, (intptr_t)DispatchPlan) == -1) { + if (sys_arch_prctl(ARCH_SET_FS, 0x200000000000) == -1 || + sys_arch_prctl(ARCH_SET_GS, (intptr_t)DispatchPlan) == -1) { fputs("error: ", stderr); fputs(strerror(errno), stderr); fputs("\nyour operating system doesn't allow you change both "