diff --git a/Makefile b/Makefile index d79899489..1580df774 100644 --- a/Makefile +++ b/Makefile @@ -269,7 +269,7 @@ CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS)) bins: $(BINS) check: $(CHECKS) -test: $(TESTS) aarch64 +test: $(TESTS) depend: o/$(MODE)/depend tags: TAGS HTAGS diff --git a/examples/greenbean.c b/examples/greenbean.c index 148203a72..7641ba57e 100644 --- a/examples/greenbean.c +++ b/examples/greenbean.c @@ -176,7 +176,7 @@ void *Worker(void *id) { // inherited by the accepted sockets, but using them also has the // side-effect that the listening socket fails with EAGAIN, every // several seconds. we can use that to our advantage to check for - // the ctrl-c shutdowne event; otherwise, we retry the accept call + // the ctrl-c shutdowne event; otherwise we retry the accept call continue; } diff --git a/libc/calls/close.c b/libc/calls/close.c index d3d30fc3a..4617184e9 100644 --- a/libc/calls/close.c +++ b/libc/calls/close.c @@ -91,6 +91,6 @@ int close(int fd) { __releasefd(fd); } } - STRACE("%s(%d) → %d% m", "close", fd, rc); + STRACE("close(%d) → %d% m", fd, rc); return rc; } diff --git a/libc/calls/internal.h b/libc/calls/internal.h index 871cc3007..d6a44a5d8 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -34,14 +34,6 @@ forceinline bool __isfdkind(int fd, int kind) { return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind == kind; } -forceinline size_t _clampio(size_t size) { - if (!IsTrustworthy()) { - return MIN(size, 0x7ffff000); - } else { - return size; - } -} - int sys_close_nt(struct Fd *, int) _Hide; int _check_interrupts(bool, struct Fd *) _Hide; int sys_openat_metal(int, const char *, int, unsigned); diff --git a/libc/calls/offset2overlap.c b/libc/calls/offset2overlap.c deleted file mode 100644 index 0b5eb2961..000000000 --- a/libc/calls/offset2overlap.c +++ /dev/null @@ -1,29 +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/nt/struct/overlapped.h" -#include "libc/str/str.h" - -textwindows struct NtOverlapped *_offset2overlap(int64_t handle, - int64_t opt_offset, - struct NtOverlapped *mem) { - if (opt_offset == -1) return NULL; - bzero(mem, sizeof(struct NtOverlapped)); - mem->Pointer = (void *)(uintptr_t)opt_offset; - return mem; -} diff --git a/libc/calls/read-nt.c b/libc/calls/read-nt.c index d25f2c4c9..23c411b12 100644 --- a/libc/calls/read-nt.c +++ b/libc/calls/read-nt.c @@ -26,6 +26,7 @@ #include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/wincrash.internal.h" #include "libc/intrin/strace.internal.h" +#include "libc/macros.internal.h" #include "libc/nt/enum/filetype.h" #include "libc/nt/errors.h" #include "libc/nt/files.h" @@ -37,13 +38,10 @@ #include "libc/sysv/errfuns.h" static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data, - size_t size, ssize_t offset) { - bool32 ok; - int64_t p; - uint32_t got, avail; - struct NtOverlapped overlap; + size_t size, int64_t offset) { - // our terrible polling mechanism + // try to poll rather than block + uint32_t avail; if (GetFileType(fd->handle) == kNtFileTypePipe) { for (;;) { if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break; @@ -63,19 +61,28 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data, POLLTRACE("sys_read_nt ready to read"); } - if (offset != -1) { - // windows changes the file pointer even if overlapped is passed - _npassert(SetFilePointerEx(fd->handle, 0, &p, SEEK_CUR)); + // perform the read i/o operation + bool32 ok; + uint32_t got; + size = MIN(size, 0x7ffff000); + if (offset == -1) { + // perform simple blocking read + ok = ReadFile(fd->handle, data, size, &got, 0); + } else { + // perform pread()-style read at particular file offset + int64_t position; + // save file pointer which windows clobbers, even for overlapped i/o + if (!SetFilePointerEx(fd->handle, 0, &position, SEEK_CUR)) { + return __winerr(); // fd probably isn't seekable? + } + struct NtOverlapped overlap = {0}; + overlap.Pointer = (void *)(uintptr_t)offset; + ok = ReadFile(fd->handle, data, size, 0, &overlap); + if (!ok && GetLastError() == kNtErrorIoPending) ok = true; + if (ok) ok = GetOverlappedResult(fd->handle, &overlap, &got, true); + // restore file pointer which windows clobbers, even on error + _unassert(SetFilePointerEx(fd->handle, position, 0, SEEK_SET)); } - - ok = ReadFile(fd->handle, data, _clampio(size), &got, - _offset2overlap(fd->handle, offset, &overlap)); - - if (offset != -1) { - // windows clobbers file pointer even on error - _npassert(SetFilePointerEx(fd->handle, p, 0, SEEK_SET)); - } - if (ok) { return got; } @@ -93,7 +100,7 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data, } textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov, - size_t iovlen, ssize_t opt_offset) { + size_t iovlen, int64_t opt_offset) { ssize_t rc; uint32_t size; size_t i, total; diff --git a/libc/calls/struct/iovec.internal.h b/libc/calls/struct/iovec.internal.h index bbec95b22..a5048940a 100644 --- a/libc/calls/struct/iovec.internal.h +++ b/libc/calls/struct/iovec.internal.h @@ -13,7 +13,7 @@ int64_t sys_vmsplice(int, const struct iovec *, int64_t, uint32_t) _Hide; int64_t sys_writev(int32_t, const struct iovec *, int32_t) _Hide; size_t __iovec_size(const struct iovec *, size_t) _Hide; ssize_t WritevUninterruptible(int, struct iovec *, int); -ssize_t sys_read_nt(struct Fd *, const struct iovec *, size_t, ssize_t) _Hide; +ssize_t sys_read_nt(struct Fd *, const struct iovec *, size_t, int64_t) _Hide; ssize_t sys_readv_metal(struct Fd *, const struct iovec *, int) _Hide; ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) _Hide; ssize_t sys_readv_serial(struct Fd *, const struct iovec *, int) _Hide; diff --git a/libc/calls/wincrash.internal.h b/libc/calls/wincrash.internal.h index 211c15b97..9f3ceb638 100644 --- a/libc/calls/wincrash.internal.h +++ b/libc/calls/wincrash.internal.h @@ -1,13 +1,10 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_WINCRASH_INTERNAL_H_ #define COSMOPOLITAN_LIBC_CALLS_WINCRASH_INTERNAL_H_ #include "libc/nt/struct/ntexceptionpointers.h" -#include "libc/nt/struct/overlapped.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ unsigned __wincrash_nt(struct NtExceptionPointers *); -struct NtOverlapped *_offset2overlap(int64_t, int64_t, - struct NtOverlapped *) _Hide; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/calls/write-nt.c b/libc/calls/write-nt.c index f1454bbdc..c2c4e5e89 100644 --- a/libc/calls/write-nt.c +++ b/libc/calls/write-nt.c @@ -16,20 +16,20 @@ │ 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/internal.h" #include "libc/calls/sig.internal.h" -#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.internal.h" #include "libc/calls/syscall_support-nt.internal.h" -#include "libc/calls/wincrash.internal.h" #include "libc/errno.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" +#include "libc/macros.internal.h" #include "libc/nt/errors.h" #include "libc/nt/files.h" #include "libc/nt/runtime.h" -#include "libc/runtime/internal.h" +#include "libc/nt/struct/overlapped.h" #include "libc/runtime/runtime.h" #include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/sig.h" @@ -37,26 +37,31 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size, ssize_t offset) { + + // perform the write i/o operation bool32 ok; - int64_t h, p; - uint32_t err, sent; - struct NtOverlapped overlap; - - h = g_fds.p[fd].handle; - - if (offset != -1) { - // windows changes the file pointer even if overlapped is passed - SetFilePointerEx(h, 0, &p, SEEK_CUR); + uint32_t sent; + int64_t handle; + handle = g_fds.p[fd].handle; + size = MIN(size, 0x7ffff000); + if (offset == -1) { + // perform simple blocking write + ok = WriteFile(handle, data, size, &sent, 0); + } else { + // perform pwrite()-style write at particular file offset + int64_t position; + // save file pointer which windows clobbers, even for overlapped i/o + if (!SetFilePointerEx(handle, 0, &position, SEEK_CUR)) { + return __winerr(); // fd probably isn't seekable? + } + struct NtOverlapped overlap = {0}; + overlap.Pointer = (void *)(uintptr_t)offset; + ok = WriteFile(handle, data, size, 0, &overlap); + if (!ok && GetLastError() == kNtErrorIoPending) ok = true; + if (ok) ok = GetOverlappedResult(handle, &overlap, &sent, true); + // restore file pointer which windows clobbers, even on error + _unassert(SetFilePointerEx(handle, position, 0, SEEK_SET)); } - - ok = WriteFile(h, data, _clampio(size), &sent, - _offset2overlap(h, offset, &overlap)); - - if (offset != -1) { - // windows clobbers file pointer even on error - SetFilePointerEx(h, p, 0, SEEK_SET); - } - if (ok) { return sent; } @@ -86,8 +91,6 @@ textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen, ssize_t opt_offset) { ssize_t rc; size_t i, total; - uint32_t size, wrote; - struct NtOverlapped overlap; if (opt_offset < -1) return einval(); while (iovlen && !iov[0].iov_len) iov++, iovlen--; if (iovlen) { diff --git a/libc/errno.h b/libc/errno.h index 745ed5222..9a8683469 100644 --- a/libc/errno.h +++ b/libc/errno.h @@ -4,25 +4,35 @@ COSMOPOLITAN_C_START_ /** - * @fileoverview System error codes. - * @see libc/sysv/consts.sh for numbers + * @fileoverview System Five error codes. + * + * This file defines the `errno` global variable. When system calls + * (e.g. read(), write(), etc.) fail they return -1 to indicate the + * failure, and that is *the only* error return value. System calls + * also update `errno` too whenever -1 is returned (otherwise errno + * isn't changed) to be a non-zero value holding one of the numbers + * below, in order to indicate why the system call failed. + * + * There is only one exception to the above rule; some system calls + * are documented with the `@returnserrno` tag, which means they'll + * return the error number rather than stuffing it in a global. You + * can usually spot these system calls easily since most of them'll + * have names like `posix_foo()` or `pthread_bar()`. + * + * @see libc/sysv/consts.sh for assigned numbers + * @see libc/sysv/dos2errno.sh for multimapped numbers */ -#if defined(__GNUC__) && defined(__x86_64__) && defined(__MNO_RED_ZONE__) && \ - !defined(__STRICT_ANSI__) && !defined(__cplusplus) -#define errno \ - (*({ \ - errno_t *_ep; \ - asm("call\t__errno_location" : "=a"(_ep) : /* no inputs */ : "cc"); \ - _ep; \ - })) -#elif defined(__GNUC__) && defined(__aarch64__) && \ - !defined(__STRICT_ANSI__) && !defined(__cplusplus) -#define errno \ - (*({ \ - errno_t *_ep; \ - asm("sub\t%0,x28,#1092" : "=r"(_ep)); \ - _ep; \ +#if defined(__GNUC__) && defined(__aarch64__) && !defined(__STRICT_ANSI__) && \ + !defined(__cplusplus) +/* this header is included by 700+ files; therefore we */ +/* hand-roll &__get_tls()->tib_errno to avoid #include */ +/* cosmopolitan uses x28 as the tls register b/c apple */ +#define errno \ + (*({ \ + errno_t *__ep; \ + asm("sub\t%0,x28,#1092" : "=r"(__ep)); \ + __ep; \ })) #else #define errno (*__errno_location()) @@ -493,7 +503,7 @@ extern const errno_t ENOMEDIUM; extern const errno_t EMEDIUMTYPE; /** - * Inappropriate file type or format. (BSD only) + * Inappropriate file type or format. */ extern const errno_t EFTYPE; @@ -513,7 +523,6 @@ extern const errno_t EPROGUNAVAIL; extern const errno_t EPWROFF; extern const errno_t ERPCMISMATCH; extern const errno_t ESHLIBVERS; - extern const errno_t EADV; extern const errno_t EBADE; extern const errno_t EBADFD; @@ -558,35 +567,20 @@ extern const errno_t EXFULL; #define EACCES EACCES #define EADDRINUSE EADDRINUSE #define EADDRNOTAVAIL EADDRNOTAVAIL -#define EADV EADV #define EAFNOSUPPORT EAFNOSUPPORT #define EAGAIN EAGAIN #define EALREADY EALREADY -#define EAUTH EAUTH -#define EBADARCH EBADARCH -#define EBADE EBADE -#define EBADEXEC EBADEXEC #define EBADF EBADF -#define EBADFD EBADFD -#define EBADMACHO EBADMACHO #define EBADMSG EBADMSG -#define EBADR EBADR -#define EBADRPC EBADRPC -#define EBADRQC EBADRQC -#define EBADSLT EBADSLT #define EBUSY EBUSY #define ECANCELED ECANCELED #define ECHILD ECHILD -#define ECHRNG ECHRNG -#define ECOMM ECOMM #define ECONNABORTED ECONNABORTED #define ECONNREFUSED ECONNREFUSED #define ECONNRESET ECONNRESET #define EDEADLK EDEADLK #define EDESTADDRREQ EDESTADDRREQ -#define EDEVERR EDEVERR #define EDOM EDOM -#define EDOTDOT EDOTDOT #define EDQUOT EDQUOT #define EEXIST EEXIST #define EFAULT EFAULT @@ -594,7 +588,6 @@ extern const errno_t EXFULL; #define EFTYPE EFTYPE #define EHOSTDOWN EHOSTDOWN #define EHOSTUNREACH EHOSTUNREACH -#define EHWPOISON EHWPOISON #define EIDRM EIDRM #define EILSEQ EILSEQ #define EINPROGRESS EINPROGRESS @@ -603,20 +596,6 @@ extern const errno_t EXFULL; #define EIO EIO #define EISCONN EISCONN #define EISDIR EISDIR -#define EISNAM EISNAM -#define EKEYEXPIRED EKEYEXPIRED -#define EKEYREJECTED EKEYREJECTED -#define EKEYREVOKED EKEYREVOKED -#define EL2HLT EL2HLT -#define EL2NSYNC EL2NSYNC -#define EL3HLT EL3HLT -#define EL3RST EL3RST -#define ELIBACC ELIBACC -#define ELIBBAD ELIBBAD -#define ELIBEXEC ELIBEXEC -#define ELIBMAX ELIBMAX -#define ELIBSCN ELIBSCN -#define ELNRNG ELNRNG #define ELOOP ELOOP #define EMEDIUMTYPE EMEDIUMTYPE #define EMFILE EMFILE @@ -624,29 +603,21 @@ extern const errno_t EXFULL; #define EMSGSIZE EMSGSIZE #define EMULTIHOP EMULTIHOP #define ENAMETOOLONG ENAMETOOLONG -#define ENAVAIL ENAVAIL -#define ENEEDAUTH ENEEDAUTH #define ENETDOWN ENETDOWN #define ENETRESET ENETRESET #define ENETUNREACH ENETUNREACH #define ENFILE ENFILE -#define ENOANO ENOANO -#define ENOATTR ENOATTR #define ENOBUFS ENOBUFS -#define ENOCSI ENOCSI #define ENODATA ENODATA #define ENODEV ENODEV #define ENOENT ENOENT #define ENOEXEC ENOEXEC -#define ENOKEY ENOKEY #define ENOLCK ENOLCK #define ENOLINK ENOLINK #define ENOMEDIUM ENOMEDIUM #define ENOMEM ENOMEM #define ENOMSG ENOMSG #define ENONET ENONET -#define ENOPKG ENOPKG -#define ENOPOLICY ENOPOLICY #define ENOPROTOOPT ENOPROTOOPT #define ENOSPC ENOSPC #define ENOSR ENOSR @@ -656,12 +627,10 @@ extern const errno_t EXFULL; #define ENOTCONN ENOTCONN #define ENOTDIR ENOTDIR #define ENOTEMPTY ENOTEMPTY -#define ENOTNAM ENOTNAM #define ENOTRECOVERABLE ENOTRECOVERABLE #define ENOTSOCK ENOTSOCK #define ENOTSUP ENOTSUP #define ENOTTY ENOTTY -#define ENOTUNIQ ENOTUNIQ #define ENXIO ENXIO #define EOPNOTSUPP EOPNOTSUPP #define EOVERFLOW EOVERFLOW @@ -669,43 +638,28 @@ extern const errno_t EXFULL; #define EPERM EPERM #define EPFNOSUPPORT EPFNOSUPPORT #define EPIPE EPIPE -#define EPROCLIM EPROCLIM -#define EPROCUNAVAIL EPROCUNAVAIL -#define EPROGMISMATCH EPROGMISMATCH -#define EPROGUNAVAIL EPROGUNAVAIL #define EPROTO EPROTO #define EPROTONOSUPPORT EPROTONOSUPPORT #define EPROTOTYPE EPROTOTYPE -#define EPWROFF EPWROFF #define ERANGE ERANGE -#define EREMCHG EREMCHG #define EREMOTE EREMOTE -#define EREMOTEIO EREMOTEIO #define ERESTART ERESTART -#define ERFKILL ERFKILL #define EROFS EROFS -#define ERPCMISMATCH ERPCMISMATCH -#define ESHLIBVERS ESHLIBVERS #define ESHUTDOWN ESHUTDOWN #define ESOCKTNOSUPPORT ESOCKTNOSUPPORT #define ESPIPE ESPIPE #define ESRCH ESRCH -#define ESRMNT ESRMNT #define ESTALE ESTALE -#define ESTRPIPE ESTRPIPE #define ETIME ETIME #define ETIMEDOUT ETIMEDOUT #define ETOOMANYREFS ETOOMANYREFS #define ETXTBSY ETXTBSY -#define EUCLEAN EUCLEAN -#define EUNATCH EUNATCH #define EUSERS EUSERS #define EWOULDBLOCK EAGAIN #define EXDEV EXDEV -#define EXFULL EXFULL extern errno_t __errno; -errno_t *__errno_location(void); +errno_t *__errno_location(void) dontthrow pureconst; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/nt/master.sh b/libc/nt/master.sh index 9b6de9275..d3d1cbce7 100755 --- a/libc/nt/master.sh +++ b/libc/nt/master.sh @@ -3298,6 +3298,7 @@ imp 'WSCWriteNameSpaceOrder32' WSCWriteNameSpaceOrder32 ws2_32 162 imp 'WSCWriteProviderOrder' WSCWriteProviderOrder ws2_32 163 imp 'WSCWriteProviderOrder32' WSCWriteProviderOrder32 ws2_32 164 imp 'WSCWriteProviderOrderEx' WSCWriteProviderOrderEx ws2_32 165 +imp '__sys_socket_nt' socket ws2_32 0 3 imp '__sys_accept_nt' accept ws2_32 1 3 # we're using WSAAccept() imp '__sys_bind_nt' bind ws2_32 2 3 imp '__sys_closesocket_nt' closesocket ws2_32 3 1 diff --git a/libc/runtime/fork-nt.c b/libc/runtime/fork-nt.c index fed4583ee..e0ee91e3c 100644 --- a/libc/runtime/fork-nt.c +++ b/libc/runtime/fork-nt.c @@ -51,6 +51,7 @@ #include "libc/runtime/internal.h" #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" +#include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/o.h" @@ -349,14 +350,20 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) { } } else { rc = 0; + // re-apply code morphing for thread-local storage if (tib && _weaken(__set_tls) && _weaken(__morph_tls)) { _weaken(__set_tls)(tib); _weaken(__morph_tls)(); __tls_enabled_set(true); } + // re-apply code morphing for synchronization nops if (threaded && !__threaded && _weaken(__enable_threads)) { _weaken(__enable_threads)(); } + // re-apply code morphing for function tracing + if (ftrace_stackdigs) { + _weaken(__hook)(_weaken(ftrace_hook), _weaken(GetSymbolTable)()); + } } if (untrackpid != -1) { __releasefd(untrackpid); diff --git a/libc/runtime/ftrace-hook.S b/libc/runtime/ftrace-hook.S index af12bcc67..84dbca1ac 100644 --- a/libc/runtime/ftrace-hook.S +++ b/libc/runtime/ftrace-hook.S @@ -119,4 +119,4 @@ ftrace_hook: 1: ret #endif /* __x86_64__ */ - .endfn ftrace_hook,globl + .endfn ftrace_hook,globl,hidden diff --git a/libc/runtime/ftrace_install.c b/libc/runtime/ftrace_install.c index e3dbeb82f..15e536d0a 100644 --- a/libc/runtime/ftrace_install.c +++ b/libc/runtime/ftrace_install.c @@ -23,8 +23,6 @@ #include "libc/runtime/stack.h" #include "libc/runtime/symbols.internal.h" -void ftrace_hook(void); - textstartup int ftrace_install(void) { if (GetSymbolTable()) { ftrace_stackdigs = LengthInt64Thousands(GetStackSize()); diff --git a/libc/runtime/internal.h b/libc/runtime/internal.h index afcb789b9..870ebcfc5 100644 --- a/libc/runtime/internal.h +++ b/libc/runtime/internal.h @@ -33,6 +33,7 @@ extern unsigned char _tls_content[] __attribute__((__weak__)); void _init(void) _Hide; int ftrace_init(void) _Hide; +void ftrace_hook(void) _Hide; void __morph_tls(void) _Hide; void __enable_tls(void) _Hide; void __enable_threads(void) _Hide; diff --git a/libc/runtime/morph.greg.c b/libc/runtime/morph.greg.c index 22082ca65..538b91ba7 100644 --- a/libc/runtime/morph.greg.c +++ b/libc/runtime/morph.greg.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #define ShouldUseMsabiAttribute() 1 #include "ape/sections.internal.h" +#include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/struct/sigset.h" #include "libc/dce.h" @@ -36,24 +37,7 @@ __msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect; -#ifdef __aarch64__ -static privileged void __aarch64_sigprocmask(int how, const sigset_t *set, - sigset_t *oldset) { - register int r0 asm("x0") = how; - register long r1 asm("x1") = (long)set; - register long r2 asm("x2") = (long)oldset; - register long r3 asm("x3") = 8; - register long r8 asm("x8") = __NR_sigprocmask; - register long r16 asm("x16") = __NR_sigprocmask; - asm volatile("svc\t0" - : "+r"(r0) - : "r"(r1), "r"(r2), "r"(r3), "r"(r8), "r"(r16) - : "memory"); -} -#endif - -static privileged void __morph_mprotect(void *addr, size_t size, int prot, - int ntprot) { +__funline void __morph_mprotect(void *addr, size_t size, int prot, int ntprot) { #ifdef __x86_64__ bool cf; int ax, dx; @@ -69,8 +53,11 @@ static privileged void __morph_mprotect(void *addr, size_t size, int prot, if (ax == -EPERM) { kprintf("error: need pledge(prot_exec) permission to code morph\n"); } + if (ax < 0) { + kprintf("error: __morph_mprotect(%p, %#zx, %d) failed: errno=%d\n", addr, + size, prot, -ax); + } #endif - if (ax) notpossible; } else { __imp_VirtualProtect(addr, size, ntprot, &op); } @@ -97,27 +84,6 @@ privileged void __morph_begin(sigset_t *save) { bool cf; intptr_t dx; sigset_t ss = {{-1, -1}}; -#ifdef __x86_64__ - if (IsOpenbsd()) { - asm volatile(CFLAG_ASM("syscall") - : CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx) - : "1"(__NR_sigprocmask), "D"(SIG_BLOCK), "S"(-1u) - : "rcx", "r8", "r9", "r10", "r11", "memory"); - save->__bits[0] = ax & 0xffffffff; - if (cf) notpossible; - } else if (!IsWindows() && !IsMetal()) { - asm volatile("mov\t$8,%%r10d\n\t" - "syscall" - : "=a"(ax), "=d"(dx) - : "0"(__NR_sigprocmask), "D"(SIG_BLOCK), "S"(&ss), "1"(save) - : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); - if (ax) notpossible; - } -#elif defined(__aarch64__) - __aarch64_sigprocmask(SIG_BLOCK, &ss, save); -#else -#error "unsupported architecture" -#endif __morph_mprotect(__executable_start, __privileged_start - __executable_start, PROT_READ | PROT_WRITE, kNtPageWritecopy); } @@ -131,24 +97,4 @@ privileged void __morph_end(sigset_t *save) { bool cf; __morph_mprotect(__executable_start, __privileged_start - __executable_start, PROT_READ | PROT_EXEC, kNtPageExecuteRead); -#ifdef __x86_64__ - if (IsOpenbsd()) { - asm volatile(CFLAG_ASM("syscall") - : CFLAG_CONSTRAINT(cf), "=a"(ax), "=d"(dx) - : "1"(__NR_sigprocmask), "D"(SIG_SETMASK), "S"(save->__bits[0]) - : "rcx", "r8", "r9", "r10", "r11", "memory"); - if (cf) notpossible; - } else if (!IsWindows() && !IsMetal()) { - asm volatile("mov\t$8,%%r10d\n\t" - "syscall" - : "=a"(ax), "=d"(dx) - : "0"(__NR_sigprocmask), "D"(SIG_SETMASK), "S"(save), "1"(0L) - : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); - if (ax) notpossible; - } -#elif defined(__aarch64__) - __aarch64_sigprocmask(SIG_SETMASK, save, 0); -#else -#error "unsupported architecture" -#endif } diff --git a/libc/runtime/opensymboltable.greg.c b/libc/runtime/opensymboltable.greg.c index 661d95df6..4a3016a58 100644 --- a/libc/runtime/opensymboltable.greg.c +++ b/libc/runtime/opensymboltable.greg.c @@ -100,8 +100,14 @@ static struct SymbolTable *OpenSymbolTableImpl(const char *filename) { for (j = i = 0; i < m; ++i) { sym = symtab + (stp[i] & 0x7fffffff); x = stp[i] >> 32; - if (j && x == t->symbols[j - 1].x) --j; - if (j && t->symbols[j - 1].y >= x) t->symbols[j - 1].y = x - 1; + if (j && x == t->symbols[j - 1].x) { + // when two symbols have an identical address value, favor the + // symbol that was defined earlier in the elf data structures. + continue; + } + if (j && t->symbols[j - 1].y >= x) { + t->symbols[j - 1].y = x - 1; + } t->names[j] = sym->st_name; t->symbols[j].x = x; if (sym->st_size) { diff --git a/libc/sysv/errno.c b/libc/sysv/errno.c index 53c1f9778..1a5889c5d 100644 --- a/libc/sysv/errno.c +++ b/libc/sysv/errno.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/errno.h" +#include "libc/thread/tls.h" /** * Global variable for last error. @@ -31,3 +32,14 @@ * @see __errno_location() stable abi */ errno_t __errno; + +/** + * Returns address of `errno` variable. + */ +errno_t *__errno_location(void) { + if (__tls_enabled) { + return &__get_tls()->tib_errno; + } else { + return &__errno; + } +} diff --git a/libc/sysv/errno_location.greg.c b/libc/sysv/errno_location.greg.c deleted file mode 100644 index 93246f2e5..000000000 --- a/libc/sysv/errno_location.greg.c +++ /dev/null @@ -1,29 +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 2022 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/thread/tls2.h" - -extern errno_t __errno; - -/** - * Returns address of errno variable. - */ -nocallersavedregisters errno_t *(__errno_location)(void) { - if (!__tls_enabled) return &__errno; - return &__get_tls_privileged()->tib_errno; -} diff --git a/libc/sysv/sysv.mk b/libc/sysv/sysv.mk index 78bf083c6..ca89ad843 100644 --- a/libc/sysv/sysv.mk +++ b/libc/sysv/sysv.mk @@ -40,7 +40,6 @@ LIBC_SYSV_A_FILES := \ libc/sysv/restorert.S \ libc/sysv/syscall.S \ libc/sysv/systemfive.S \ - libc/sysv/errno_location.greg.c \ libc/sysv/sysret.c \ libc/sysv/errno.c \ libc/sysv/errfun.S \