diff --git a/build/config.mk b/build/config.mk index f2b48affa2e..ceb7f9764a3 100644 --- a/build/config.mk +++ b/build/config.mk @@ -5,6 +5,7 @@ # # - `make` # - Backtraces +# - Syscall tracing # - Function tracing # - Reasonably small # - Reasonably optimized @@ -13,6 +14,7 @@ ifeq ($(MODE),) CONFIG_CCFLAGS += \ $(BACKTRACES) \ $(FTRACE) \ + -DSYSDEBUG \ -Og TARGET_ARCH ?= \ -msse3 @@ -23,6 +25,8 @@ endif # - `make MODE=opt` # - Backtraces # - More optimized +# - Syscall tracing +# - Function tracing # - Reasonably small # - No memory corruption detection # - assert() / CHECK_xx() may leak code into binary for debuggability @@ -35,6 +39,7 @@ CONFIG_CPPFLAGS += \ CONFIG_CCFLAGS += \ $(BACKTRACES) \ $(FTRACE) \ + -DSYSDEBUG \ -O3 TARGET_ARCH ?= \ -march=native @@ -122,6 +127,7 @@ CONFIG_CPPFLAGS += \ CONFIG_CCFLAGS += \ $(BACKTRACES) \ $(FTRACE) \ + -DSYSDEBUG \ -O2 \ -fno-inline CONFIG_COPTS += \ @@ -287,7 +293,7 @@ endif # LLVM Mode ifeq ($(MODE), llvm) TARGET_ARCH ?= -msse3 -CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2 +CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O2 AS = clang CC = clang CXX = clang++ diff --git a/libc/calls/chdir.c b/libc/calls/chdir.c index 101f6dfb811..07b57656d1f 100644 --- a/libc/calls/chdir.c +++ b/libc/calls/chdir.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -30,10 +31,14 @@ * @see fchdir() */ int chdir(const char *path) { - if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); - if (!IsWindows()) { - return sys_chdir(path); + int rc; + if (IsAsan() && !__asan_is_valid(path, 1)) { + rc = efault(); + } else if (!IsWindows()) { + rc = sys_chdir(path); } else { - return sys_chdir_nt(path); + rc = sys_chdir_nt(path); } + STRACE("chdir(%#s) → %d% m", path, rc); + return rc; } diff --git a/libc/calls/close.c b/libc/calls/close.c index 68012071073..ae30694a12e 100644 --- a/libc/calls/close.c +++ b/libc/calls/close.c @@ -19,7 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/macros.internal.h" #include "libc/sock/internal.h" #include "libc/sysv/errfuns.h" @@ -61,6 +61,6 @@ int close(int fd) { } } __releasefd(fd); - SYSDEBUG("close(%d) -> %d", fd, rc); + STRACE("%s(%d) → %d% m", "close", fd, rc); return rc; } diff --git a/libc/calls/commandv.c b/libc/calls/commandv.c index fde8e689aa7..be7b86d3074 100644 --- a/libc/calls/commandv.c +++ b/libc/calls/commandv.c @@ -19,7 +19,7 @@ #include "libc/bits/bits.h" #include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/log/libfatal.internal.h" @@ -159,6 +159,6 @@ noasan char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) { errno = f; } } - SYSDEBUG("commandv(%#s, %p) → %#s% m", name, pathbuf, res); + STRACE("commandv(%#s, %p) → %#s% m", name, pathbuf, res); return res; } diff --git a/libc/runtime/describeframe.c b/libc/calls/describeframe.c similarity index 89% rename from libc/runtime/describeframe.c rename to libc/calls/describeframe.c index 6d1f04e096e..1dc78593f57 100644 --- a/libc/runtime/describeframe.c +++ b/libc/calls/describeframe.c @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/log/libfatal.internal.h" +#include "libc/intrin/kprintf.h" #include "libc/macros.internal.h" #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" @@ -28,21 +28,19 @@ noasan const char *DescribeFrame(int x) { /* asan runtime depends on this function */ char *p; - static char buf[128]; + static char buf[32]; if (IsShadowFrame(x)) { - p = buf; - p = __stpcpy(p, " shadow of "); - p = __fixcpy(p, UNSHADOW(ADDR(x)), 48); + ksnprintf(buf, sizeof(buf), " /*shadow:%.12p*/", UNSHADOW(ADDR(x))); return buf; - return " shadow "; + return " /*shadow*/ "; } else if (IsAutoFrame(x)) { - return " automap"; + return " /*automap*/"; } else if (IsFixedFrame(x)) { - return " fixed "; + return " /*fixed*/ "; } else if (IsArenaFrame(x)) { - return " arena "; + return " /*arena*/ "; } else if (IsStaticStackFrame(x)) { - return " stack "; + return " /*stack*/ "; } else { return ""; } diff --git a/libc/runtime/describemapping.c b/libc/calls/describemapping.c similarity index 88% rename from libc/runtime/describemapping.c rename to libc/calls/describemapping.c index 3dffeab43f9..93e4f9d7417 100644 --- a/libc/runtime/describemapping.c +++ b/libc/calls/describemapping.c @@ -20,19 +20,26 @@ #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/prot.h" +static noasan char DescribeMapType(int flags) { + switch (flags & MAP_TYPE) { + case MAP_FILE: + return 'f'; + case MAP_PRIVATE: + return 'p'; + case MAP_SHARED: + return 's'; + default: + return '?'; + } +} + noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) { /* asan runtime depends on this function */ p[0] = (prot & PROT_READ) ? 'r' : '-'; p[1] = (prot & PROT_WRITE) ? 'w' : '-'; p[2] = (prot & PROT_EXEC) ? 'x' : '-'; - if (flags & MAP_PRIVATE) { - p[3] = 'p'; - } else if (flags & MAP_SHARED) { - p[3] = 's'; - } else { - p[3] = '?'; - } - p[4] = (flags & MAP_ANONYMOUS) ? 'a' : 'f'; + p[3] = DescribeMapType(flags); + p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-'; p[5] = (flags & MAP_GROWSDOWN) ? 'S' : '-'; p[6] = (flags & MAP_FIXED) ? 'F' : '-'; p[7] = 0; diff --git a/libc/runtime/directmap-metal.c b/libc/calls/directmap-metal.c similarity index 100% rename from libc/runtime/directmap-metal.c rename to libc/calls/directmap-metal.c diff --git a/libc/runtime/directmap-nt.c b/libc/calls/directmap-nt.c similarity index 87% rename from libc/runtime/directmap-nt.c rename to libc/calls/directmap-nt.c index e50ce99d620..d083fe3717f 100644 --- a/libc/runtime/directmap-nt.c +++ b/libc/calls/directmap-nt.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/macros.internal.h" #include "libc/nt/enum/filemapflags.h" #include "libc/nt/enum/pageflags.h" @@ -46,14 +46,14 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size, dm.maphandle = CreateFileMappingNuma(-1, &kNtIsInheritable, kNtPageExecuteReadwrite, upsize >> 32, upsize, NULL, kNtNumaNoPreferredNode); - SYSDEBUG("CreateFileMappingNuma(-1, kNtPageExecuteReadwrite, 0x%x/0x%x) -> " - "0x%x", - upsize, size, dm.maphandle); + STRACE( + "CreateFileMappingNuma(-1, kNtPageExecuteReadwrite, %'zu/%'zu) -> %p", + upsize, size, dm.maphandle); if (dm.maphandle) { dm.addr = MapViewOfFileExNuma(dm.maphandle, kNtFileMapWrite | kNtFileMapExecute, 0, 0, upsize, addr, kNtNumaNoPreferredNode); - SYSDEBUG("MapViewOfFileExNuma(WX, 0x%x) -> addr:0x%x", addr, dm.addr); + STRACE("MapViewOfFileExNuma(WX, %p) → addr:%p", addr, dm.addr); if (dm.addr) { for (i = 0; i < size; i += got) { got = 0; @@ -78,20 +78,16 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size, (prot & PROT_WRITE) ? kNtPageExecuteReadwrite : kNtPageExecuteRead, handle != -1 ? 0 : size >> 32, handle != -1 ? 0 : size, NULL, kNtNumaNoPreferredNode); - SYSDEBUG("CreateFileMappingNuma(fhand:%d, prot:%s, size:0x%x) -> " - "handle:0x%x", - handle, (prot & PROT_WRITE) ? "XRW" : "XR", - handle != -1 ? 0 : size); + STRACE("CreateFileMappingNuma(fhand:%ld, prot:%s, size:%'zu) → %p", handle, + (prot & PROT_WRITE) ? "XRW" : "XR", handle != -1 ? 0 : size); if (dm.maphandle) { dm.addr = MapViewOfFileExNuma( dm.maphandle, (prot & PROT_WRITE) ? kNtFileMapWrite | kNtFileMapExecute : kNtFileMapRead | kNtFileMapExecute, off >> 32, off, size, addr, kNtNumaNoPreferredNode); - SYSDEBUG( - "MapViewOfFileExNuma(prot:%s, off:0x%x, size:0x%x, addr:0x%x) -> " - "addr:0x%x", - (prot & PROT_WRITE) ? "WX" : "RX", off, size, addr, dm.addr); + STRACE("MapViewOfFileExNuma(prot:%s, off:%'ld, size:%'zu, addr:%p) → %p", + (prot & PROT_WRITE) ? "WX" : "RX", off, size, addr, dm.addr); if (dm.addr) { return dm; } else { diff --git a/libc/runtime/directmap.c b/libc/calls/directmap.c similarity index 80% rename from libc/runtime/directmap.c rename to libc/calls/directmap.c index ab1a121b8e9..a07365028c6 100644 --- a/libc/runtime/directmap.c +++ b/libc/calls/directmap.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/errno.h" #include "libc/nt/runtime.h" #include "libc/runtime/directmap.internal.h" @@ -36,20 +36,18 @@ noasan struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { /* asan runtime depends on this function */ char mode[8]; - struct DirectMap dm; + struct DirectMap d; if (!IsWindows() && !IsMetal()) { - dm.addr = __sys_mmap(addr, size, prot, flags, fd, off, off); - SYSDEBUG("sys_mmap(0x%p%s, 0x%x, %s, %d, %d) -> 0x%p %s", addr, - DescribeFrame((intptr_t)addr >> 16), size, - DescribeMapping(prot, flags, mode), (long)fd, off, dm.addr, - dm.addr != MAP_FAILED ? "" : strerror(errno)); - dm.maphandle = kNtInvalidHandleValue; - return dm; + d.addr = __sys_mmap(addr, size, prot, flags, fd, off, off); + d.maphandle = kNtInvalidHandleValue; } else if (IsMetal()) { - return sys_mmap_metal(addr, size, prot, flags, fd, off); + d = sys_mmap_metal(addr, size, prot, flags, fd, off); } else { - return sys_mmap_nt(addr, size, prot, flags, - fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue, - off); + d = sys_mmap_nt(addr, size, prot, flags, + fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue, off); } + STRACE("sys_mmap(%.12p%s, %'zu, %s, %d, %'ld) → {%.12p, %p}% m", addr, + DescribeFrame((intptr_t)addr >> 16), size, + DescribeMapping(prot, flags, mode), fd, off, d.addr, d.maphandle); + return d; } diff --git a/libc/calls/dup.c b/libc/calls/dup.c index 13b9ee6e323..e8c01080148 100644 --- a/libc/calls/dup.c +++ b/libc/calls/dup.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" /** @@ -36,6 +36,6 @@ int dup(int fd) { } else { fd2 = sys_dup_nt(fd, -1, 0); } - SYSDEBUG("dup(%d) -> %d", fd, fd2); + STRACE("%s(%d) → %d% m", "dup", fd, fd2); return fd2; } diff --git a/libc/calls/dup2.c b/libc/calls/dup2.c index 4ec133e97ef..108f739df36 100644 --- a/libc/calls/dup2.c +++ b/libc/calls/dup2.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" /** @@ -32,11 +32,14 @@ * @vforksafe */ int dup2(int oldfd, int newfd) { - SYSDEBUG("dup2(%d, %d)", oldfd, newfd); - if (oldfd == newfd) return newfd; - if (!IsWindows()) { - return sys_dup3(oldfd, newfd, 0); + int rc; + if (oldfd == newfd) { + rc = newfd; + } else if (!IsWindows()) { + rc = sys_dup3(oldfd, newfd, 0); } else { - return sys_dup_nt(oldfd, newfd, 0); + rc = sys_dup_nt(oldfd, newfd, 0); } + STRACE("dup2(%d, %d) → %d% m", oldfd, newfd, rc); + return rc; } diff --git a/libc/calls/dup3.c b/libc/calls/dup3.c index fc6e1985839..717518fd78f 100644 --- a/libc/calls/dup3.c +++ b/libc/calls/dup3.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/sysv/errfuns.h" @@ -36,10 +36,12 @@ * @see dup(), dup2() */ int dup3(int oldfd, int newfd, int flags) { - SYSDEBUG("dup3(%d, %d, %d)", oldfd, newfd, flags); + int rc; if (!IsWindows()) { - return sys_dup3(oldfd, newfd, flags); + rc = sys_dup3(oldfd, newfd, flags); } else { - return sys_dup_nt(oldfd, newfd, flags); + rc = sys_dup_nt(oldfd, newfd, flags); } + STRACE("dup3(%d, %d, %d) → %d% m", oldfd, newfd, flags, rc); + return rc; } diff --git a/libc/calls/execve.c b/libc/calls/execve.c index 8e9fa67aeca..f7a278ecb27 100644 --- a/libc/calls/execve.c +++ b/libc/calls/execve.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/intrin/kprintf.h" @@ -39,35 +39,41 @@ * @asyncsignalsafe * @vforksafe */ -int execve(const char *program, char *const argv[], char *const envp[]) { +int execve(const char *prog, char *const argv[], char *const envp[]) { + int rc; size_t i; - if (!program || !argv || !envp) return efault(); - if (IsAsan() && - (!__asan_is_valid(program, 1) || !__asan_is_valid_strlist(argv) || - !__asan_is_valid_strlist(envp))) { - return efault(); - } - if (DEBUGSYS) { - kprintf("SYS: execve(%s, {", program); - for (i = 0; argv[i]; ++i) { - if (i) kprintf(", "); - kprintf("%s", argv[i]); + if (!prog || !argv || !envp || + (IsAsan() && + (!__asan_is_valid(prog, 1) || !__asan_is_valid_strlist(argv) || + !__asan_is_valid_strlist(envp)))) { + rc = efault(); + } else { +#ifdef SYSDEBUG + if (__strace > 0) { + kprintf(STRACE_PROLOGUE "execve(%#s, {", prog); + for (i = 0; argv[i]; ++i) { + if (i) kprintf(", "); + kprintf("%#s", argv[i]); + } + kprintf("}, {"); + for (i = 0; envp[i]; ++i) { + if (i) kprintf(", "); + kprintf("%#s", envp[i]); + } + kprintf("})%n"); } - kprintf("}, {"); - for (i = 0; envp[i]; ++i) { - if (i) kprintf(", "); - kprintf("%s", envp[i]); +#endif + for (i = 3; i < g_fds.n; ++i) { + if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) { + close(i); + } } - kprintf("})\n"); - } - for (i = 3; i < g_fds.n; ++i) { - if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) { - close(i); + if (!IsWindows()) { + rc = sys_execve(prog, argv, envp); + } else { + rc = sys_execve_nt(prog, argv, envp); } } - if (!IsWindows()) { - return sys_execve(program, argv, envp); - } else { - return sys_execve_nt(program, argv, envp); - } + STRACE("execve(%#s) failed %d% m", prog, rc); + return rc; } diff --git a/libc/calls/fchmodat.c b/libc/calls/fchmodat.c index d33db04cf2b..75db6c76189 100644 --- a/libc/calls/fchmodat.c +++ b/libc/calls/fchmodat.c @@ -19,7 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -42,14 +42,13 @@ int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) { int rc; if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); - if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) { - rc = -1; /* TODO(jart): implement me */ + if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) { + STRACE("zipos fchmodat not supported yet"); } else if (!IsWindows()) { rc = sys_fchmodat(dirfd, path, mode, flags); } else { rc = sys_fchmodat_nt(dirfd, path, mode, flags); } - SYSDEBUG("fchmodat(%d, %s, %o, %d) -> %d %s", (long)dirfd, path, mode, flags, - rc != -1 ? "" : strerror(errno)); + STRACE("fchmodat(%d, %#s, %#o, %d) → %d% m", dirfd, path, mode, flags, rc); return rc; } diff --git a/libc/calls/fchownat.c b/libc/calls/fchownat.c index 4b408dcf671..e4b55f6e8d5 100644 --- a/libc/calls/fchownat.c +++ b/libc/calls/fchownat.c @@ -19,6 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -39,9 +40,15 @@ */ int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid, int flags) { - if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); - if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) { - return -1; /* TODO(jart): implement me */ + int rc; + if (IsAsan() && !__asan_is_valid(path, 1)) { + rc = efault(); + } else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) { + STRACE("zipos fchownat not supported yet"); + } else { + rc = sys_fchownat(dirfd, path, uid, gid, flags); } - return sys_fchownat(dirfd, path, uid, gid, flags); + STRACE("fchownat(%d, %#s, %d, %d, %#b) → %d% m", dirfd, path, uid, gid, flags, + rc); + return rc; } diff --git a/libc/calls/fcntl.c b/libc/calls/fcntl.c index 230fcb045d8..40ce8f3da00 100644 --- a/libc/calls/fcntl.c +++ b/libc/calls/fcntl.c @@ -28,6 +28,12 @@ * * CHECK_NE(-1, fcntl(fd, F_SETFD, FD_CLOEXEC)); * + * This function lets you duplicate file descriptors without running + * into an edge case where they take over stdio handles: + * + * CHECK_GE((newfd = fcntl(oldfd, F_DUPFD, 3)), 3); + * CHECK_GE((newfd = fcntl(oldfd, F_DUPFD_CLOEXEC, 3)), 3); + * * This function implements POSIX Advisory Locks, e.g. * * CHECK_NE(-1, fcntl(zfd, F_SETLKW, &(struct flock){F_WRLCK})); diff --git a/libc/calls/fdatasync.c b/libc/calls/fdatasync.c index 7da2a6f3042..2f63c428129 100644 --- a/libc/calls/fdatasync.c +++ b/libc/calls/fdatasync.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" /** @@ -28,9 +29,12 @@ * @asyncsignalsafe */ int fdatasync(int fd) { + int rc; if (!IsWindows()) { - return sys_fdatasync(fd); + rc = sys_fdatasync(fd); } else { - return sys_fdatasync_nt(fd); + rc = sys_fdatasync_nt(fd); } + STRACE("%s(%d) → %d% m", "fdatasync", fd, rc); + return rc; } diff --git a/libc/calls/fileexists.c b/libc/calls/fileexists.c index ad6de423a98..164b0bee9b7 100644 --- a/libc/calls/fileexists.c +++ b/libc/calls/fileexists.c @@ -69,8 +69,7 @@ bool fileexists(const char *path) { } else { res = false; } - SYSDEBUG("fileexists(%s) -> %s %s", path, res ? "true" : "false", - res ? "" : strerror(errno)); + STRACE("fileexists(%#s) → %hhhd% m", path, res); if (!res && (errno == ENOENT || errno == ENOTDIR)) { errno = e; } diff --git a/libc/calls/flock.c b/libc/calls/flock.c index c8f7af7f914..8d6a1a05886 100644 --- a/libc/calls/flock.c +++ b/libc/calls/flock.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" /** @@ -30,9 +31,12 @@ * @return 0 on success, or -1 w/ errno */ int flock(int fd, int op) { + int rc; if (!IsWindows()) { - return sys_flock(fd, op); + rc = sys_flock(fd, op); } else { - return sys_flock_nt(fd, op); + rc = sys_flock_nt(fd, op); } + STRACE("flock(%d, %d) → %d% m", fd, op, rc); + return rc; } diff --git a/libc/calls/fstat-nt.c b/libc/calls/fstat-nt.c index fd4bce28645..c2909562a84 100644 --- a/libc/calls/fstat-nt.c +++ b/libc/calls/fstat-nt.c @@ -18,8 +18,8 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/stat.h" -#include "libc/calls/sysdebug.internal.h" #include "libc/fmt/conv.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/bsr.h" @@ -64,7 +64,7 @@ static textwindows uint32_t GetSizeOfReparsePoint(int64_t fh) { z += x < 0200 ? 1 : bsrl(tpenc(x)) >> 3; } } else { - SYSDEBUG("GetSizeOfReparsePoint failed %d", GetLastError()); + STRACE("%s failed %m", "GetSizeOfReparsePoint"); } return z; } @@ -122,7 +122,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) { st->st_blocks = ROUNDUP(actualsize, PAGESIZE) / 512; } } else { - SYSDEBUG("GetFileInformationByHandle failed %d", GetLastError()); + STRACE("%s failed %m", "GetFileInformationByHandle"); } break; default: @@ -130,7 +130,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) { } return 0; } else { - SYSDEBUG("GetFileType failed %d", GetLastError()); + STRACE("%s failed %m", "GetFileType"); return __winerr(); } } diff --git a/libc/calls/fstat-sysv.c b/libc/calls/fstat-sysv.c index f8ac0f05492..e05714552f9 100644 --- a/libc/calls/fstat-sysv.c +++ b/libc/calls/fstat-sysv.c @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -42,7 +41,6 @@ int32_t sys_fstat(int32_t fd, struct stat *st) { __stat2cosmo(st, &ms); return 0; } else { - SYSDEBUG("sys_fstat(%d) failed w/ %m", fd); return -1; } } diff --git a/libc/calls/fstat.c b/libc/calls/fstat.c index e41f50834c7..3ae6364b905 100644 --- a/libc/calls/fstat.c +++ b/libc/calls/fstat.c @@ -19,6 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -29,15 +30,19 @@ * @asyncsignalsafe */ int fstat(int fd, struct stat *st) { + int rc; if (__isfdkind(fd, kFdZip)) { - return weaken(__zipos_fstat)( + rc = weaken(__zipos_fstat)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st); } else if (!IsWindows() && !IsMetal()) { - return sys_fstat(fd, st); + rc = sys_fstat(fd, st); } else if (IsMetal()) { - return sys_fstat_metal(fd, st); + rc = sys_fstat_metal(fd, st); + } else if (!__isfdkind(fd, kFdFile)) { + rc = ebadf(); } else { - if (!__isfdkind(fd, kFdFile)) return ebadf(); - return sys_fstat_nt(g_fds.p[fd].handle, st); + rc = sys_fstat_nt(g_fds.p[fd].handle, st); } + STRACE("fstat(%d, [%s]) → %d% m", fd, __strace_stat(rc, st), rc); + return rc; } diff --git a/libc/calls/fstatat.c b/libc/calls/fstatat.c index db489f107ff..1dc1357d35f 100644 --- a/libc/calls/fstatat.c +++ b/libc/calls/fstatat.c @@ -19,6 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" @@ -38,15 +39,28 @@ * @return 0 on success, or -1 w/ errno * @see S_ISDIR(st.st_mode), S_ISREG() * @asyncsignalsafe + * @vforksafe */ int fstatat(int dirfd, const char *path, struct stat *st, int flags) { + /* execve() depends on this */ + int rc; struct ZiposUri zipname; - if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */ - if (weaken(__zipos_stat) && weaken(__zipos_parseuri)(path, &zipname) != -1) { - return weaken(__zipos_stat)(&zipname, st); + if (__isfdkind(dirfd, kFdZip)) { + STRACE("zipos dirfd not supported yet"); + rc = einval(); + } else if (weaken(__zipos_stat) && + weaken(__zipos_parseuri)(path, &zipname) != -1) { + if (!__vforked) { + rc = weaken(__zipos_stat)(&zipname, st); + } else { + rc = enotsup(); + } } else if (!IsWindows()) { - return sys_fstatat(dirfd, path, st, flags); + rc = sys_fstatat(dirfd, path, st, flags); } else { - return sys_fstatat_nt(dirfd, path, st, flags); + rc = sys_fstatat_nt(dirfd, path, st, flags); } + STRACE("fstatat(%d, %#s, [%s], %#b) → %d% m", dirfd, path, + __strace_stat(rc, st), flags, rc); + return rc; } diff --git a/libc/calls/fsync.c b/libc/calls/fsync.c index 39a8b447692..99b6286ec12 100644 --- a/libc/calls/fsync.c +++ b/libc/calls/fsync.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" /** @@ -28,9 +29,12 @@ * @asyncsignalsafe */ int fsync(int fd) { + int rc; if (!IsWindows()) { - return sys_fsync(fd); + rc = sys_fsync(fd); } else { - return sys_fdatasync_nt(fd); + rc = sys_fdatasync_nt(fd); } + STRACE("%s(%d) → %d% m", "fsync", fd, rc); + return rc; } diff --git a/libc/calls/ftruncate.c b/libc/calls/ftruncate.c index a55b2fca4ad..5c17d57806a 100644 --- a/libc/calls/ftruncate.c +++ b/libc/calls/ftruncate.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/sysv/errfuns.h" @@ -32,11 +33,15 @@ * @asyncsignalsafe */ int ftruncate(int fd, int64_t length) { - if (fd < 0) return einval(); - if (!IsWindows()) { - return sys_ftruncate(fd, length, length); + int rc; + if (fd < 0) { + rc = einval(); + } else if (!IsWindows()) { + rc = sys_ftruncate(fd, length, length); } else { - if (fd >= g_fds.n) return ebadf(); - return sys_ftruncate_nt(g_fds.p[fd].handle, length); + if (fd >= g_fds.n) rc = ebadf(); + rc = sys_ftruncate_nt(g_fds.p[fd].handle, length); } + STRACE("ftruncate(%d, %'ld) → %d% m", fd, length, rc); + return rc; } diff --git a/libc/calls/g_fds_init.S b/libc/calls/g_fds_init.S index 4e7d3a9996b..b444acd8472 100644 --- a/libc/calls/g_fds_init.S +++ b/libc/calls/g_fds_init.S @@ -18,10 +18,10 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" - .init.start 302,_init_g_fds + .init.start 305,_init_g_fds push %rdi push %rsi call InitializeFileDescriptors pop %rsi pop %rdi - .init.end 302,_init_g_fds + .init.end 305,_init_g_fds diff --git a/libc/calls/getcwd.c b/libc/calls/getcwd.c index 536d8df798a..caa17091f8f 100644 --- a/libc/calls/getcwd.c +++ b/libc/calls/getcwd.c @@ -16,11 +16,13 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" +#include "libc/log/backtrace.internal.h" #include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/sysv/errfuns.h" @@ -43,19 +45,20 @@ char *getcwd(char *buf, size_t size) { if (buf) { p = buf; if (!size) { - SYSDEBUG("getcwd(%p, %x) EINVAL", buf, size); einval(); + STRACE("getcwd(%p, %'zu) %m", buf, size); return 0; } } else if (weaken(malloc)) { + assert(!__vforked); if (!size) size = PATH_MAX + 1; if (!(p = weaken(malloc)(size))) { - SYSDEBUG("getcwd(%p, %x) ENOMEM", buf, size); + STRACE("getcwd(%p, %'zu) %m", buf, size); return 0; } } else { - SYSDEBUG("getcwd() EINVAL needs buf≠0 or STATIC_YOINK(\"malloc\")"); einval(); + STRACE("getcwd() needs buf≠0 or STATIC_YOINK(\"malloc\")"); return 0; } *p = '\0'; @@ -85,6 +88,6 @@ char *getcwd(char *buf, size_t size) { } } } - SYSDEBUG("getcwd(%p, %x) -> %s", buf, size, r); + STRACE("getcwd(%p, %'zu) → %#s", buf, size, r); return r; } diff --git a/libc/calls/getitimer.c b/libc/calls/getitimer.c index 476df9bdaee..57b8937a994 100644 --- a/libc/calls/getitimer.c +++ b/libc/calls/getitimer.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -29,13 +30,22 @@ * @return 0 on success or -1 w/ errno */ int getitimer(int which, struct itimerval *curvalue) { + int rc; if (IsAsan() && !__asan_is_valid(curvalue, sizeof(*curvalue))) { - return efault(); + rc = efault(); + } else if (!IsWindows()) { + rc = sys_getitimer(which, curvalue); + } else if (!curvalue) { + rc = efault(); + } else { + rc = sys_setitimer_nt(which, 0, curvalue); } - if (!IsWindows()) { - return sys_getitimer(which, curvalue); + if (curvalue) { + STRACE("getitimer(%d, [{{%'ld, %'ld}, {%'ld, %'ld}}]) → %d% m", which, + curvalue->it_interval.tv_sec, curvalue->it_interval.tv_usec, + curvalue->it_value.tv_sec, curvalue->it_value.tv_usec, rc); } else { - if (!curvalue) return efault(); - return sys_setitimer_nt(which, 0, curvalue); + STRACE("getitimer(%d, 0) → %d% m", which, rc); } + return rc; } diff --git a/libc/calls/getpgid.c b/libc/calls/getpgid.c index 8f8d0cac549..8ae485a7ee4 100644 --- a/libc/calls/getpgid.c +++ b/libc/calls/getpgid.c @@ -18,15 +18,19 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" /** * Returns process group id. */ int getpgid(int pid) { + int rc; if (!IsWindows()) { - return sys_getpgid(pid); + rc = sys_getpgid(pid); } else { - return getpid(); + rc = getpid(); } + STRACE("%s(%d) → %d% m", "getpgid", pid, rc); + return rc; } diff --git a/libc/calls/getrlimit.c b/libc/calls/getrlimit.c index c651a3f707f..17f117bde02 100644 --- a/libc/calls/getrlimit.c +++ b/libc/calls/getrlimit.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -31,7 +32,16 @@ * @see libc/sysv/consts.sh */ int getrlimit(int resource, struct rlimit *rlim) { - if (resource == 127) return einval(); - if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) return efault(); - return sys_getrlimit(resource, rlim); + int rc; + char buf[64]; + if (resource == 127) { + rc = einval(); + } else if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) { + rc = efault(); + } else { + rc = sys_getrlimit(resource, rlim); + } + STRACE("getrlimit(%s, [%s]) → %d% m", __strace_rlimit_name(resource), + __strace_rlimit(buf, sizeof(buf), rc, rlim), rc); + return rc; } diff --git a/libc/calls/getsid.c b/libc/calls/getsid.c index a2f057528b5..4c29139f2df 100644 --- a/libc/calls/getsid.c +++ b/libc/calls/getsid.c @@ -18,10 +18,14 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" /** * Creates session and sets the process group id. */ uint32_t getsid(int pid) { - return sys_getsid(pid); + int rc; + rc = sys_getsid(pid); + STRACE("%s(%d) → %d% m", "getsid", pid, rc); + return rc; } diff --git a/libc/calls/getuid.c b/libc/calls/getuid.c index f801a93f759..34eb2702f71 100644 --- a/libc/calls/getuid.c +++ b/libc/calls/getuid.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/macros.internal.h" #include "libc/nt/accounting.h" @@ -51,11 +52,14 @@ static textwindows dontinline uint32_t GetUserNameHash(void) { * @vforksafe */ uint32_t getuid(void) { + int rc; if (!IsWindows()) { - return sys_getuid(); + rc = sys_getuid(); } else { - return GetUserNameHash(); + rc = GetUserNameHash(); } + STRACE("%s() → %d% m", "getuid", rc); + return rc; } /** @@ -68,9 +72,12 @@ uint32_t getuid(void) { * @vforksafe */ uint32_t getgid(void) { + int rc; if (!IsWindows()) { - return sys_getgid(); + rc = sys_getgid(); } else { - return GetUserNameHash(); + rc = GetUserNameHash(); } + STRACE("%s() → %d% m", "getgid", rc); + return rc; } diff --git a/libc/calls/ioctl_siocgifconf.c b/libc/calls/ioctl_siocgifconf.c index debafc1b44f..a1b41bea4cb 100644 --- a/libc/calls/ioctl_siocgifconf.c +++ b/libc/calls/ioctl_siocgifconf.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" +#include "libc/bits/bits.h" #include "libc/bits/weaken.h" #include "libc/calls/internal.h" #include "libc/calls/ioctl.h" diff --git a/libc/calls/ioctl_tcgets.c b/libc/calls/ioctl_tcgets.c index 564fcb7723c..5e9a7aa83c1 100644 --- a/libc/calls/ioctl_tcgets.c +++ b/libc/calls/ioctl_tcgets.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" #include "libc/calls/ioctl.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/metatermios.internal.h" #include "libc/calls/termios.internal.h" #include "libc/calls/ttydefaults.h" @@ -65,23 +66,27 @@ static int ioctl_tcgets_sysv(int fd, struct termios *tio) { * @see ioctl(fd, TIOCGETA, tio) dispatches here */ int ioctl_tcgets(int fd, ...) { + int rc; va_list va; struct termios *tio; va_start(va, fd); tio = va_arg(va, struct termios *); va_end(va); if (fd >= 0) { - if (!tio) return efault(); - if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { - return enotty(); + if (!tio) { + rc = efault(); + } else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { + rc = enotty(); } else if (IsMetal()) { - return ioctl_tcgets_metal(fd, tio); + rc = ioctl_tcgets_metal(fd, tio); } else if (!IsWindows()) { - return ioctl_tcgets_sysv(fd, tio); + rc = ioctl_tcgets_sysv(fd, tio); } else { - return ioctl_tcgets_nt(fd, tio); + rc = ioctl_tcgets_nt(fd, tio); } } else { - return einval(); + rc = einval(); } + STRACE("ioctl_tcgets(%d, %p) → %d% m", fd, tio, rc); + return rc; } diff --git a/libc/calls/ioctl_tcsets.c b/libc/calls/ioctl_tcsets.c index a89abb0b806..4f665b2db46 100644 --- a/libc/calls/ioctl_tcsets.c +++ b/libc/calls/ioctl_tcsets.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" #include "libc/calls/ioctl.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/metatermios.internal.h" #include "libc/calls/termios.internal.h" #include "libc/dce.h" @@ -86,5 +87,6 @@ int ioctl_tcsets(int fd, uint64_t request, ...) { if (rc != -1) { __nomultics = !(tio->c_oflag & OPOST); } + STRACE("ioctl_tcsets(%d, %p, %p) → %d% m", fd, request, tio, rc); return rc; } diff --git a/libc/calls/isdirectory.c b/libc/calls/isdirectory.c index c1c9278898f..2b92d311529 100644 --- a/libc/calls/isdirectory.c +++ b/libc/calls/isdirectory.c @@ -19,9 +19,9 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/metastat.internal.h" #include "libc/calls/struct/stat.h" -#include "libc/calls/sysdebug.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" @@ -68,8 +68,7 @@ bool isdirectory(const char *path) { } else { res = isdirectory_nt(path); } - SYSDEBUG("isdirectory(%s) -> %s %s", path, res ? "true" : "false", - res ? "" : strerror(errno)); + STRACE("isdirectory(%#s) → %hhhd% m", path, res); if (!res && (errno == ENOENT || errno == ENOTDIR)) { errno = e; } diff --git a/libc/calls/isexecutable.c b/libc/calls/isexecutable.c index f79f7ca6deb..f8de085a602 100644 --- a/libc/calls/isexecutable.c +++ b/libc/calls/isexecutable.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" +#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/s.h" /** @@ -25,9 +26,11 @@ * * @see access(exe, X_OK) which is more accurate on NT * @asyncsignalsafe + * @vforksafe */ bool isexecutable(const char *path) { + /* execve() depends on this */ struct stat st; - if (stat(path, &st)) return 0; - return st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH); + if (fstatat(AT_FDCWD, path, &st, 0)) return 0; + return !!(st.st_mode & 0111); } diff --git a/libc/calls/isregularfile.c b/libc/calls/isregularfile.c index 66d0022d424..ca938c13043 100644 --- a/libc/calls/isregularfile.c +++ b/libc/calls/isregularfile.c @@ -40,7 +40,7 @@ * @see isdirectory(), ischardev(), issymlink() */ bool isregularfile(const char *path) { - int rc, e; + int e; union metastat st; struct ZiposUri zipname; if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); diff --git a/libc/calls/linkat.c b/libc/calls/linkat.c index 2df6171c0b3..05ef16efbb6 100644 --- a/libc/calls/linkat.c +++ b/libc/calls/linkat.c @@ -19,6 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -36,18 +37,20 @@ */ int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) { + int rc; if (IsAsan() && (!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) { - return efault(); - } - if (weaken(__zipos_notat) && - (weaken(__zipos_notat)(olddirfd, oldpath) == -1 || - weaken(__zipos_notat)(newdirfd, newpath) == -1)) { - return -1; /* TODO(jart): implement me */ - } - if (!IsWindows()) { - return sys_linkat(olddirfd, oldpath, newdirfd, newpath, flags); + rc = efault(); + } else if (weaken(__zipos_notat) && + ((rc = __zipos_notat(olddirfd, oldpath)) == -1 || + (rc = __zipos_notat(newdirfd, newpath)) == -1)) { + STRACE("zipos fchownat not supported yet"); + } else if (!IsWindows()) { + rc = sys_linkat(olddirfd, oldpath, newdirfd, newpath, flags); } else { - return sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath); + rc = sys_linkat_nt(olddirfd, oldpath, newdirfd, newpath); } + STRACE("linkat(%d, %#s, %d, %#s, %#b) → %d% m", olddirfd, oldpath, newdirfd, + newpath, flags, rc); + return rc; } diff --git a/libc/calls/lseek.c b/libc/calls/lseek.c index e391f3bef39..07961309f1f 100644 --- a/libc/calls/lseek.c +++ b/libc/calls/lseek.c @@ -19,6 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/log/backtrace.internal.h" #include "libc/zipos/zipos.internal.h" @@ -33,14 +34,17 @@ * @asyncsignalsafe */ int64_t lseek(int fd, int64_t offset, unsigned whence) { + int64_t rc; if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { - return weaken(__zipos_lseek)( + rc = weaken(__zipos_lseek)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, offset, whence); } else if (!IsWindows() && !IsOpenbsd() && !IsNetbsd()) { - return sys_lseek(fd, offset, whence, 0); + rc = sys_lseek(fd, offset, whence, 0); } else if (IsOpenbsd() || IsNetbsd()) { - return sys_lseek(fd, offset, offset, whence); + rc = sys_lseek(fd, offset, offset, whence); } else { - return sys_lseek_nt(fd, offset, whence); + rc = sys_lseek_nt(fd, offset, whence); } + STRACE("lseek(%d, %'ld, %d) → %'ld% m", fd, offset, whence, rc); + return rc; } diff --git a/libc/calls/madvise-nt.c b/libc/calls/madvise-nt.c index 6592ff700ee..ce50c000221 100644 --- a/libc/calls/madvise-nt.c +++ b/libc/calls/madvise-nt.c @@ -50,8 +50,7 @@ forceinline typeof(OfferVirtualMemory) *GetOfferVirtualMemory(void) { textwindows int sys_madvise_nt(void *addr, size_t length, int advice) { uint32_t rangecount; struct NtMemoryRangeEntry ranges[1]; - if ((advice & (int)MADV_WILLNEED) == (int)MADV_WILLNEED || - (advice & (int)MADV_SEQUENTIAL) == (int)MADV_SEQUENTIAL) { + if (advice == MADV_WILLNEED || advice == MADV_SEQUENTIAL) { typeof(PrefetchVirtualMemory) *fn = GetPrefetchVirtualMemory(); if (fn) { ranges[0].VirtualAddress = addr; @@ -65,7 +64,7 @@ textwindows int sys_madvise_nt(void *addr, size_t length, int advice) { } else { return enosys(); } - } else if ((advice & (int)MADV_FREE) == (int)MADV_FREE) { + } else if (advice == MADV_FREE) { typeof(OfferVirtualMemory) *fn = GetOfferVirtualMemory(); if (fn) { if (fn(addr, length, kNtVmOfferPriorityNormal)) { diff --git a/libc/calls/madvise.c b/libc/calls/madvise.c index d73571ae398..d4f2c7b516d 100644 --- a/libc/calls/madvise.c +++ b/libc/calls/madvise.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -31,10 +32,18 @@ * @see fadvise() */ int madvise(void *addr, size_t length, int advice) { - if (IsAsan() && !__asan_is_valid(addr, length)) return efault(); - if (!IsWindows()) { - return sys_madvise(addr, length, advice); + int rc; + if (advice != 127 /* see consts.sh */) { + if (IsAsan() && !__asan_is_valid(addr, length)) { + rc = efault(); + } else if (!IsWindows()) { + rc = sys_madvise(addr, length, advice); + } else { + rc = sys_madvise_nt(addr, length, advice); + } } else { - return sys_madvise_nt(addr, length, advice); + rc = einval(); } + STRACE("madvise(%p, %'zu, %d) → %d% m", addr, length, advice, rc); + return rc; } diff --git a/libc/calls/mkdirat.c b/libc/calls/mkdirat.c index 29ccaedb464..b34f8341880 100644 --- a/libc/calls/mkdirat.c +++ b/libc/calls/mkdirat.c @@ -19,6 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/consts/at.h" @@ -38,13 +39,16 @@ * @see makedirs() */ int mkdirat(int dirfd, const char *path, unsigned mode) { - if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); - if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) { - return -1; /* TODO(jart): implement me */ - } - if (!IsWindows()) { - return sys_mkdirat(dirfd, path, mode); + int rc; + if (IsAsan() && !__asan_is_valid(path, 1)) { + rc = efault(); + } else if (weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) { + STRACE("zipos mkdirat not supported yet"); + } else if (!IsWindows()) { + rc = sys_mkdirat(dirfd, path, mode); } else { - return sys_mkdirat_nt(dirfd, path, mode); + rc = sys_mkdirat_nt(dirfd, path, mode); } + STRACE("mkdirat(%d, %#s, %#o) → %d% m", dirfd, path, mode, rc); + return rc; } diff --git a/libc/calls/mknod.c b/libc/calls/mknod.c index 33b13d598c8..63d2b971569 100644 --- a/libc/calls/mknod.c +++ b/libc/calls/mknod.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/consts/s.h" @@ -38,14 +39,17 @@ * @asyncsignalsafe */ int mknod(const char *path, uint32_t mode, uint64_t dev) { + int rc; if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); if (mode & S_IFREG) return creat(path, mode & ~S_IFREG); if (mode & S_IFDIR) return mkdir(path, mode & ~S_IFDIR); if (mode & S_IFIFO) return mkfifo(path, mode & ~S_IFIFO); if (!IsWindows()) { /* TODO(jart): Whys there code out there w/ S_xxx passed via dev? */ - return sys_mknod(path, mode, dev); + rc = sys_mknod(path, mode, dev); } else { - return enosys(); + rc = enosys(); } + STRACE("mknod(%#s, %#o, %#lx) → %d% m", path, mode, dev, rc); + return rc; } diff --git a/libc/calls/mkntpath.c b/libc/calls/mkntpath.c index 0f60e65ff52..85248baadd1 100644 --- a/libc/calls/mkntpath.c +++ b/libc/calls/mkntpath.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" #include "libc/calls/ntmagicpaths.internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/nt/systeminfo.h" #include "libc/str/oldutf16.internal.h" #include "libc/str/str.h" @@ -76,8 +76,8 @@ textwindows int __mkntpath2(const char *path, * 4. Reserve ≥10 for CreateNamedPipe "\\.\pipe\" prefix requirement * 5. Reserve ≥13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0" */ - char *q; char16_t *p; + const char *q; size_t i, n, m, z; if (!path) return efault(); path = FixNtMagicPath(path, flags); @@ -96,7 +96,7 @@ textwindows int __mkntpath2(const char *path, } n = tprecode8to16(p, z, q).ax; if (n == z - 1) { - SYSDEBUG("path too long for windows: %s", path); + STRACE("path too long for windows: %#s", path); return enametoolong(); } for (i = 0; i < n; ++i) { diff --git a/libc/calls/mkntpathat.c b/libc/calls/mkntpathat.c index a2f4e2cef42..7dc8f49b70a 100644 --- a/libc/calls/mkntpathat.c +++ b/libc/calls/mkntpathat.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/macros.internal.h" #include "libc/nt/files.h" #include "libc/str/str.h" @@ -35,7 +35,7 @@ int __mkntpathat(int dirfd, const char *path, int flags, kNtFileNameNormalized | kNtVolumeNameDos); if (!dirlen) return __winerr(); if (dirlen + 1 + filelen + 1 > ARRAYLEN(dir)) { - SYSDEBUG("path too long: %.*hs\\%.*hs", dirlen, dir, filelen, file); + STRACE("path too long: %#.*hs\\%#.*hs", dirlen, dir, filelen, file); return enametoolong(); } dir[dirlen] = u'\\'; diff --git a/libc/runtime/mman.greg.c b/libc/calls/mman.greg.c similarity index 100% rename from libc/runtime/mman.greg.c rename to libc/calls/mman.greg.c diff --git a/libc/runtime/mremap-sysv.c b/libc/calls/mremap-sysv.greg.c similarity index 85% rename from libc/runtime/mremap-sysv.c rename to libc/calls/mremap-sysv.greg.c index 76303f16143..83e5dd297c9 100644 --- a/libc/runtime/mremap-sysv.c +++ b/libc/calls/mremap-sysv.greg.c @@ -18,10 +18,19 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" #include "libc/calls/calls.h" +#include "libc/calls/strace.internal.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/mremap.h" #include "libc/sysv/errfuns.h" +/** + * Relocates memory. + * + * This function lets you move to to different addresses witohut copying + * it. This system call is currently supported on Linux and NetBSD. Your + * C library runtime won't have any awareness of this memory, so certain + * features like ASAN memory safety and kprintf() won't work as well. + */ privileged void *sys_mremap(void *p, size_t n, size_t m, int f, void *q) { bool cf; uintptr_t rax, rdi, rsi, rdx; @@ -43,7 +52,7 @@ privileged void *sys_mremap(void *p, size_t n, size_t m, int f, void *q) { asm(CFLAG_ASM("syscall") : CFLAG_CONSTRAINT(cf), "+a"(rax) : "D"(p), "S"(n), "d"(q), "r"(r10), "r"(r8) - : "rcx", "r11", "memory", "cc"); + : "rcx", "r9", "r11", "memory", "cc"); if (cf) errno = rax, rax = -1; } else { rax = einval(); @@ -51,5 +60,6 @@ privileged void *sys_mremap(void *p, size_t n, size_t m, int f, void *q) { } else { rax = enosys(); } + STRACE("sys_mremap(%p, %'zu, %'zu, %#b, %p) → %p% m", p, n, m, f, q, rax); return (void *)rax; } diff --git a/libc/runtime/munmap-metal.c b/libc/calls/munmap-metal.c similarity index 100% rename from libc/runtime/munmap-metal.c rename to libc/calls/munmap-metal.c diff --git a/libc/runtime/munmap-sysv.c b/libc/calls/munmap-sysv.c similarity index 93% rename from libc/runtime/munmap-sysv.c rename to libc/calls/munmap-sysv.c index c4db57ac61f..2d93337dad0 100644 --- a/libc/runtime/munmap-sysv.c +++ b/libc/calls/munmap-sysv.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.internal.h" @@ -28,7 +28,7 @@ int sys_munmap(void *p, size_t n) { } else { rc = sys_munmap_metal(p, n); } - SYSDEBUG("sys_munmap(0x%p%s, 0x%x) -> %d", p, - DescribeFrame((intptr_t)p >> 16), n, (long)rc); + STRACE("sys_munmap(%p%s, %'zu) → %d", p, DescribeFrame((intptr_t)p >> 16), n, + rc); return rc; } diff --git a/libc/calls/ntaccesscheck.c b/libc/calls/ntaccesscheck.c index 79104c1c338..07f3a72a1a5 100644 --- a/libc/calls/ntaccesscheck.c +++ b/libc/calls/ntaccesscheck.c @@ -19,7 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/mem/mem.h" #include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/securityimpersonationlevel.h" @@ -87,24 +87,24 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) { if (result || flags == F_OK) { rc = 0; } else { - SYSDEBUG("ntaccesscheck finale failed %d %d", result, flags); + STRACE("ntaccesscheck finale failed %d %d", result, flags); rc = eacces(); } } else { rc = __winerr(); - SYSDEBUG("AccessCheck failed: %m"); + STRACE("%s failed: %m", "AccessCheck"); } } else { rc = __winerr(); - SYSDEBUG("DuplicateToken failed: %m"); + STRACE("%s failed: %m", "DuplicateToken"); } } else { rc = __winerr(); - SYSDEBUG("OpenProcessToken failed: %m"); + STRACE("%s failed: %m", "OpenProcessToken"); } } else { e = GetLastError(); - SYSDEBUG("GetFileSecurity failed: %d %d", e, secsize); + STRACE("GetFileSecurity failed: %d %u", e, secsize); if (!IsTiny() && e == kNtErrorInsufficientBuffer) { if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) { s = freeme; diff --git a/libc/calls/ntspawn.c b/libc/calls/ntspawn.c index a9f30a27ad0..6f53b38d156 100644 --- a/libc/calls/ntspawn.c +++ b/libc/calls/ntspawn.c @@ -19,7 +19,7 @@ #include "libc/bits/pushpop.h" #include "libc/calls/internal.h" #include "libc/calls/ntspawn.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/macros.internal.h" #include "libc/nt/enum/filemapflags.h" #include "libc/nt/enum/pageflags.h" @@ -95,7 +95,7 @@ textwindows int ntspawn( } else { __winerr(); } - SYSDEBUG("CreateProcess(`%hs`, `%hs`) -> %d", prog16, block->cmdline, rc); + STRACE("CreateProcess(%#hs, %#hs) → %d% m", prog16, block->cmdline, rc); } } else { __winerr(); diff --git a/libc/calls/openat.c b/libc/calls/openat.c index 501f54d0a2f..00f1ad72910 100644 --- a/libc/calls/openat.c +++ b/libc/calls/openat.c @@ -19,7 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/log/log.h" @@ -73,8 +73,7 @@ int openat(int dirfd, const char *file, int flags, ...) { } else { rc = efault(); } - SYSDEBUG("openat(%d, %s, %d, %d) -> %d %s", (long)dirfd, file, flags, - (flags & (O_CREAT | O_TMPFILE)) ? mode : 0, (long)rc, - rc == -1 ? strerror(errno) : ""); + STRACE("openat(%d, %#s, %#x, %#o) → %d% m", dirfd, file, flags, + (flags & (O_CREAT | O_TMPFILE)) ? mode : 0, rc); return rc; } diff --git a/libc/calls/pause.c b/libc/calls/pause.c index 1ce657307f5..81ef62957e6 100644 --- a/libc/calls/pause.c +++ b/libc/calls/pause.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/sigset.h" #include "libc/errno.h" #include "libc/sysv/consts/sig.h" @@ -36,6 +37,7 @@ int pause(void) { int rc, olderr; sigset_t oldmask; olderr = errno; + STRACE("pause()"); if ((rc = sys_pause()) == -1 && errno == ENOSYS) { errno = olderr; if (sigprocmask(SIG_BLOCK, NULL, &oldmask) == -1) return -1; diff --git a/libc/calls/program_executable_name.c b/libc/calls/program_executable_name.c index 38845cf9739..97ecf0468cb 100644 --- a/libc/calls/program_executable_name.c +++ b/libc/calls/program_executable_name.c @@ -20,7 +20,7 @@ #include "libc/bits/bits.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/log/libfatal.internal.h" @@ -125,7 +125,7 @@ textstartup void program_executable_name_init(int argc, char **argv, GetProgramExecutableName(executable, argv[0], auxv); errno = e; __stpcpy(program_executable_name, executable); - SYSDEBUG("program_executable_name → %#s", program_executable_name); + STRACE("program_executable_name → %#s", program_executable_name); } const void *const program_executable_name_init_ctor[] initarray = { diff --git a/libc/calls/readlinkat-nt.c b/libc/calls/readlinkat-nt.c index 13300dacaa5..ade68047171 100644 --- a/libc/calls/readlinkat-nt.c +++ b/libc/calls/readlinkat-nt.c @@ -20,7 +20,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/bsr.h" #include "libc/nt/createfile.h" @@ -39,7 +39,7 @@ static textwindows ssize_t sys_readlinkat_nt_error(void) { uint32_t e; e = GetLastError(); - SYSDEBUG("sys_readlinkat_nt() error %d", e); + STRACE("sys_readlinkat_nt() error %d", e); switch (e) { case kNtErrorNotAReparsePoint: return einval(); @@ -56,11 +56,11 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf, uint64_t w; wint_t x, y; void *freeme; - uint32_t e, i, j, n, mem; + uint32_t i, j, n, mem; char16_t path16[PATH_MAX], *p; struct NtReparseDataBuffer *rdb; if (__mkntpathat(dirfd, path, 0, path16) == -1) { - SYSDEBUG("sys_readlinkat_nt() failed b/c __mkntpathat() failed"); + STRACE("sys_readlinkat_nt() failed b/c __mkntpathat() failed"); return -1; } if (weaken(malloc)) { @@ -72,7 +72,7 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf, rdb = (struct NtReparseDataBuffer *)buf; freeme = 0; } else { - SYSDEBUG("sys_readlinkat_nt() needs bigger buffer malloc() to be yoinked"); + STRACE("sys_readlinkat_nt() needs bigger buffer malloc() to be yoinked"); return enomem(); } if ((h = CreateFile(path16, 0, 0, 0, kNtOpenExisting, @@ -113,20 +113,20 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf, if (freeme || (intptr_t)(buf + j) <= (intptr_t)(p + i)) { rc = j; } else { - SYSDEBUG("sys_readlinkat_nt() too many astral codepoints"); + STRACE("sys_readlinkat_nt() too many astral codepoints"); rc = enametoolong(); } } else { - SYSDEBUG("sys_readlinkat_nt() should have kNtIoReparseTagSymlink"); + STRACE("sys_readlinkat_nt() should have kNtIoReparseTagSymlink"); rc = einval(); } } else { - SYSDEBUG("DeviceIoControl(kNtFsctlGetReparsePoint) failed"); + STRACE("%s failed %m", "DeviceIoControl(kNtFsctlGetReparsePoint)"); rc = sys_readlinkat_nt_error(); } CloseHandle(h); } else { - SYSDEBUG("CreateFile(kNtFileFlagOpenReparsePoint) failed"); + STRACE("%s failed %m", "CreateFile(kNtFileFlagOpenReparsePoint)"); rc = sys_readlinkat_nt_error(); } if (freeme && weaken(free)) { diff --git a/libc/calls/readlinkat.c b/libc/calls/readlinkat.c index 93e4dcf811c..9b946c6a922 100644 --- a/libc/calls/readlinkat.c +++ b/libc/calls/readlinkat.c @@ -19,7 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" @@ -50,18 +50,17 @@ */ ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) { ssize_t bytes; - struct ZiposUri zipname; if ((IsAsan() && !__asan_is_valid(buf, bufsiz)) || (bufsiz && !buf)) { bytes = efault(); - } else if (weaken(__zipos_notat) && __zipos_notat(dirfd, path) == -1) { - SYSDEBUG("TOOD: zipos support for readlinkat"); - bytes = enosys(); /* TODO(jart): code me */ + } else if (weaken(__zipos_notat) && + (bytes = __zipos_notat(dirfd, path)) == -1) { + STRACE("TOOD: zipos support for readlinkat"); } else if (!IsWindows()) { bytes = sys_readlinkat(dirfd, path, buf, bufsiz); } else { bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz); } - SYSDEBUG("readlinkat(%d, %s, 0x%p, 0x%x) -> %d %s", (long)dirfd, path, buf, - bufsiz, bytes, bytes != -1 ? "" : strerror(errno)); + STRACE("readlinkat(%d, %#s, [%#.*s]) → %d% m", dirfd, path, MAX(0, bytes), + buf, bytes); return bytes; } diff --git a/libc/calls/releasefd.c b/libc/calls/releasefd.c index 2708f696870..56316ec6e04 100644 --- a/libc/calls/releasefd.c +++ b/libc/calls/releasefd.c @@ -22,7 +22,7 @@ void __releasefd(int fd) { int x; if (!__vforked && 0 <= fd && fd < g_fds.n) { - g_fds.p[fd].kind = kFdEmpty; + bzero(g_fds.p + fd, sizeof(*g_fds.p)); do { x = g_fds.f; if (fd >= x) break; diff --git a/libc/calls/renameat.c b/libc/calls/renameat.c index f98061d8899..cf7eec9ced6 100644 --- a/libc/calls/renameat.c +++ b/libc/calls/renameat.c @@ -19,6 +19,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/consts/at.h" @@ -36,18 +37,20 @@ */ int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { + int rc; if (IsAsan() && (!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) { - return efault(); - } - if (weaken(__zipos_notat) && - (weaken(__zipos_notat)(olddirfd, oldpath) == -1 || - weaken(__zipos_notat)(newdirfd, newpath) == -1)) { - return -1; /* TODO(jart): implement me */ - } - if (!IsWindows()) { - return sys_renameat(olddirfd, oldpath, newdirfd, newpath); + rc = efault(); + } else if (weaken(__zipos_notat) && + ((rc = __zipos_notat(olddirfd, oldpath)) == -1 || + (rc = __zipos_notat(newdirfd, newpath)) == -1)) { + STRACE("zipos renameat not supported yet"); + } else if (!IsWindows()) { + rc = sys_renameat(olddirfd, oldpath, newdirfd, newpath); } else { - return sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath); + rc = sys_renameat_nt(olddirfd, oldpath, newdirfd, newpath); } + STRACE("renameat(%d, %#s, %d, %#s) → %d% m", olddirfd, oldpath, newdirfd, + newpath, rc); + return rc; } diff --git a/libc/calls/sched_yield.c b/libc/calls/sched_yield.c index c268fa27949..04b744961aa 100644 --- a/libc/calls/sched_yield.c +++ b/libc/calls/sched_yield.c @@ -16,14 +16,15 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/calls/internal.h" #include "libc/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/dce.h" /** * Asks kernel to deschedule thread momentarily. */ int sched_yield(void) { + /* TODO(jart): Add get_sched_yield() so we can STRACE() */ if (!IsWindows()) { return sys_sched_yield(); } else { diff --git a/libc/calls/setrlimit.c b/libc/calls/setrlimit.c index 332efffccfd..ae9e2b12185 100644 --- a/libc/calls/setrlimit.c +++ b/libc/calls/setrlimit.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -32,7 +33,16 @@ * @vforksafe */ int setrlimit(int resource, const struct rlimit *rlim) { - if (resource == 127) return einval(); - if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) return efault(); - return sys_setrlimit(resource, rlim); + int rc; + char buf[64]; + if (resource == 127) { + rc = einval(); + } else if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) { + rc = efault(); + } else { + rc = sys_setrlimit(resource, rlim); + } + STRACE("setrlimit(%s, %s) → %d% m", __strace_rlimit_name(resource), + __strace_rlimit(buf, sizeof(buf), 0, rlim), rc); + return rc; } diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index a8dd0cd49e0..239c9022052 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -21,6 +21,7 @@ #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/sigbits.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/sigaction-freebsd.internal.h" #include "libc/calls/struct/sigaction-linux.internal.h" #include "libc/calls/struct/sigaction-netbsd.h" @@ -129,19 +130,8 @@ static void sigaction_native2cosmo(union metasigaction *sa) { } } -/** - * Installs handler for kernel interrupt, e.g.: - * - * void GotCtrlC(int sig, siginfo_t *si, ucontext_t *ctx); - * struct sigaction sa = {.sa_sigaction = GotCtrlC, - * .sa_flags = SA_RESETHAND|SA_RESTART|SA_SIGINFO}; - * CHECK_NE(-1, sigaction(SIGINT, &sa, NULL)); - * - * @see xsigaction() for a much better api - * @asyncsignalsafe - * @vforksafe - */ -int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) { +static int __sigaction(int sig, const struct sigaction *act, + struct sigaction *oldact) { _Static_assert((sizeof(struct sigaction) > sizeof(struct sigaction_linux) && sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) && sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) && @@ -233,3 +223,25 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) { } return rc; } + +/** + * Installs handler for kernel interrupt, e.g.: + * + * void GotCtrlC(int sig, siginfo_t *si, ucontext_t *ctx); + * struct sigaction sa = {.sa_sigaction = GotCtrlC, + * .sa_flags = SA_RESETHAND|SA_RESTART|SA_SIGINFO}; + * CHECK_NE(-1, sigaction(SIGINT, &sa, NULL)); + * + * @see xsigaction() for a much better api + * @asyncsignalsafe + * @vforksafe + */ +int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) { + int rc; + char buf[2][128]; + rc = __sigaction(sig, act, oldact); + STRACE("sigaction(%s, %s, [%s]) → %d% m", strsignal(sig), + __strace_sigaction(buf[0], sizeof(buf[0]), 0, act), + __strace_sigaction(buf[1], sizeof(buf[1]), rc, oldact), rc); + return rc; +} diff --git a/libc/calls/sigaltstack.c b/libc/calls/sigaltstack.c index 754fe4e9526..3f2a74eb02d 100644 --- a/libc/calls/sigaltstack.c +++ b/libc/calls/sigaltstack.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/metasigaltstack.h" #include "libc/calls/struct/sigaltstack.h" #include "libc/dce.h" @@ -70,37 +71,41 @@ static noasan void sigaltstack2linux(struct sigaltstack *linux, */ noasan int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) { int rc; - void *a, *b; + void *b; + const void *a; struct sigaltstack_bsd bsd; if (IsAsan() && ((old && __asan_check(old, sizeof(*old)).kind) || (neu && (__asan_check(neu, sizeof(*neu)).kind || __asan_check(neu->ss_sp, neu->ss_size).kind)))) { - return efault(); - } - if (IsLinux()) { - a = neu; - b = old; - } else if (IsBsd()) { - if (neu) { - sigaltstack2bsd(&bsd, neu); - a = &bsd; + rc = efault(); + } else if (IsLinux() || IsBsd()) { + if (IsLinux()) { + a = neu; + b = old; } else { - a = 0; + if (neu) { + sigaltstack2bsd(&bsd, neu); + a = &bsd; + } else { + a = 0; + } + if (old) { + b = &bsd; + } else { + b = 0; + } } - if (old) { - b = &bsd; + if ((rc = sys_sigaltstack(a, b)) != -1) { + if (IsBsd() && old) { + sigaltstack2linux(old, &bsd); + } + rc = 0; } else { - b = 0; - } - } else { - return enosys(); - } - if ((rc = sys_sigaltstack(a, b)) != -1) { - if (IsBsd() && old) { - sigaltstack2linux(old, &bsd); + rc = -1; } - return 0; } else { - return -1; + rc = enosys(); } + STRACE("sigaltstack() → %d% m", rc); + return rc; } diff --git a/libc/calls/sigprocmask.c b/libc/calls/sigprocmask.c index e9dd0202c5f..148a351c325 100644 --- a/libc/calls/sigprocmask.c +++ b/libc/calls/sigprocmask.c @@ -18,12 +18,23 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/sigset.h" #include "libc/dce.h" +#include "libc/fmt/itoa.h" #include "libc/intrin/asan.internal.h" #include "libc/str/str.h" +#include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" +static const char *DescribeHow(char buf[12], int how) { + if (how == SIG_BLOCK) return "SIG_BLOCK"; + if (how == SIG_UNBLOCK) return "SIG_UNBLOCK"; + if (how == SIG_SETMASK) return "SIG_SETMASK"; + FormatInt32(buf, how); + return buf; +} + /** * Changes program signal blocking state, e.g.: * @@ -40,25 +51,50 @@ * @vforksafe */ int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) { - int32_t x; - if (IsAsan() && - ((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) || - (opt_out_oldset && - !__asan_is_valid(opt_out_oldset, sizeof(*opt_out_oldset))))) { - return efault(); - } - if (!IsWindows() && !IsOpenbsd()) { - return sys_sigprocmask(how, opt_set, opt_out_oldset, 8); - } else if (IsOpenbsd()) { - if (!opt_set) how = 1; - if (opt_set) opt_set = (sigset_t *)(uintptr_t)(*(uint32_t *)opt_set); - if ((x = sys_sigprocmask(how, opt_set, 0, 0)) != -1) { - if (opt_out_oldset) memcpy(opt_out_oldset, &x, sizeof(x)); - return 0; + int x, rc; + char howbuf[12]; + char buf[2][41]; + sigset_t old, *oldp; + if (!(IsAsan() && + ((opt_set && !__asan_is_valid(opt_set, sizeof(*opt_set))) || + (opt_out_oldset && + !__asan_is_valid(opt_out_oldset, sizeof(*opt_out_oldset)))))) { + if (!IsWindows() && !IsOpenbsd()) { + if (opt_out_oldset) { + bzero(&old, sizeof(old)); + oldp = &old; + } else { + oldp = 0; + } + if (sys_sigprocmask(how, opt_set, oldp, 8) != -1) { + if (opt_out_oldset) { + memcpy(opt_out_oldset, &old, sizeof(old)); + } + rc = 0; + } else { + rc = -1; + } + } else if (IsOpenbsd()) { + if (!opt_set) how = 1; + if (opt_set) opt_set = (sigset_t *)(uintptr_t)(*(uint32_t *)opt_set); + if ((x = sys_sigprocmask(how, opt_set, 0, 0)) != -1) { + if (opt_out_oldset) { + bzero(opt_out_oldset, sizeof(*opt_out_oldset)); + memcpy(opt_out_oldset, &x, sizeof(x)); + } + rc = 0; + } else { + rc = -1; + } } else { - return -1; + if (opt_out_oldset) bzero(opt_out_oldset, sizeof(*opt_out_oldset)); + rc = 0; /* TODO(jart): Implement me! */ } } else { - return 0; /* TODO(jart): Implement me! */ + rc = efault(); } + STRACE("sigprocmask(%s, %s, [%s]) → %d% m", DescribeHow(howbuf, how), + __strace_sigset(buf[0], sizeof(buf[0]), 0, opt_set), + __strace_sigset(buf[1], sizeof(buf[1]), rc, opt_out_oldset), rc); + return rc; } diff --git a/libc/calls/sigsuspend.c b/libc/calls/sigsuspend.c index d699b173dbf..c27c6a8e85f 100644 --- a/libc/calls/sigsuspend.c +++ b/libc/calls/sigsuspend.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/sigset.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" @@ -31,12 +32,18 @@ * @asyncsignalsafe */ int sigsuspend(const sigset_t *ignore) { - unsigned x; - if (IsAsan() && !__asan_is_valid(ignore, sizeof(*ignore))) return efault(); - if (!IsWindows()) { + int rc; + char buf[41]; + if (!ignore || (IsAsan() && !__asan_is_valid(ignore, sizeof(*ignore)))) { + rc = efault(); + } else if (!IsWindows()) { + STRACE("sigsuspend(%s)", __strace_sigset(buf, sizeof(buf), 0, ignore)); if (IsOpenbsd()) ignore = (sigset_t *)(uintptr_t)(*(uint32_t *)ignore); return sys_sigsuspend(ignore, 8); } else { - return enosys(); /* TODO(jart): Implement me! */ + rc = enosys(); /* TODO(jart): Implement me! */ } + STRACE("sigsuspend(%s) → %d% m", __strace_sigset(buf, sizeof(buf), 0, ignore), + rc); + return rc; } diff --git a/libc/calls/sigwinch-nt.c b/libc/calls/sigwinch-nt.c index a9bb56e038d..b62ac6ef0cc 100644 --- a/libc/calls/sigwinch-nt.c +++ b/libc/calls/sigwinch-nt.c @@ -18,8 +18,8 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/winsize.h" -#include "libc/calls/sysdebug.internal.h" #include "libc/errno.h" #include "libc/nt/struct/consolescreenbufferinfoex.h" #include "libc/str/str.h" @@ -38,8 +38,8 @@ textwindows bool _check_sigwinch(struct Fd *fd) { if (old.ws_col != ws.ws_col || old.ws_row != ws.ws_row) { __ws = ws; if (old.ws_col | old.ws_row) { - SYSDEBUG("SIGWINCH %hhu×%hhu → %hhu×%hhu", old.ws_col, old.ws_row, - ws.ws_col, ws.ws_row); + STRACE("SIGWINCH %hhu×%hhu → %hhu×%hhu", old.ws_col, old.ws_row, + ws.ws_col, ws.ws_row); if (__sighandrvas[SIGWINCH] >= kSigactionMinRva) { bzero(&si, sizeof(si)); ((sigaction_f)(_base + __sighandrvas[SIGWINCH]))(SIGWINCH, &si, 0); diff --git a/libc/calls/strace.internal.h b/libc/calls/strace.internal.h new file mode 100644 index 00000000000..1e2e9ecc1c1 --- /dev/null +++ b/libc/calls/strace.internal.h @@ -0,0 +1,34 @@ +#ifndef COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_ +#define COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_ +#include "libc/calls/struct/rlimit.h" +#include "libc/calls/struct/sigaction.h" +#include "libc/calls/struct/stat.h" + +#define STRACE_PROLOGUE "%rSYS %5P %'18T " + +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +#ifdef SYSDEBUG +#define STRACE(FMT, ...) \ + do { \ + if (__strace > 0) { \ + __stracef(STRACE_PROLOGUE FMT "%n", ##__VA_ARGS__); \ + } \ + } while (0) +#else +#define STRACE(FMT, ...) (void)0 +#endif + +extern int __strace; + +void __stracef(const char *, ...); +const char *__strace_stat(int, const struct stat *); +const char *__strace_sigaction(char *, size_t, int, const struct sigaction *); +const char *__strace_sigset(char[41], size_t, int, const sigset_t *); +const char *__strace_rlimit_name(int); +const char *__strace_rlimit(char[41], size_t, int, const struct rlimit *); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_ */ diff --git a/libc/calls/strace_rlimit.c b/libc/calls/strace_rlimit.c new file mode 100644 index 00000000000..58b4aea71fb --- /dev/null +++ b/libc/calls/strace_rlimit.c @@ -0,0 +1,40 @@ +/*-*- 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/calls/strace.internal.h" +#include "libc/calls/struct/rlimit.h" +#include "libc/fmt/itoa.h" +#include "libc/intrin/kprintf.h" +#include "libc/sysv/consts/rlimit.h" + +const char *__strace_rlimit_name(int resource) { + static char buf[12]; + if (resource == RLIMIT_AS) return "RLIMIT_AS"; + if (resource == RLIMIT_CPU) return "RLIMIT_CPU"; + if (resource == RLIMIT_FSIZE) return "RLIMIT_FSIZE"; + FormatInt32(buf, resource); + return buf; +} + +privileged const char *__strace_rlimit(char buf[64], size_t bufsize, int rc, + const struct rlimit *rlim) { + if (rc == -1) return "n/a"; + if (!rlim) return "NULL"; + ksnprintf(buf, bufsize, "{%'lu, %'lu}", rlim->rlim_cur, rlim->rlim_max); + return buf; +} diff --git a/libc/calls/strace_sigaction.greg.c b/libc/calls/strace_sigaction.greg.c new file mode 100644 index 00000000000..e34df149b88 --- /dev/null +++ b/libc/calls/strace_sigaction.greg.c @@ -0,0 +1,31 @@ +/*-*- 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/calls/strace.internal.h" +#include "libc/intrin/kprintf.h" + +privileged const char *__strace_sigaction(char *buf, size_t bufsize, int rc, + const struct sigaction *sa) { + char maskbuf[41]; + if (rc == -1) return "n/a"; + if (!sa) return "NULL"; + ksnprintf(buf, bufsize, "{.sa_handler=%p, .sa_flags=%#lx, .sa_mask=%s}", + sa->sa_handler, sa->sa_flags, + __strace_sigset(maskbuf, sizeof(maskbuf), rc, &sa->sa_mask)); + return buf; +} diff --git a/libc/calls/strace_sigset.greg.c b/libc/calls/strace_sigset.greg.c new file mode 100644 index 00000000000..f083d75c63d --- /dev/null +++ b/libc/calls/strace_sigset.greg.c @@ -0,0 +1,28 @@ +/*-*- 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/calls/strace.internal.h" +#include "libc/intrin/kprintf.h" + +privileged const char *__strace_sigset(char buf[41], size_t bufsize, int rc, + const sigset_t *ss) { + if (rc == -1) return "n/a"; + if (!ss) return "NULL"; + ksnprintf(buf, bufsize, "{%#lx, %#lx}", ss->__bits[0], ss->__bits[1]); + return buf; +} diff --git a/libc/calls/strace_stat.greg.c b/libc/calls/strace_stat.greg.c new file mode 100644 index 00000000000..475e2c0234a --- /dev/null +++ b/libc/calls/strace_stat.greg.c @@ -0,0 +1,29 @@ +/*-*- 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/calls/strace.internal.h" +#include "libc/intrin/kprintf.h" + +privileged const char *__strace_stat(int rc, const struct stat *st) { + static char buf[256]; + if (rc == -1) return "n/a"; + if (!st) return "NULL"; + ksnprintf(buf, sizeof(buf), "{.st_size=%'ld, .st_mode=%#o, .st_ino=%'lu}", + st->st_size, st->st_mode, st->st_ino); + return buf; +} diff --git a/libc/calls/sysdebug.internal.h b/libc/calls/sysdebug.internal.h deleted file mode 100644 index bc9efeb3c8b..00000000000 --- a/libc/calls/sysdebug.internal.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_ -#define COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_ -#include "libc/log/libfatal.internal.h" - -#ifndef DEBUGSYS -#define DEBUGSYS 0 -#endif - -#if DEBUGSYS -#define SYSDEBUG(FMT, ...) kprintf("SYS: " FMT "\n", ##__VA_ARGS__) -#else -#define SYSDEBUG(FMT, ...) (void)0 -#endif - -#endif /* COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_ */ diff --git a/libc/calls/wait4-nt.c b/libc/calls/wait4-nt.c index a5fa862c2e7..a55a4a46ec7 100644 --- a/libc/calls/wait4-nt.c +++ b/libc/calls/wait4-nt.c @@ -19,8 +19,8 @@ #include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/rusage.h" -#include "libc/calls/sysdebug.internal.h" #include "libc/fmt/conv.h" #include "libc/macros.internal.h" #include "libc/nt/accounting.h" @@ -71,12 +71,12 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options, i = WaitForMultipleObjects(count, handles, false, -1); } if (i == kNtWaitFailed) { - SYSDEBUG("WaitForMultipleObjects failed %d", GetLastError()); + STRACE("%s failed %u", "WaitForMultipleObjects", GetLastError()); return __winerr(); } assert(__isfdkind(pids[i], kFdProcess)); if (!GetExitCodeProcess(handles[i], &dwExitCode)) { - SYSDEBUG("GetExitCodeProcess failed %d", GetLastError()); + STRACE("%s failed %u", "GetExitCodeProcess", GetLastError()); return __winerr(); } if (dwExitCode == kNtStillActive) continue; @@ -92,7 +92,7 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options, opt_out_rusage->ru_stime = WindowsDurationToTimeVal(ReadFileTime(kernelfiletime)); } else { - SYSDEBUG("GetProcessTimes failed %d", GetLastError()); + STRACE("%s failed %u", "GetProcessTimes", GetLastError()); } } CloseHandle(g_fds.p[pids[i]].handle); diff --git a/libc/calls/wait4.c b/libc/calls/wait4.c index f74f75c6b62..a6c83dcacd3 100644 --- a/libc/calls/wait4.c +++ b/libc/calls/wait4.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/wait4.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" @@ -38,21 +38,20 @@ */ int wait4(int pid, int *opt_out_wstatus, int options, struct rusage *opt_out_rusage) { - int rc, ws; + int rc, ws = 0; if (IsAsan() && ((opt_out_wstatus && !__asan_is_valid(opt_out_wstatus, sizeof(*opt_out_wstatus))) || (opt_out_rusage && !__asan_is_valid(opt_out_rusage, sizeof(*opt_out_rusage))))) { - return efault(); - } - ws = 0; - if (!IsWindows()) { + rc = efault(); + } else if (!IsWindows()) { rc = sys_wait4(pid, &ws, options, opt_out_rusage); } else { rc = sys_wait4_nt(pid, &ws, options, opt_out_rusage); } - SYSDEBUG("waitpid(%d, [0x%x], %d) -> [%d]", pid, ws, options, rc); - if (opt_out_wstatus) *opt_out_wstatus = ws; + if (rc != -1 && opt_out_wstatus) *opt_out_wstatus = ws; + STRACE("wait4(%d, [%#x], %d, %p) → %d% m", pid, ws, options, opt_out_rusage, + rc); return rc; } diff --git a/libc/calls/wincrash.c b/libc/calls/wincrash.c index 32259c4d1dc..62aa0b55ccf 100644 --- a/libc/calls/wincrash.c +++ b/libc/calls/wincrash.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/typedef/sigaction_f.h" #include "libc/calls/ucontext.h" #include "libc/nt/enum/exceptionhandleractions.h" @@ -31,7 +31,7 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) { ucontext_t ctx; struct siginfo si; } g; - SYSDEBUG("__wincrash"); + STRACE("__wincrash"); switch (ep->ExceptionRecord->ExceptionCode) { case kNtSignalBreakpoint: sig = SIGTRAP; diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index 73a0879fa04..3ce36c7eff2 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -23,6 +23,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/iovec.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" @@ -1378,6 +1379,7 @@ textstartup void __asan_init(int argc, char **argv, char **envp, __asan_shadow_string_list(envp); __asan_shadow_auxv(auxv); __asan_install_malloc_hooks(); + STRACE("cosmopolitan memory safety module initialized"); } static textstartup void __asan_ctor(void) { diff --git a/libc/intrin/exit.greg.c b/libc/intrin/exit.greg.c index a0a77023891..86ca692bb17 100644 --- a/libc/intrin/exit.greg.c +++ b/libc/intrin/exit.greg.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #define ShouldUseMsabiAttribute() 1 #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/kprintf.h" #include "libc/nexgen32e/vendor.internal.h" @@ -37,6 +38,7 @@ * @noreturn */ privileged noinstrument noasan noubsan wontreturn void _Exit(int exitcode) { + STRACE("_Exit(%d)", exitcode); if ((!IsWindows() && !IsMetal()) || (IsMetal() && IsGenuineCosmo())) { asm volatile("syscall" : /* no outputs */ diff --git a/libc/intrin/getenv.c b/libc/intrin/getenv.c index 3aa83de4a48..d6e3e6eb44e 100644 --- a/libc/intrin/getenv.c +++ b/libc/intrin/getenv.c @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/runtime/runtime.h" @@ -63,6 +63,6 @@ char *getenv(const char *s) { } else { r = GetEnv(s, ToUpper); } - SYSDEBUG("getenv(%#s) → %#s", s, r); + STRACE("getenv(%#s) → %#s", s, r); return r; } diff --git a/libc/intrin/psrldq.c b/libc/intrin/psrldq.c index 505d870e169..9ed38136adc 100644 --- a/libc/intrin/psrldq.c +++ b/libc/intrin/psrldq.c @@ -27,7 +27,6 @@ * @mayalias */ void(psrldq)(uint8_t b[16], const uint8_t a[16], unsigned long n) { - unsigned i; if (n > 16) n = 16; __builtin_memcpy(b, a + n, 16 - n); __builtin_memset(b + (16 - n), 0, n); diff --git a/libc/intrin/quick_exit.c b/libc/intrin/quick_exit.c index 54e37e1729f..1970c534cba 100644 --- a/libc/intrin/quick_exit.c +++ b/libc/intrin/quick_exit.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/weaken.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/nt/console.h" #include "libc/nt/runtime.h" @@ -35,6 +36,7 @@ const char kConsoleHandles[2] = {kNtStdInputHandle, kNtStdOutputHandle}; wontreturn void quick_exit(int exitcode) { int i; const uintptr_t *p; + STRACE("quick_exit(%d)", exitcode); if (weaken(fflush)) { weaken(fflush)(0); } diff --git a/libc/intrin/somanyasan.S b/libc/intrin/somanyasan.S index 41d41d4c43a..a473f4a8bc1 100644 --- a/libc/intrin/somanyasan.S +++ b/libc/intrin/somanyasan.S @@ -184,7 +184,7 @@ __asan_version_mismatch_check_v8: .endfn __asan_version_mismatch_check_v8,globl // Initializes Address Sanitizer runtime earlier if linked. - .init.start 301,_init_asan + .init.start 303,_init_asan push %rdi push %rsi mov %r12,%rdi @@ -194,7 +194,7 @@ __asan_version_mismatch_check_v8: call __asan_init pop %rsi pop %rdi - .init.end 301,_init_asan + .init.end 303,_init_asan __asan_before_dynamic_init: push %rbp diff --git a/libc/intrin/stracef.greg.c b/libc/intrin/stracef.greg.c new file mode 100644 index 00000000000..ab5fbc4fe8d --- /dev/null +++ b/libc/intrin/stracef.greg.c @@ -0,0 +1,28 @@ +/*-*- 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/calls/strace.internal.h" +#include "libc/intrin/kprintf.h" + +privileged void __stracef(const char *fmt, ...) { + va_list v; + if (__strace <= 0) return; + va_start(v, fmt); + kvprintf(fmt, v); + va_end(v); +} diff --git a/libc/log/libfatal.internal.h b/libc/log/libfatal.internal.h index 7e8a77a5ddf..f53aad990a5 100644 --- a/libc/log/libfatal.internal.h +++ b/libc/log/libfatal.internal.h @@ -242,6 +242,26 @@ forceinline char *__strstr(const char *haystack, const char *needle) { return 0; } +forceinline char *__getenv(char **p, const char *s) { + size_t i, j; + if (p) { + for (i = 0; p[i]; ++i) { + for (j = 0;; ++j) { + if (!s[j]) { + if (p[i][j] == '=') { + return p[i] + j + 1; + } + break; + } + if ((s[j] & 255) != __ToUpper(p[i][j] & 255)) { + break; + } + } + } + } + return 0; +} + forceinline const char *__strchr(const char *s, unsigned char c) { char *r; for (;; ++s) { diff --git a/libc/mem/putenv.c b/libc/mem/putenv.c index b2f6c41a978..27ff7724037 100644 --- a/libc/mem/putenv.c +++ b/libc/mem/putenv.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/alg/alg.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/macros.internal.h" #include "libc/mem/internal.h" @@ -121,6 +121,6 @@ void __freeenv(void *p) { int putenv(char *s) { int rc; rc = PutEnvImpl(strdup(s), true); - SYSDEBUG("putenv(%#s) → %d", s, rc); + STRACE("putenv(%#s) → %d", s, rc); return rc; } diff --git a/libc/mem/setenv.c b/libc/mem/setenv.c index c7e24ff260b..bb9c33cdcd3 100644 --- a/libc/mem/setenv.c +++ b/libc/mem/setenv.c @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/mem/internal.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" @@ -37,6 +37,6 @@ int setenv(const char *name, const char *value, int overwrite) { s = malloc(namelen + valuelen + 2); memcpy(mempcpy(mempcpy(s, name, namelen), "=", 1), value, valuelen + 1); rc = PutEnvImpl(s, overwrite); - SYSDEBUG("setenv(%#s, %#s, %d) → %d", name, value, overwrite, rc); + STRACE("setenv(%#s, %#s, %d) → %d", name, value, overwrite, rc); return rc; } diff --git a/libc/runtime/arememoryintervalsok.c b/libc/runtime/arememoryintervalsok.c index 8c20eb62304..1a4969a1438 100644 --- a/libc/runtime/arememoryintervalsok.c +++ b/libc/runtime/arememoryintervalsok.c @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/runtime/memtrack.internal.h" noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) { @@ -24,7 +24,7 @@ noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) { int i; for (i = 0; i < mm->i; ++i) { if (mm->p[i].y < mm->p[i].x) { - SYSDEBUG("AreMemoryIntervalsOk() y should be >= x!"); + STRACE("AreMemoryIntervalsOk() y should be >= x!"); return false; } if (i) { @@ -34,7 +34,7 @@ noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) { } } else { if (!(mm->p[i - 1].y + 1 <= mm->p[i].x)) { - SYSDEBUG("AreMemoryIntervalsOk() out of order or overlap!"); + STRACE("AreMemoryIntervalsOk() out of order or overlap!"); return false; } } diff --git a/libc/runtime/clearenv.c b/libc/runtime/clearenv.c index 46308f92a19..c37f1fb5349 100644 --- a/libc/runtime/clearenv.c +++ b/libc/runtime/clearenv.c @@ -16,12 +16,14 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/strace.internal.h" #include "libc/runtime/runtime.h" /** * Removes all environment variables. */ int clearenv(void) { + STRACE("clearenv() → 0"); environ = NULL; return 0; } diff --git a/libc/runtime/cosmo.S b/libc/runtime/cosmo.S index 5760a93b049..f9685696424 100644 --- a/libc/runtime/cosmo.S +++ b/libc/runtime/cosmo.S @@ -21,6 +21,7 @@ #include "libc/notice.inc" #include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/map.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" .text.startup @@ -37,6 +38,10 @@ cosmo: push %rbp mov %rsi,%r13 mov %rdx,%r14 mov %rcx,%r15 +#ifdef SYSDEBUG + call __strace_init + mov %eax,%r12d +#endif /* SYSDEBUG */ #ifdef __FAST_MATH__ push %rax stmxcsr (%rsp) @@ -72,7 +77,7 @@ cosmo: push %rbp .endfn cosmo,weak #ifdef __PG__ - .init.start 800,_init_ftrace + .init.start 306,_init_ftrace push %rdi push %rsi mov %r12d,%edi @@ -86,5 +91,21 @@ cosmo: push %rbp mov %eax,%r12d pop %rsi pop %rdi - .init.end 800,_init_ftrace + .init.end 306,_init_ftrace +#endif + +#if IsModeDbg() +#ifdef SYSDEBUG + .init.start 307,_init_printargs + push %rdi + push %rsi + mov %r12d,%edi + mov %r13,%rsi + mov %r14,%rdx + mov %r15,%rcx + call __printargs + pop %rsi + pop %rdi + .init.end 307,_init_printargs +#endif #endif diff --git a/libc/runtime/dsohandle.S b/libc/runtime/dsohandle.S index 6e9d6d6aec8..136dd405bdc 100644 --- a/libc/runtime/dsohandle.S +++ b/libc/runtime/dsohandle.S @@ -19,7 +19,9 @@ #include "libc/macros.internal.h" #include "libc/notice.inc" + .underrun // Uniquely identifies each artifact linked in an address space. __dso_handle: .quad __dso_handle .endobj __dso_handle,globl,hidden + .overrun diff --git a/libc/runtime/exit.c b/libc/runtime/exit.c index 6818ff1fcc3..3dcaad2ce10 100644 --- a/libc/runtime/exit.c +++ b/libc/runtime/exit.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/weaken.h" +#include "libc/calls/strace.internal.h" #include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" @@ -32,6 +33,7 @@ * @noreturn */ wontreturn void exit(int exitcode) { + STRACE("exit(%d)", exitcode); if (weaken(__cxa_finalize)) { weaken(__cxa_finalize)(NULL); } diff --git a/libc/runtime/finddebugbinary.c b/libc/runtime/finddebugbinary.c index 5df30e39d21..72c87233c42 100644 --- a/libc/runtime/finddebugbinary.c +++ b/libc/runtime/finddebugbinary.c @@ -22,46 +22,37 @@ #include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" -static char *g_comdbg; -static char g_comdbg_buf[PATH_MAX + 1]; - -static optimizesize textstartup void g_comdbg_init() { +/** + * Returns path of binary with the debug information, or null. + * + * @return path to debug binary, or NULL + */ +const char *FindDebugBinary(void) { + static bool once; + static char *res; + static char buf[PATH_MAX + 1]; char *p; size_t n; - static bool once; if (!once) { - if (!(g_comdbg = getenv("COMDBG"))) { + if (!(res = getenv("COMDBG"))) { p = program_executable_name; n = strlen(p); if (n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) { - g_comdbg = p; + res = p; } else if (n > 4 && READ32LE(p + n - 4) == READ32LE(".com") && n + 4 <= PATH_MAX) { - mempcpy(mempcpy(g_comdbg_buf, p, n), ".dbg", 5); - if (fileexists(g_comdbg_buf)) { - g_comdbg = g_comdbg_buf; + mempcpy(mempcpy(buf, p, n), ".dbg", 5); + if (fileexists(buf)) { + res = buf; } } else if (n + 8 <= PATH_MAX) { - mempcpy(mempcpy(g_comdbg_buf, p, n), ".com.dbg", 9); - if (fileexists(g_comdbg_buf)) { - g_comdbg = g_comdbg_buf; + mempcpy(mempcpy(buf, p, n), ".com.dbg", 9); + if (fileexists(buf)) { + res = buf; } } } once = true; } + return res; } - -/** - * Returns path of binary with the debug information, or null. - * - * @return path to debug binary, or NULL - */ -const char *FindDebugBinary(void) { - g_comdbg_init(); - return g_comdbg; -} - -const void *const g_comdbg_ctor[] initarray = { - g_comdbg_init, -}; diff --git a/libc/runtime/fork-nt.c b/libc/runtime/fork-nt.c index c455c792c53..7aefaa140f2 100644 --- a/libc/runtime/fork-nt.c +++ b/libc/runtime/fork-nt.c @@ -21,7 +21,7 @@ #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/ntspawn.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/fmt/itoa.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/nt2sysv.h" @@ -60,7 +60,7 @@ static textwindows noasan char16_t *ParseInt(char16_t *p, int64_t *x) { } static dontinline textwindows noasan bool ForkIo(int64_t h, void *buf, size_t n, - bool32 (*f)()) { + bool32 (*f)()) { char *p; size_t i; uint32_t x; @@ -73,17 +73,15 @@ static dontinline textwindows noasan bool ForkIo(int64_t h, void *buf, size_t n, } static dontinline textwindows noasan void WriteAll(int64_t h, void *buf, - size_t n) { - if (!ForkIo(h, buf, n, WriteFile)) { - SYSDEBUG("fork() WriteFile(%zu) failed %d\n", n, GetLastError()); - } + size_t n) { + bool rc = ForkIo(h, buf, n, WriteFile); + STRACE("%s(%ld, %'zu) %d% m", "WriteFile", h, n); } static textwindows dontinline noasan void ReadAll(int64_t h, void *buf, - size_t n) { - if (!ForkIo(h, buf, n, ReadFile)) { - SYSDEBUG("fork() ReadFile(%zu) failed %d\n", n, GetLastError()); - } + size_t n) { + bool rc = ForkIo(h, buf, n, ReadFile); + STRACE("%s(%ld, %'zu) %d% m", "ReadFile", h, n); } textwindows noasan noinstrument void WinMainForked(void) { @@ -99,6 +97,7 @@ textwindows noasan noinstrument void WinMainForked(void) { varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var)); if (!varlen) return; if (varlen >= ARRAYLEN(var)) ExitProcess(123); + STRACE("WinMainForked()"); SetEnvironmentVariable(u"_FORK", NULL); ParseInt(ParseInt(var, &reader), &writer); ReadAll(reader, jb, sizeof(jb)); diff --git a/libc/runtime/fork.c b/libc/runtime/fork.c index 5d47e474ac7..14a94670bdf 100644 --- a/libc/runtime/fork.c +++ b/libc/runtime/fork.c @@ -20,7 +20,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/nt/process.h" @@ -55,12 +55,12 @@ int fork(void) { } parent = __pid; __pid = dx; - SYSDEBUG("fork() → 0 (child of %d)", parent); + STRACE("fork() → 0 (child of %d)", parent); if (weaken(__onfork)) { weaken(__onfork)(); } } else { - SYSDEBUG("fork() → %d% m", ax); + STRACE("fork() → %d% m", ax); } return ax; } diff --git a/libc/runtime/ftrace-hook.S b/libc/runtime/ftrace-hook.S index f17c1bb7a00..a679c52b13f 100644 --- a/libc/runtime/ftrace-hook.S +++ b/libc/runtime/ftrace-hook.S @@ -21,7 +21,7 @@ ftrace_hook: cmp $0,g_ftrace(%rip) - je 1f + jg 1f ret 1: push %rbp mov %rsp,%rbp diff --git a/libc/runtime/ftraceinit.c b/libc/runtime/ftraceinit.greg.c similarity index 84% rename from libc/runtime/ftraceinit.c rename to libc/runtime/ftraceinit.greg.c index cd6af1c9ff8..48bbc05aae9 100644 --- a/libc/runtime/ftraceinit.c +++ b/libc/runtime/ftraceinit.greg.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" @@ -31,26 +32,10 @@ * * @see libc/runtime/_init.S for documentation */ -textstartup int ftrace_init(int argc, char *argv[]) { - int i; - bool foundflag; - foundflag = false; - for (i = 1; i <= argc; ++i) { - if (!foundflag) { - if (argv[i]) { - if (strcmp(argv[i], "--ftrace") == 0) { - foundflag = true; - } else if (strcmp(argv[i], "----ftrace") == 0) { - strcpy(argv[i], "--ftrace"); - } - } - } else { - argv[i - 1] = argv[i]; - } - } - if (foundflag) { - --argc; +textstartup int ftrace_init(void) { + if (__intercept_flag(&__argc, __argv, "--ftrace")) { ftrace_install(); + ++g_ftrace; } - return argc; + return __argc; } diff --git a/libc/runtime/interceptflag.greg.c b/libc/runtime/interceptflag.greg.c new file mode 100644 index 00000000000..026ea4dbede --- /dev/null +++ b/libc/runtime/interceptflag.greg.c @@ -0,0 +1,46 @@ +/*-*- 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/log/libfatal.internal.h" +#include "libc/runtime/internal.h" +#include "libc/str/str.h" + +textstartup bool __intercept_flag(int *argc, char *argv[], const char *flag) { + /* asan isn't initialized yet at runlevel 300 */ + char *a; + int i, j; + bool found; + found = false; + for (j = i = 1; i <= *argc;) { + a = argv[j++]; + if (a && !__strcmp(a, flag)) { + found = true; + --*argc; + } else { + /* + * e.g. turns ----strace → --strace for execve. + * todo: update this to allow ------strace etc. + */ + if (a && a[0] == '-' && a[1] == '-' && !__strcmp(a + 2, flag)) { + a = flag; + } + argv[i++] = a; + } + } + return found; +} diff --git a/libc/runtime/internal.h b/libc/runtime/internal.h index 3b0e05e9714..1942922d158 100644 --- a/libc/runtime/internal.h +++ b/libc/runtime/internal.h @@ -27,6 +27,7 @@ long _setstack(void *, void *, ...) hidden; int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden; Elf64_Ehdr *MapElfRead(const char *, struct MappedFile *) hidden; int GetDosEnviron(const char16_t *, char *, size_t, char **, size_t) hidden; +bool __intercept_flag(int *, char *[], const char *); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/runtime/memtrack.c b/libc/runtime/memtrack.c index 127bef8a7e3..a3b2783f9e9 100644 --- a/libc/runtime/memtrack.c +++ b/libc/runtime/memtrack.c @@ -21,7 +21,7 @@ #include "libc/bits/likely.h" #include "libc/bits/weaken.h" #include "libc/calls/calls.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" @@ -76,13 +76,13 @@ static noasan bool ExtendMemoryIntervals(struct MemoryIntervals *mm) { shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000); dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0); if (!dm.addr) { - SYSDEBUG("ExtendMemoryIntervals() fail #1"); + STRACE("ExtendMemoryIntervals() fail #1"); return false; } } dm = sys_mmap(base, gran, prot, flags, -1, 0); if (!dm.addr) { - SYSDEBUG("ExtendMemoryIntervals() fail #2"); + STRACE("ExtendMemoryIntervals() fail #2"); return false; } MoveMemoryIntervals(dm.addr, mm->p, mm->i); @@ -95,13 +95,13 @@ static noasan bool ExtendMemoryIntervals(struct MemoryIntervals *mm) { shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000); dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0); if (!dm.addr) { - SYSDEBUG("ExtendMemoryIntervals() fail #3"); + STRACE("ExtendMemoryIntervals() fail #3"); return false; } } dm = sys_mmap(base, gran, prot, flags, -1, 0); if (!dm.addr) { - SYSDEBUG("ExtendMemoryIntervals() fail #4"); + STRACE("ExtendMemoryIntervals() fail #4"); return false; } mm->n = (size + gran) / sizeof(*mm->p); diff --git a/libc/runtime/memtrack.internal.h b/libc/runtime/memtrack.internal.h index 1fb01f23845..18ae776f124 100644 --- a/libc/runtime/memtrack.internal.h +++ b/libc/runtime/memtrack.internal.h @@ -1,5 +1,6 @@ #ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_ #define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_ +#include "libc/assert.h" #include "libc/dce.h" #include "libc/macros.internal.h" #include "libc/nt/enum/version.h" @@ -164,6 +165,7 @@ forceinline unsigned FindMemoryInterval(const struct MemoryIntervals *mm, r = m; } } + assert(l == mm->i || x <= mm->p[l].y); return l; } @@ -171,7 +173,7 @@ forceinline bool IsMemtracked(int x, int y) { unsigned i; i = FindMemoryInterval(&_mmi, x); if (i == _mmi.i) return false; - if (!(_mmi.p[i].x <= x && x <= _mmi.p[i].y)) return false; + if (x < _mmi.p[i].x) return false; for (;;) { if (y <= _mmi.p[i].y) return true; if (++i == _mmi.i) return false; diff --git a/libc/runtime/memtracknt.c b/libc/runtime/memtracknt.c index f6dc682ca3b..3873f1cfad3 100644 --- a/libc/runtime/memtracknt.c +++ b/libc/runtime/memtracknt.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/nt/memory.h" #include "libc/nt/runtime.h" #include "libc/runtime/memtrack.internal.h" @@ -37,8 +37,8 @@ noasan void ReleaseMemoryNt(struct MemoryIntervals *mm, int l, int r) { for (i = l; i <= r; ++i) { addr = GetFrameAddr(mm->p[i].x); last = GetFrameAddr(mm->p[i].y); - SYSDEBUG("UnmapViewOfFile(addr:0x%x, size:0x%x, hand:0x%x)", addr, - last - addr + FRAMESIZE, mm->p[i].h); + STRACE("UnmapViewOfFile(%p, size:%'zu, hand:%ld)", addr, + last - addr + FRAMESIZE, mm->p[i].h); ok = UnmapViewOfFile(addr); assert(ok); ok = CloseHandle(mm->p[i].h); diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index ee58ac8cf13..0b02674417c 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -21,7 +21,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" @@ -40,7 +40,6 @@ #define IP(X) (intptr_t)(X) #define VIP(X) (void *)IP(X) -#define SMALL(n) ((n) <= 0xffffffffffff) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) #define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16) #define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000) @@ -60,7 +59,7 @@ noasan static bool NeedAutomap(char *p, size_t n) { IsMapped(p, n); } -noasan static bool ChooseInterval(int x, int n, int *res) { +noasan static bool ChooseMemoryInterval(int x, int n, int *res) { int i; if (_mmi.i) { i = FindMemoryInterval(&_mmi, x); @@ -89,18 +88,17 @@ noasan static bool ChooseInterval(int x, int n, int *res) { noasan static bool Automap(int n, int *res) { *res = -1; - if (ChooseInterval(FRAME(kAutomapStart), n, res)) { + if (ChooseMemoryInterval(FRAME(kAutomapStart), n, res)) { assert(*res >= FRAME(kAutomapStart)); if (*res + n <= FRAME(kAutomapStart + (kAutomapStart - 1))) { return true; } else { - SYSDEBUG("mmap(0x%p, 0x%x) ENOMEM (automap interval exhausted)", - ADDR(*res), ADDR(n + 1)); + STRACE("mmap(%.12p, %p) ENOMEM (automap interval exhausted)", ADDR(*res), + ADDR(n + 1)); return false; } } else { - SYSDEBUG("mmap(0x%p, 0x%x) ENOMEM (automap failed)", ADDR(*res), - ADDR(n + 1)); + STRACE("mmap(%.12p, %p) ENOMEM (automap failed)", ADDR(*res), ADDR(n + 1)); return false; } } @@ -111,28 +109,28 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags, dm = sys_mmap(addr, size, prot, f, fd, off); if (UNLIKELY(dm.addr == MAP_FAILED)) { if (IsWindows() && (flags & MAP_FIXED)) { - SYSDEBUG("mmap(0x%p, 0x%x) -> %s (%s)", addr, size, strerror(errno), - "can't recover from MAP_FIXED errors on Windows"); + STRACE("mmap(%.12p, %'ld) → %s (%s)", addr, size, strerror(errno), + "can't recover from MAP_FIXED errors on Windows"); assert(!"MapMemory() failed"); Die(); } return MAP_FAILED; } if (UNLIKELY(dm.addr != addr)) { - SYSDEBUG("KERNEL DIDN'T RESPECT MAP_FIXED"); + STRACE("KERNEL DIDN'T RESPECT MAP_FIXED"); assert(!"MapMemory() failed"); Die(); } if (!IsWindows() && (flags & MAP_FIXED)) { if (UntrackMemoryIntervals(addr, size)) { - SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno)); + STRACE("FIXED UNTRACK FAILED %s", strerror(errno)); assert(!"MapMemory() failed"); Die(); } } if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) { if (sys_munmap(addr, n) == -1) { - SYSDEBUG("TRACK MUNMAP FAILED %s", strerror(errno)); + STRACE("TRACK MUNMAP FAILED %s", strerror(errno)); assert(!"MapMemory() failed"); Die(); } @@ -151,21 +149,21 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags, * punch holes into existing mappings. */ static textwindows dontinline noasan void *MapMemories(char *addr, size_t size, - int prot, int flags, - int fd, int64_t off, int f, - int x, size_t n) { + int prot, int flags, + int fd, int64_t off, + int f, int x, size_t n) { struct DirectMap dm; size_t i, m = (n - 1) * FRAMESIZE; assert(m < size && m + FRAMESIZE >= size); dm = sys_mmap(addr + m, size - m, prot, f, fd, fd == -1 ? 0 : off + m); if (dm.addr == MAP_FAILED) { - SYSDEBUG("MapMemories(%p+%x/%x) %s", addr, m, size, strerror(errno)); + STRACE("MapMemories(%.12p+%lx/%lx) %m", addr, m, size); return MAP_FAILED; } if (TrackMemoryInterval(&_mmi, x + (n - 1), x + (n - 1), dm.maphandle, prot, flags) == -1) { - SYSDEBUG("MapMemories(%p+%x/%x) unrecoverable failure #1 %s", addr, m, size, - strerror(errno)); + STRACE("MapMemories(%.12p+%lx/%lx) unrecoverable failure #1 %m", addr, m, + size); assert(!"MapMemories() failed"); Die(); } @@ -174,8 +172,8 @@ static textwindows dontinline noasan void *MapMemories(char *addr, size_t size, if (dm.addr == MAP_FAILED || TrackMemoryInterval(&_mmi, x + i / FRAMESIZE, x + i / FRAMESIZE, dm.maphandle, prot, flags) == -1) { - SYSDEBUG("MapMemories(%p+%x/%x) unrecoverable failure #2 %s", addr, i, - size, strerror(errno)); + STRACE("MapMemories(%p+%x/%x) unrecoverable failure #2 %m", addr, i, + size); assert(!"MapMemories() failed"); Die(); } @@ -221,56 +219,56 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd, int a, b, i, f, m, n, x; char mode[8], *p = addr; if (UNLIKELY(!size)) { - SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (size=0)", p, size); + STRACE("mmap(%.12p, %'zu) EINVAL (size=0)", p, size); return VIP(einval()); } - if (UNLIKELY(!SMALL(size))) { - SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (size isn't 48-bit)", p, size); + if (UNLIKELY(!IsLegalSize(size))) { + STRACE("mmap(%.12p, %'zu) EINVAL (size isn't 48-bit)", p, size); return VIP(einval()); } if (UNLIKELY(!IsLegalPointer(p))) { - SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, size); + STRACE("mmap(%.12p, %'zu) EINVAL (p isn't 48-bit)", p, size); return VIP(einval()); } if (UNLIKELY(!ALIGNED(p))) { - SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 64kb aligned)", p, size); + STRACE("mmap(%.12p, %'zu) EINVAL (p isn't 64kb aligned)", p, size); return VIP(einval()); } if (UNLIKELY(fd < -1)) { - SYSDEBUG("mmap(0x%p, 0x%x, fd=%d) EBADF", p, size, (long)fd); + STRACE("mmap(%.12p, %'zu, fd=%d) EBADF", p, size, fd); return VIP(ebadf()); } if (UNLIKELY(!((fd != -1) ^ !!(flags & MAP_ANONYMOUS)))) { - SYSDEBUG("mmap(0x%p, 0x%x, %s, %d, %d) EINVAL (fd anonymous mismatch)", p, - size, DescribeMapping(prot, flags, mode), (long)fd, off); + STRACE("mmap(%.12p, %'zu, %s, %d, %'ld) EINVAL (fd anonymous mismatch)", p, + size, DescribeMapping(prot, flags, mode), fd, off); return VIP(einval()); } if (UNLIKELY(!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED)))) { - SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (MAP_SHARED ^ MAP_PRIVATE)", p, size); + STRACE("mmap(%.12p, %'zu) EINVAL (MAP_SHARED ^ MAP_PRIVATE)", p, size); return VIP(einval()); } if (UNLIKELY(off < 0)) { - SYSDEBUG("mmap(0x%p, 0x%x, off=%d) EINVAL (neg off)", p, size, off); + STRACE("mmap(%.12p, %'zu, off=%'ld) EINVAL (neg off)", p, size, off); return VIP(einval()); } if (UNLIKELY(INT64_MAX - size < off)) { - SYSDEBUG("mmap(0x%p, 0x%x, off=%d) EINVAL (too large)", p, size, off); + STRACE("mmap(%.12p, %'zu, off=%'ld) EINVAL (too large)", p, size, off); return VIP(einval()); } if (UNLIKELY(!ALIGNED(off))) { - SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 64kb aligned)", p, size); + STRACE("mmap(%.12p, %'zu) EINVAL (p isn't 64kb aligned)", p, size); return VIP(einval()); } if ((flags & MAP_FIXED_NOREPLACE) && IsMapped(p, size)) { if (OverlapsImageSpace(p, size)) { - SYSDEBUG("mmap(0x%p, 0x%x) EFAULT (overlaps image)", p, size); + STRACE("mmap(%.12p, %'zu) EFAULT (overlaps image)", p, size); } else { - SYSDEBUG("mmap(0x%p, 0x%x) EFAULT (overlaps existing)", p, size); + STRACE("mmap(%.12p, %'zu) EFAULT (overlaps existing)", p, size); } return VIP(efault()); } - SYSDEBUG("mmap(0x%p, 0x%x, %s, %d, %d)", p, size, - DescribeMapping(prot, flags, mode), (long)fd, off); + STRACE("mmap(%.12p, %'zu, %s, %d, %'ld)% m", p, size, + DescribeMapping(prot, flags, mode), fd, off); if (fd == -1) { size = ROUNDUP(size, FRAMESIZE); if (IsWindows()) { @@ -283,7 +281,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd, x = FRAME(p); if (IsWindows()) { if (UntrackMemoryIntervals(p, size)) { - SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno)); + STRACE("FIXED UNTRACK FAILED %m"); assert(!"mmap() failed"); Die(); } diff --git a/libc/runtime/mremap.c b/libc/runtime/mremap.c index dc9b8ead12f..82dad601e93 100644 --- a/libc/runtime/mremap.c +++ b/libc/runtime/mremap.c @@ -21,10 +21,9 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" -#include "libc/log/libfatal.internal.h" #include "libc/macros.internal.h" #include "libc/nt/runtime.h" #include "libc/runtime/directmap.internal.h" @@ -36,7 +35,6 @@ #define IP(X) (intptr_t)(X) #define VIP(X) (void *)IP(X) -#define SMALL(n) ((n) <= 0xffffffffffff) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) #define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16) #define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000) @@ -76,43 +74,44 @@ void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) { size_t i, j, k; struct DirectMap dm; int a, b, prot, flags; + assert(!__vforked); if (UNLIKELY(!m)) { - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (m=0)", p, n, m, f); + STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (m=0)", p, n, m, f); return VIP(einval()); } if (UNLIKELY(!n)) { - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EOPNOTSUPP (n=0)", p, n, m, f); + STRACE("mremap(%p, %'zu, %'zu, %#b) EOPNOTSUPP (n=0)", p, n, m, f); return VIP(eopnotsupp()); } if (UNLIKELY(!ALIGNED(n))) { - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EOPNOTSUPP (n align)", p, n, m, f); + STRACE("mremap(%p, %'zu, %'zu, %#b) EOPNOTSUPP (n align)", p, n, m, f); return VIP(eopnotsupp()); } if (UNLIKELY(!ALIGNED(m))) { - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EOPNOTSUPP (n align)", p, n, m, f); + STRACE("mremap(%p, %'zu, %'zu, %#b) EOPNOTSUPP (n align)", p, n, m, f); return VIP(eopnotsupp()); } if (UNLIKELY(!ALIGNED(p))) { - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (64kb align)", p, n, m, f); + STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (64kb align)", p, n, m, f); return VIP(einval()); } - if (UNLIKELY(!SMALL(n))) { - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (n too big)", p, n, m, f); + if (UNLIKELY(!IsLegalSize(n))) { + STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (n too big)", p, n, m, f); return VIP(enomem()); } - if (UNLIKELY(!SMALL(m))) { - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (m too big)", p, n, m, f); + if (UNLIKELY(!IsLegalSize(m))) { + STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (m too big)", p, n, m, f); return VIP(enomem()); } if (f & ~(MREMAP_MAYMOVE | MREMAP_FIXED)) { - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x) EINVAL (bad flag)", p, n, m, f); + STRACE("mremap(%p, %'zu, %'zu, %#b) EINVAL (bad flag)", p, n, m, f); return VIP(einval()); } if (!IsMemtracked(FRAME(p), FRAME((intptr_t)p + (n - 1)))) { - SYSDEBUG("munmap(0x%x, 0x%x) EFAULT (interval not tracked)", p, n); + STRACE("munmap(%p, %'zu) EFAULT (interval not tracked)", p, n); return VIP(efault()); } - SYSDEBUG("mremap(0x%p, 0x%x, 0x%x, 0x%x)", p, n, m, f); + 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; @@ -174,8 +173,8 @@ void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) { } q = sys_mremap((void *)p, n, m, MREMAP_MAYMOVE | MREMAP_FIXED, (void *)ADDR(a)); - SYSDEBUG("sys_mremap(0x%p, 0x%x, 0x%x, 0x%x, 0x%x) -> 0x%p", p, n, m, - MREMAP_MAYMOVE | MREMAP_FIXED, ADDR(a)); + STRACE("sys_mremap(%p, %'zu, %'zu, %#b, %p) → %p", p, n, m, + MREMAP_MAYMOVE | MREMAP_FIXED, ADDR(a), q); if (q == MAP_FAILED) return 0; if (ReleaseMemoryIntervals(&_mmi, (uintptr_t)p >> 16, ((uintptr_t)p + n - FRAMESIZE) >> 16, 0) != -1 && diff --git a/libc/runtime/munmap.c b/libc/runtime/munmap.c index 45098727ea9..6073bc9690f 100644 --- a/libc/runtime/munmap.c +++ b/libc/runtime/munmap.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/likely.h" #include "libc/calls/internal.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" @@ -31,10 +31,8 @@ #include "libc/sysv/errfuns.h" #define IP(X) (intptr_t)(X) -#define SMALL(n) ((n) <= 0xffffffffffff) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) #define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16) -#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000) #define FRAME(x) ((int)((intptr_t)(x) >> 16)) /** @@ -56,28 +54,29 @@ noasan int munmap(void *v, size_t n) { int rc; char poison, *p = v; intptr_t a, b, x, y; + assert(!__vforked); if (UNLIKELY(!n)) { - SYSDEBUG("munmap(0x%p, 0x%x) %s (n=0)", p, n); + STRACE("munmap(%.12p, %'zu) %s (n=0)", p, n); return einval(); } - if (UNLIKELY(!SMALL(n))) { - SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (n isn't 48-bit)", p, n); + if (UNLIKELY(!IsLegalSize(n))) { + STRACE("munmap(%.12p, %'zu) EINVAL (n isn't 48-bit)", p, n); return einval(); } if (UNLIKELY(!IsLegalPointer(p))) { - SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, n); + STRACE("munmap(%.12p, %'zu) EINVAL (p isn't 48-bit)", p, n); return einval(); } if (UNLIKELY(!IsLegalPointer(p + (n - 1)))) { - SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p+(n-1) isn't 48-bit)", p, n); + STRACE("munmap(%.12p, %'zu) EINVAL (p+(n-1) isn't 48-bit)", p, n); return einval(); } if (UNLIKELY(!ALIGNED(p))) { - SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p isn't 64kb aligned)", p, n); + STRACE("munmap(%.12p, %'zu) EINVAL (p isn't 64kb aligned)", p, n); return einval(); } if (!IsMemtracked(FRAME(p), FRAME(p + (n - 1)))) { - SYSDEBUG("munmap(0x%p, 0x%x) EFAULT (interval not tracked)", p, n); + STRACE("munmap(%.12p, %'zu) EFAULT (interval not tracked)", p, n); return efault(); } if (UntrackMemoryIntervals(p, n) != -1) { @@ -85,7 +84,7 @@ noasan int munmap(void *v, size_t n) { rc = sys_munmap(p, n); if (rc != -1) { if (IsAsan() && !OverlapsShadowSpace(p, n)) { - a = SHADE(p); + a = ((intptr_t)p >> 3) + 0x7fff8000; b = a + (n >> 3); if (IsMemtracked(FRAME(a), FRAME(b - 1))) { x = ROUNDUP(a, FRAMESIZE); @@ -100,7 +99,7 @@ noasan int munmap(void *v, size_t n) { __repstosb((void *)a, kAsanUnmapped, b - a); } } else { - SYSDEBUG("unshadow(0x%x, 0x%x) EFAULT", a, b - a); + STRACE("unshadow(%.12p, %p) EFAULT", a, b - a); } } } @@ -110,7 +109,7 @@ noasan int munmap(void *v, size_t n) { } else { rc = -1; } - SYSDEBUG("munmap(0x%p, 0x%x) -> %d %s", p, n, (long)rc, - rc == -1 ? strerror(errno) : ""); + STRACE("munmap(%.12p, %'zu) → %d %s", p, n, rc, + rc == -1 ? strerror(errno) : ""); return rc; } diff --git a/libc/runtime/opensymboltable.c b/libc/runtime/opensymboltable.c index 6d2d229c494..d615ed020f9 100644 --- a/libc/runtime/opensymboltable.c +++ b/libc/runtime/opensymboltable.c @@ -20,7 +20,7 @@ #include "libc/assert.h" #include "libc/bits/bits.h" #include "libc/calls/calls.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/elf/def.h" #include "libc/elf/scalar.h" @@ -187,7 +187,7 @@ noasan struct SymbolTable *OpenSymbolTable(const char *filename) { RaiseEnoexec: errno = ENOEXEC; SystemError: - SYSDEBUG("OpenSymbolTable() %s", strerror(errno)); + STRACE("OpenSymbolTable() %m"); if (map != MAP_FAILED) { munmap(map, st.st_size); } diff --git a/libc/runtime/printargs.c b/libc/runtime/printargs.c new file mode 100644 index 00000000000..986be211545 --- /dev/null +++ b/libc/runtime/printargs.c @@ -0,0 +1,116 @@ +/*-*- 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/calls/strace.internal.h" +#include "libc/intrin/kprintf.h" +#include "libc/macros.internal.h" +#include "libc/runtime/runtime.h" +#include "libc/runtime/stack.h" +#include "libc/sysv/consts/auxv.h" + +static const struct AuxiliaryValue { + const char *fmt; + long *id; + const char *name; +} kAuxiliaryValues[] = { + {"%-14p", &AT_EXECFD, "AT_EXECFD"}, + {"%-14p", &AT_PHDR, "AT_PHDR"}, + {"%-14p", &AT_PHENT, "AT_PHENT"}, + {"%-14p", &AT_PHNUM, "AT_PHNUM"}, + {"%-14p", &AT_PAGESZ, "AT_PAGESZ"}, + {"%-14p", &AT_BASE, "AT_BASE"}, + {"%-14p", &AT_ENTRY, "AT_ENTRY"}, + {"%-14p", &AT_NOTELF, "AT_NOTELF"}, + {"%-14d", &AT_UID, "AT_UID"}, + {"%-14d", &AT_EUID, "AT_EUID"}, + {"%-14d", &AT_GID, "AT_GID"}, + {"%-14d", &AT_EGID, "AT_EGID"}, + {"%-14d", &AT_CLKTCK, "AT_CLKTCK"}, + {"%-14d", &AT_OSRELDATE, "AT_OSRELDATE"}, + {"%-14p", &AT_PLATFORM, "AT_PLATFORM"}, + {"%-14p", &AT_DCACHEBSIZE, "AT_DCACHEBSIZE"}, + {"%-14p", &AT_ICACHEBSIZE, "AT_ICACHEBSIZE"}, + {"%-14p", &AT_UCACHEBSIZE, "AT_UCACHEBSIZE"}, + {"%-14p", &AT_SECURE, "AT_SECURE"}, + {"%-14s", &AT_BASE_PLATFORM, "AT_BASE_PLATFORM"}, + {"%-14p", &AT_RANDOM, "AT_RANDOM"}, + {"%-14s", &AT_EXECFN, "AT_EXECFN"}, + {"%-14p", &AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR"}, + {"%-14p", &AT_FLAGS, "AT_FLAGS"}, + {"%-14p", &AT_HWCAP, "AT_HWCAP"}, + {"%-14p", &AT_HWCAP2, "AT_HWCAP2"}, + {"%-14p", &AT_STACKBASE, "AT_STACKBASE"}, + {"%-14p", &AT_CANARY, "AT_CANARY"}, + {"%-14p", &AT_CANARYLEN, "AT_CANARYLEN"}, + {"%-14ld", &AT_NCPUS, "AT_NCPUS"}, + {"%-14p", &AT_PAGESIZES, "AT_PAGESIZES"}, + {"%-14d", &AT_PAGESIZESLEN, "AT_PAGESIZESLEN"}, + {"%-14p", &AT_TIMEKEEP, "AT_TIMEKEEP"}, + {"%-14p", &AT_STACKPROT, "AT_STACKPROT"}, + {"%-14p", &AT_EHDRFLAGS, "AT_EHDRFLAGS"}, +}; + +static const struct AuxiliaryValue *DescribeAuxv(unsigned long x) { + int i; + for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) { + if (*kAuxiliaryValues[i].id && x == *kAuxiliaryValues[i].id) { + return kAuxiliaryValues + i; + } + } + return NULL; +} + +textstartup void __printargs(int argc, char **argv, char **envp, + intptr_t *auxv) { +#ifdef SYSDEBUG + long key; + char **env; + unsigned i; + intptr_t *auxp; + char path[PATH_MAX]; + struct AuxiliaryValue *auxinfo; + STRACE("ARGUMENTS (%p)", argv); + for (i = 0; i < argc; ++i) { + STRACE(" ☼ %s", argv[i]); + } + STRACE("ENVIRONMENT (%p)", envp); + for (env = envp; *env; ++env) { + STRACE(" ☼ %s", *env); + } + STRACE("AUXILIARY (%p)", auxv); + for (auxp = auxv; *auxp; auxp += 2) { + if ((auxinfo = DescribeAuxv(auxp[0]))) { + ksnprintf(path, sizeof(path), auxinfo->fmt, auxp[1]); + STRACE(" ☼ %16s[%4ld] = %s", auxinfo->name, auxp[0], path); + } else { + STRACE(" ☼ %16s[%4ld] = %014p", "unknown", auxp[0], auxp[1]); + } + } + STRACE("SPECIALS"); + STRACE(" ☼ %21s = %#s", "kTmpPath", kTmpPath); + STRACE(" ☼ %21s = %#s", "kNtSystemDirectory", kNtSystemDirectory); + STRACE(" ☼ %21s = %#s", "kNtWindowsDirectory", kNtWindowsDirectory); + STRACE(" ☼ %21s = %#s", "program_executable_name", program_executable_name); + STRACE(" ☼ %21s = %#s", "GetInterpreterExecutableName()", + GetInterpreterExecutableName(path, sizeof(path))); + STRACE(" ☼ %21s = %p", "RSP", __builtin_frame_address(0)); + STRACE(" ☼ %21s = %p", "GetStackAddr()", GetStackAddr(0)); + STRACE(" ☼ %21s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0)); + STRACE(" ☼ %21s = %p", "GetStackSize()", GetStackSize()); +#endif +} diff --git a/libc/runtime/straceinit.greg.c b/libc/runtime/straceinit.greg.c new file mode 100644 index 00000000000..5c43e462a60 --- /dev/null +++ b/libc/runtime/straceinit.greg.c @@ -0,0 +1,37 @@ +/*-*- 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/bits/safemacros.internal.h" +#include "libc/calls/strace.internal.h" +#include "libc/fmt/conv.h" +#include "libc/intrin/kprintf.h" +#include "libc/log/libfatal.internal.h" +#include "libc/runtime/internal.h" +#include "libc/str/str.h" + +/** + * Enables plaintext system call logging if `--strace` flag is passed. + */ +textstartup int __strace_init(int argc, char **argv, char **envp, long *auxv) { + /* asan isn't initialized yet at runlevel 300 */ + if (__intercept_flag(&argc, argv, "--strace") || + __atoul(nulltoempty(__getenv(envp, "STRACE")))) { + ++__strace; + } + return argc; +} diff --git a/libc/runtime/vfork.S b/libc/runtime/vfork.S index 197d6f763b0..11c6e1cfb56 100644 --- a/libc/runtime/vfork.S +++ b/libc/runtime/vfork.S @@ -17,14 +17,10 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" +#include "libc/calls/strace.internal.h" #include "libc/macros.internal.h" .privileged -#ifdef __FSANITIZE_ADDRESS__ -vfork: jmp fork # TODO: asan and vfork don't mix? - .endfn vfork,globl -#else - // Forks process without copying page tables. // // This is the same as fork() except it's optimized for the case @@ -40,11 +36,24 @@ vfork: jmp fork # TODO: asan and vfork don't mix? // @returnstwice // @vforksafe vfork: +#ifdef __FSANITIZE_ADDRESS__ + jmp fork # TODO: asan and vfork don't mix? + .endfn vfork,globl +#else #if SupportsWindows() testb IsWindows() - jnz sys_fork_nt + jnz sys_fork_nt # and we're lucky to have that #endif +#if SupportsOpenbsd() + testb IsOpenbsd() + jnz fork # fake vfork plus msyscall issues +#endif +#ifdef SYSDEBUG + ezlea .Llog,di + call __stracef +#endif /* SYSDEBUG */ mov __NR_vfork(%rip),%eax + mov errno(%rip),%r8d # avoid question of @vforksafe errno pop %rsi # saves return address in a register #if SupportsBsd() testb IsBsd() @@ -56,7 +65,8 @@ vfork: cmp $-4095,%eax jae systemfive_error #endif -0: ezlea __vforked,di +0: mov %r8d,errno(%rip) + ezlea __vforked,di test %eax,%eax jz 1f decl (%rdi) @@ -81,4 +91,11 @@ vfork.bsd: .endfn vfork.bsd #endif /* BSD */ +#ifdef SYSDEBUG + .rodata.str1.1 +.Llog: .ascii STRACE_PROLOGUE + .asciz "vfork()%n" + .previous +#endif /* DEBUGSYS */ + #endif /* __FSANITIZE_ADDRESS__ */ diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index 35ffb0810ce..72c8fdb04b9 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -20,6 +20,7 @@ #include "libc/bits/pushpop.h" #include "libc/bits/weaken.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/fmt/fmt.h" #include "libc/intrin/kprintf.h" @@ -127,6 +128,7 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) { stacksize = GetStackSize(); allocsize = argsize + stacksize; allocaddr = stackaddr - argsize; + STRACE("WinMainNew() mapping arg block / stack"); MapViewOfFileExNuma( (_mmi.p[0].h = CreateFileMappingNuma( -1, &kNtIsInheritable, kNtPageExecuteReadwrite, allocsize >> 32, @@ -139,6 +141,7 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) { _mmi.p[0].flags = MAP_PRIVATE | MAP_ANONYMOUS; _mmi.i = 1; wa = (struct WinArgs *)allocaddr; + STRACE("WinMainNew() loading arg block"); count = GetDosArgv(GetCommandLine(), wa->argblock, ARRAYLEN(wa->argblock), wa->argv, ARRAYLEN(wa->argv)); for (i = 0; wa->argv[0][i]; ++i) { @@ -147,11 +150,13 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) { } } env16 = GetEnvironmentStrings(); + STRACE("WinMainNew() loading environment"); GetDosEnviron(env16, wa->envblock, ARRAYLEN(wa->envblock) - 8, wa->envp, ARRAYLEN(wa->envp) - 1); FreeEnvironmentStrings(env16); wa->auxv[0][0] = pushpop(AT_EXECFN); wa->auxv[0][1] = (intptr_t)wa->argv[0]; + STRACE("WinMainNew() switching stacks"); _jmpstack((char *)stackaddr + stacksize, cosmo, count, wa->argv, wa->envp, wa->auxv); } @@ -198,6 +203,7 @@ noasan textwindows noinstrument int64_t WinMain(int64_t hInstance, ts = rdtsc(); __nomultics = true; __pid = GetCurrentProcessId(); + STRACE("WinMain()"); MakeLongDoubleLongAgain(); if (weaken(WinSockInit)) weaken(WinSockInit)(); if (weaken(WinMainForked)) weaken(WinMainForked)(); diff --git a/libc/sock/accept4.c b/libc/sock/accept4.c index 1d24bb048a4..85c87189817 100644 --- a/libc/sock/accept4.c +++ b/libc/sock/accept4.c @@ -17,10 +17,12 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" +#include "libc/sock/sockdebug.h" #include "libc/sysv/errfuns.h" /** @@ -35,14 +37,20 @@ * @asyncsignalsafe */ int accept4(int fd, void *out_addr, uint32_t *inout_addrsize, int flags) { - if (!out_addr) return efault(); - if (!inout_addrsize) return efault(); - if (IsAsan() && !__asan_is_valid(out_addr, *inout_addrsize)) return efault(); - if (!IsWindows()) { - return sys_accept4(fd, out_addr, inout_addrsize, flags); + int rc; + char addrbuf[72]; + if (!out_addr || !inout_addrsize || + (IsAsan() && !__asan_is_valid(out_addr, *inout_addrsize))) { + rc = efault(); + } else if (!IsWindows()) { + rc = sys_accept4(fd, out_addr, inout_addrsize, flags); } else if (__isfdkind(fd, kFdSocket)) { - return sys_accept_nt(&g_fds.p[fd], out_addr, inout_addrsize, flags); + rc = sys_accept_nt(&g_fds.p[fd], out_addr, inout_addrsize, flags); } else { - return ebadf(); + rc = ebadf(); } + STRACE("accept4(%d, [%s]) -> %d% m", fd, + __describe_sockaddr(out_addr, inout_addrsize ? *inout_addrsize : 0), + rc); + return rc; } diff --git a/libc/sock/bind.c b/libc/sock/bind.c index 28cb9c689df..a65c7bc6c32 100644 --- a/libc/sock/bind.c +++ b/libc/sock/bind.c @@ -18,10 +18,12 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" +#include "libc/sock/sockdebug.h" #include "libc/str/str.h" #include "libc/sysv/errfuns.h" @@ -36,26 +38,30 @@ * @asyncsignalsafe */ int bind(int fd, const void *addr, uint32_t addrsize) { - if (!addr) return efault(); - if (IsAsan() && !__asan_is_valid(addr, addrsize)) return efault(); - if (addrsize == sizeof(struct sockaddr_in)) { + int rc; + char addrbuf[72]; + if (!addr || (IsAsan() && !__asan_is_valid(addr, addrsize))) { + rc = efault(); + } else if (addrsize >= sizeof(struct sockaddr_in)) { if (!IsWindows()) { if (!IsBsd()) { - return sys_bind(fd, addr, addrsize); + rc = sys_bind(fd, addr, addrsize); } else { char addr2[sizeof( struct sockaddr_un_bsd)]; /* sockaddr_un_bsd is the largest */ assert(addrsize <= sizeof(addr2)); memcpy(&addr2, addr, addrsize); sockaddr2bsd(&addr2[0]); - return sys_bind(fd, &addr2, addrsize); + rc = sys_bind(fd, &addr2, addrsize); } } else if (__isfdkind(fd, kFdSocket)) { - return sys_bind_nt(&g_fds.p[fd], addr, addrsize); + rc = sys_bind_nt(&g_fds.p[fd], addr, addrsize); } else { - return ebadf(); + rc = ebadf(); } } else { - return einval(); + rc = einval(); } + STRACE("bind(%d, %s) -> %d% m", fd, __describe_sockaddr(addr, addrsize), rc); + return rc; } diff --git a/libc/sock/connect.c b/libc/sock/connect.c index 2793124817a..41e39882f77 100644 --- a/libc/sock/connect.c +++ b/libc/sock/connect.c @@ -16,9 +16,11 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sock/internal.h" +#include "libc/sock/sockdebug.h" #include "libc/sysv/errfuns.h" /** @@ -32,15 +34,20 @@ * @asyncsignalsafe */ int connect(int fd, const void *addr, uint32_t addrsize) { - uint32_t ip; - if (!addr) return efault(); - if (IsAsan() && !__asan_is_valid(addr, addrsize)) return efault(); - _firewall(addr, addrsize); - if (!IsWindows()) { - return sys_connect(fd, addr, addrsize); - } else if (__isfdkind(fd, kFdSocket)) { - return sys_connect_nt(&g_fds.p[fd], addr, addrsize); + int rc; + if (addr && !(IsAsan() && !__asan_is_valid(addr, addrsize))) { + _firewall(addr, addrsize); + if (!IsWindows()) { + rc = sys_connect(fd, addr, addrsize); + } else if (__isfdkind(fd, kFdSocket)) { + rc = sys_connect_nt(&g_fds.p[fd], addr, addrsize); + } else { + rc = ebadf(); + } } else { - return ebadf(); + rc = efault(); } + STRACE("connect(%d, %s) -> %d% m", fd, __describe_sockaddr(addr, addrsize), + rc); + return rc; } diff --git a/libc/sock/getpeername.c b/libc/sock/getpeername.c index 444a3e60c55..0fbf32df7ec 100644 --- a/libc/sock/getpeername.c +++ b/libc/sock/getpeername.c @@ -17,10 +17,12 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" +#include "libc/sock/sockdebug.h" #include "libc/sysv/errfuns.h" /** @@ -29,12 +31,19 @@ * @see getsockname() */ int getpeername(int fd, void *out_addr, uint32_t *out_addrsize) { - if (IsAsan() && !__asan_is_valid(out_addr, *out_addrsize)) return efault(); - if (!IsWindows()) { - return sys_getpeername(fd, out_addr, out_addrsize); + int rc; + if (!out_addr || !out_addrsize || + (IsAsan() && (!__asan_is_valid(out_addrsize, 4) || + !__asan_is_valid(out_addr, *out_addrsize)))) { + rc = efault(); + } else if (!IsWindows()) { + rc = sys_getpeername(fd, out_addr, out_addrsize); } else if (__isfdkind(fd, kFdSocket)) { - return sys_getpeername_nt(&g_fds.p[fd], out_addr, out_addrsize); + rc = sys_getpeername_nt(&g_fds.p[fd], out_addr, out_addrsize); } else { - return ebadf(); + rc = ebadf(); } + STRACE("getpeername(%d, [%s]) -> %d% m", fd, + __describe_sockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc); + return rc; } diff --git a/libc/sock/getsockname.c b/libc/sock/getsockname.c index 49c7e9dbe4d..fac44ca1a71 100644 --- a/libc/sock/getsockname.c +++ b/libc/sock/getsockname.c @@ -17,10 +17,12 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" +#include "libc/sock/sockdebug.h" #include "libc/sysv/errfuns.h" /** @@ -29,12 +31,19 @@ * @see getpeername() */ int getsockname(int fd, void *out_addr, uint32_t *out_addrsize) { - if (IsAsan() && !__asan_is_valid(out_addr, *out_addrsize)) return efault(); - if (!IsWindows()) { - return sys_getsockname(fd, out_addr, out_addrsize); + int rc; + if (!out_addrsize || !out_addrsize || + (IsAsan() && (!__asan_is_valid(out_addrsize, 4) || + !__asan_is_valid(out_addr, *out_addrsize)))) { + rc = efault(); + } else if (!IsWindows()) { + rc = sys_getsockname(fd, out_addr, out_addrsize); } else if (__isfdkind(fd, kFdSocket)) { - return sys_getsockname_nt(&g_fds.p[fd], out_addr, out_addrsize); + rc = sys_getsockname_nt(&g_fds.p[fd], out_addr, out_addrsize); } else { - return ebadf(); + rc = ebadf(); } + STRACE("getsockname(%d, [%s]) -> %d% m", fd, + __describe_sockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc); + return rc; } diff --git a/libc/sock/inet_ntop.c b/libc/sock/inet_ntop.c index 3e8fbe99c8f..afbc88d946d 100644 --- a/libc/sock/inet_ntop.c +++ b/libc/sock/inet_ntop.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/itoa.h" +#include "libc/str/str.h" #include "libc/sysv/consts/af.h" #include "libc/sysv/errfuns.h" @@ -34,16 +35,17 @@ const char *inet_ntop(int af, const void *src, char *dst, uint32_t size) { unsigned char *ip; int i, t, a, b, c, d; p = dst; + if (!size) return dst; if ((ip = src)) { if (af == AF_INET) { if (size >= 16) { - p += uint64toarray_radix10(ip[0], p); + p = FormatUint32(p, ip[0]); *p++ = '.'; - p += uint64toarray_radix10(ip[1], p); + p = FormatUint32(p, ip[1]); *p++ = '.'; - p += uint64toarray_radix10(ip[2], p); + p = FormatUint32(p, ip[2]); *p++ = '.'; - p += uint64toarray_radix10(ip[3], p); + p = FormatUint32(p, ip[3]); *p = '\0'; return dst; } else { @@ -98,6 +100,5 @@ const char *inet_ntop(int af, const void *src, char *dst, uint32_t size) { } else { einval(); } - if (size) dst[0] = '\0'; - return NULL; + return 0; } diff --git a/libc/sock/internal.h b/libc/sock/internal.h index 312826592c4..7126f579873 100644 --- a/libc/sock/internal.h +++ b/libc/sock/internal.h @@ -1,6 +1,5 @@ #ifndef COSMOPOLITAN_LIBC_SOCK_INTERNAL_H_ #define COSMOPOLITAN_LIBC_SOCK_INTERNAL_H_ -#include "libc/bits/bits.h" #include "libc/calls/internal.h" #include "libc/nt/thunk/msabi.h" #include "libc/nt/winsock.h" @@ -148,12 +147,10 @@ int sys_close_epoll(int) hidden; */ forceinline void sockaddr2bsd(void *saddr) { char *p; - uint16_t fam; if (saddr) { p = saddr; - fam = READ16LE(p); + p[1] = p[0]; p[0] = sizeof(struct sockaddr_in_bsd); - p[1] = fam; } } @@ -161,11 +158,11 @@ forceinline void sockaddr2bsd(void *saddr) { * Converts sockaddr_in_bsd (XNU/BSD) → sockaddr (Linux/Windows). */ forceinline void sockaddr2linux(void *saddr) { - char *p, fam; + char *p; if (saddr) { p = saddr; - fam = p[1]; - WRITE16LE(p, fam); + p[0] = p[1]; + p[1] = 0; } } diff --git a/libc/sock/listen.c b/libc/sock/listen.c index 65c1465c118..a3500345f0a 100644 --- a/libc/sock/listen.c +++ b/libc/sock/listen.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" @@ -34,11 +35,14 @@ * @return 0 on success or -1 w/ errno */ int listen(int fd, int backlog) { + int rc; if (!IsWindows()) { - return sys_listen(fd, backlog); + rc = sys_listen(fd, backlog); } else if (__isfdkind(fd, kFdSocket)) { - return sys_listen_nt(&g_fds.p[fd], backlog); + rc = sys_listen_nt(&g_fds.p[fd], backlog); } else { - return ebadf(); + rc = ebadf(); } + STRACE("listen(%d, %d) → %d% m", fd, backlog, rc); + return rc; } diff --git a/libc/sock/poll.c b/libc/sock/poll.c index 38fa964f7d0..bf5e5e23f13 100644 --- a/libc/sock/poll.c +++ b/libc/sock/poll.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sock/internal.h" @@ -38,16 +39,18 @@ * @asyncsignalsafe */ int poll(struct pollfd *fds, uint64_t nfds, int32_t timeout_ms) { + int rc; if (IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd))) { - return efault(); - } - if (!IsWindows()) { + rc = efault(); + } else if (!IsWindows()) { if (!IsMetal()) { - return sys_poll(fds, nfds, timeout_ms); + rc = sys_poll(fds, nfds, timeout_ms); } else { - return sys_poll_metal(fds, nfds, timeout_ms); + rc = sys_poll_metal(fds, nfds, timeout_ms); } } else { - return sys_poll_nt(fds, nfds, timeout_ms); + rc = sys_poll_nt(fds, nfds, timeout_ms); } + STRACE("poll(%p, %'lu, %'d) → %d% m", fds, nfds, timeout_ms, rc); + return rc; } diff --git a/libc/sock/shutdown.c b/libc/sock/shutdown.c index 2183b2f2fa3..7c9f3df8ca1 100644 --- a/libc/sock/shutdown.c +++ b/libc/sock/shutdown.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" @@ -31,11 +32,14 @@ * @asyncsignalsafe */ int shutdown(int fd, int how) { + int rc; if (!IsWindows()) { - return sys_shutdown(fd, how); + rc = sys_shutdown(fd, how); } else if (__isfdkind(fd, kFdSocket)) { - return sys_shutdown_nt(&g_fds.p[fd], how); + rc = sys_shutdown_nt(&g_fds.p[fd], how); } else { - return ebadf(); + rc = ebadf(); } + STRACE("shutdown(%d, %d) -> %d% m", fd, how, rc); + return rc; } diff --git a/libc/sock/sock.h b/libc/sock/sock.h index 6eb96b9cac5..95c9d7bcc79 100644 --- a/libc/sock/sock.h +++ b/libc/sock/sock.h @@ -136,31 +136,30 @@ char *inet_ntoa(struct in_addr); int parseport(const char *); uint32_t *GetHostIps(void); -int socket(int, int, int) nodiscard; -int accept(int, void *, uint32_t *) nodiscard; -int accept4(int, void *, uint32_t *, int) nodiscard; +int socket(int, int, int); +int accept(int, void *, uint32_t *); +int accept4(int, void *, uint32_t *, int); int bind(int, const void *, uint32_t); int connect(int, const void *, uint32_t); int listen(int, int); int shutdown(int, int); -int getsockname(int, void *, uint32_t *) paramsnonnull(); -int getpeername(int, void *, uint32_t *) paramsnonnull(); -ssize_t send(int, const void *, size_t, int) paramsnonnull(); +int getsockname(int, void *, uint32_t *); +int getpeername(int, void *, uint32_t *); +ssize_t send(int, const void *, size_t, int); ssize_t recv(int, void *, size_t, int); -ssize_t recvmsg(int, struct msghdr *, int) paramsnonnull(); +ssize_t recvmsg(int, struct msghdr *, int); ssize_t recvfrom(int, void *, size_t, uint32_t, void *, uint32_t *); -ssize_t sendmsg(int, const struct msghdr *, int) paramsnonnull(); +ssize_t sendmsg(int, const struct msghdr *, int); ssize_t readv(int, const struct iovec *, int); ssize_t writev(int, const struct iovec *, int); ssize_t sendfile(int, int, int64_t *, size_t); -int getsockopt(int, int, int, void *, uint32_t *) paramsnonnull((5)); +int getsockopt(int, int, int, void *, uint32_t *); int setsockopt(int, int, int, const void *, uint32_t); -int socketpair(int, int, int, int[2]) paramsnonnull(); -int poll(struct pollfd *, uint64_t, int32_t) paramsnonnull(); +int socketpair(int, int, int, int[2]); +int poll(struct pollfd *, uint64_t, int32_t); int ppoll(struct pollfd *, uint64_t, const struct timespec *, - const struct sigset *) paramsnonnull((1, 4)); -ssize_t sendto(int, const void *, size_t, uint32_t, const void *, uint32_t) - paramsnonnull((2)); + const struct sigset *); +ssize_t sendto(int, const void *, size_t, uint32_t, const void *, uint32_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/sock/sockdebug.c b/libc/sock/sockdebug.c new file mode 100644 index 00000000000..42e5c12c77f --- /dev/null +++ b/libc/sock/sockdebug.c @@ -0,0 +1,114 @@ +/*-*- 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/calls/struct/sockaddr6.h" +#include "libc/errno.h" +#include "libc/fmt/itoa.h" +#include "libc/macros.internal.h" +#include "libc/sock/sock.h" +#include "libc/sock/sockdebug.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/af.h" +#include "libc/sysv/consts/ipproto.h" +#include "libc/sysv/consts/sock.h" + +const char *__describe_socket_family(int family) { + static char buf[12]; + if (family == AF_UNIX) return "AF_UNIX"; + if (family == AF_INET) return "AF_INET"; + if (family == AF_INET6) return "AF_INET6"; + FormatInt32(buf, family); + return buf; +} + +const char *__describe_socket_type(int type) { + int x; + char *p; + static char buf[12 + 1 + 12 + 1 + 13 + 1]; + p = buf; + x = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); + if (x == SOCK_STREAM) { + p = stpcpy(p, "SOCK_STREAM"); + } else if (x == SOCK_DGRAM) { + p = stpcpy(p, "SOCK_DGRAM"); + } else if (x == SOCK_RAW) { + p = stpcpy(p, "SOCK_RAW"); + } else { + p = FormatInt32(p, x); + } + if (type & SOCK_CLOEXEC) p = stpcpy(p, "|SOCK_CLOEXEC"); + if (type & SOCK_NONBLOCK) p = stpcpy(p, "|SOCK_NONBLOCK"); + return buf; +} + +const char *__describe_socket_protocol(int family) { + static char buf[12]; + if (family == IPPROTO_IP) return "IPPROTO_IP"; + if (family == IPPROTO_ICMP) return "IPPROTO_ICMP"; + if (family == IPPROTO_TCP) return "IPPROTO_TCP"; + if (family == IPPROTO_UDP) return "IPPROTO_UDP"; + if (family == IPPROTO_RAW) return "IPPROTO_RAW"; + if (family == IPPROTO_IPV6) return "IPPROTO_IPv6"; + FormatInt32(buf, family); + return buf; +} + +const char *__describe_sockaddr(const struct sockaddr *sa, size_t sasize) { + int e; + size_t n; + uint16_t port; + char *p, ip[72]; + static char buf[128]; + e = errno; + stpcpy(buf, "NULL"); + if (sa && sasize >= sizeof(sa->sa_family)) { + stpcpy(buf, __describe_socket_family(sa->sa_family)); + if (sa->sa_family == AF_INET && sasize >= sizeof(struct sockaddr_in)) { + const struct sockaddr_in *in; + in = (const struct sockaddr_in *)sa; + if (inet_ntop(AF_INET, &in->sin_addr, ip, sizeof(ip))) { + p = buf; + p = stpcpy(p, ip); + *p++ = ':'; + p = FormatUint32(p, in->sin_port); + } + } else if (sa->sa_family == AF_INET6 && + sasize >= sizeof(struct sockaddr_in6)) { + const struct sockaddr_in6 *in6; + in6 = (const struct sockaddr_in6 *)sa; + if (inet_ntop(AF_INET6, &in6->sin6_addr, ip, sizeof(ip))) { + p = buf; + *p++ = '['; + p = stpcpy(p, ip); + *p++ = ']'; + *p++ = ':'; + p = FormatUint32(p, in6->sin6_port); + } + } else if (sa->sa_family == AF_UNIX && + sasize >= sizeof(struct sockaddr_un)) { + const struct sockaddr_un *unix; + unix = (const struct sockaddr_un *)sa; + n = strnlen(unix->sun_path, sizeof(unix->sun_path)); + n = MIN(n, sizeof(buf) - 1); + memcpy(buf, unix->sun_path, n); + buf[n] = 0; + } + } + errno = e; + return buf; +} diff --git a/libc/sock/sockdebug.h b/libc/sock/sockdebug.h new file mode 100644 index 00000000000..f85b99bff9c --- /dev/null +++ b/libc/sock/sockdebug.h @@ -0,0 +1,14 @@ +#ifndef COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_ +#define COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_ +#include "libc/sock/sock.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +const char *__describe_sockaddr(const struct sockaddr *, size_t); +const char *__describe_socket_family(int); +const char *__describe_socket_type(int); +const char *__describe_socket_protocol(int); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_ */ diff --git a/libc/sock/socket.c b/libc/sock/socket.c index f668a5f000f..e7b6a4d13b1 100644 --- a/libc/sock/socket.c +++ b/libc/sock/socket.c @@ -16,11 +16,12 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" +#include "libc/sock/sockdebug.h" #include "libc/sysv/consts/af.h" -#include "libc/sysv/errfuns.h" /** * Creates new system resource for network communication, e.g. @@ -38,17 +39,15 @@ * @asyncsignalsafe */ int socket(int family, int type, int protocol) { - if (family == AF_UNSPEC) { - family = AF_INET; - } else if (family == AF_INET6) { - /* Recommend IPv6 on frontend serving infrastructure only. That's - what Google Cloud does. It's more secure. It also means poll() - will work on Windows, which doesn't allow mixing third layers. */ - return epfnosupport(); - } + int rc; + if (family == AF_UNSPEC) family = AF_INET; if (!IsWindows()) { - return sys_socket(family, type, protocol); + rc = sys_socket(family, type, protocol); } else { - return sys_socket_nt(family, type, protocol); + rc = sys_socket_nt(family, type, protocol); } + STRACE("socket(%s, %s, %s) -> %d% m", __describe_socket_family(family), + __describe_socket_type(type), __describe_socket_protocol(protocol), + rc); + return rc; } diff --git a/libc/stdio/fopen.c b/libc/stdio/fopen.c index 722d26480cc..3e78067fc90 100644 --- a/libc/stdio/fopen.c +++ b/libc/stdio/fopen.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #include "libc/mem/mem.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" @@ -59,7 +59,7 @@ FILE *fopen(const char *pathname, const char *mode) { FILE *f; bool noclose; int fd, flags; - SYSDEBUG("fopen(%s)", pathname); + STRACE("fopen(%s)", pathname); flags = fopenflags(mode); pathname = fixpathname(pathname, flags); if ((fd = openpathname(pathname, flags, &noclose)) != -1) { diff --git a/libc/str/istext.c b/libc/str/istext.c index 0a75f602197..460626572c7 100644 --- a/libc/str/istext.c +++ b/libc/str/istext.c @@ -21,7 +21,7 @@ /** * Returns true if buffer is most likely plaintext. */ -bool IsText(const void *data, size_t size) { +bool _istext(const void *data, size_t size) { const unsigned char *p, *pe; for (p = data, pe = p + size; p < pe; ++p) { if (*p <= 3) { diff --git a/libc/str/isutf8.c b/libc/str/isutf8.c index 983ce72822c..9155c5e4a46 100644 --- a/libc/str/isutf8.c +++ b/libc/str/isutf8.c @@ -23,7 +23,7 @@ * * This function will return false if a pure ascii string is passed. */ -bool IsUtf8(const void *data, size_t size) { +bool _isutf8(const void *data, size_t size) { const unsigned char *p, *pe; for (p = data, pe = p + size; p + 2 <= pe; ++p) { if (p[0] >= 0300) { diff --git a/libc/str/str.h b/libc/str/str.h index 1f63ad42777..fca378aa857 100644 --- a/libc/str/str.h +++ b/libc/str/str.h @@ -203,8 +203,8 @@ char *strtoupper(char *) paramsnonnull(); char *chomp(char *); char16_t *chomp16(char16_t *); wchar_t *wchomp(wchar_t *); -bool IsText(const void *, size_t); -bool IsUtf8(const void *, size_t); +bool _istext(const void *, size_t); +bool _isutf8(const void *, size_t); bool _isabspath(const char *) strlenesque; bool escapedos(char16_t *, unsigned, const char16_t *, unsigned); diff --git a/libc/runtime/describeos.c b/libc/sysv/describeos.greg.c similarity index 86% rename from libc/runtime/describeos.c rename to libc/sysv/describeos.greg.c index ded8f318542..1b0f37c6a2c 100644 --- a/libc/runtime/describeos.c +++ b/libc/sysv/describeos.greg.c @@ -17,23 +17,21 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -char *describeos(char *buf, size_t size) { - const char *s; +const char *__describe_os(void) { if (IsLinux()) { - s = "gnu/systemd"; + return "gnu/systemd"; } else if (IsXnu()) { - s = "xnu's not unix"; + return "xnu's not unix!"; } else if (IsFreebsd()) { - s = "freebesiyatadishmaya"; + return "free besiyata dishmaya"; + } else if (IsNetbsd()) { + return "net besiyata dishmaya"; } else if (IsOpenbsd()) { - s = "openbsd"; + return "open besiyata dishmaya"; } else if (IsWindows()) { - s = "the new technology"; + return "the new technology"; } else { - s = "wut"; + return "wut"; } - return memccpy(buf, s, '\0', size); } diff --git a/libc/sysv/strace.greg.c b/libc/sysv/strace.greg.c new file mode 100644 index 00000000000..cd75bfa5fc0 --- /dev/null +++ b/libc/sysv/strace.greg.c @@ -0,0 +1,21 @@ +/*-*- 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/calls/strace.internal.h" + +int __strace; diff --git a/libc/sysv/systemfive.S b/libc/sysv/systemfive.S index f2b5f9bcabb..8a899572018 100644 --- a/libc/sysv/systemfive.S +++ b/libc/sysv/systemfive.S @@ -16,13 +16,14 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/strace.internal.h" #include "libc/dce.h" -#include "libc/sysv/consts/prot.h" -#include "libc/sysv/consts/nr.h" -#include "libc/sysv/consts/map.h" #include "libc/macros.internal.h" -#include "libc/sysv/consts/prot.h" #include "libc/nexgen32e/macros.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/nr.h" +#include "libc/sysv/consts/prot.h" +#include "libc/sysv/consts/prot.h" /* ▄▄▄ ▄▄▄ ▀▓▓▒▄ @@ -306,8 +307,29 @@ _init_systemfive_magnums: jnz 3b xchg %rbx,%rax stosq +#ifdef SYSDEBUG + inc %r8d +#endif jmp 2b -5: pop %rdi +5: nop +#ifdef SYSDEBUG + push %rdi + push %rsi + push %r8 + call __describe_os + mov %rax,%rdx + pop %r8 + .weak __stracef + ezlea __stracef,ax + test %rax,%rax + jz 5f + ezlea .Llog,di + mov %r8d,%esi + call *%rax +5: pop %rsi + pop %rdi +#endif /* DEBUGSYS */ + pop %rdi pop %rsi pop %rbx // 𝑠𝑙𝑖𝑑𝑒 @@ -325,8 +347,12 @@ _init_systemfive_pid: .endfn _init_systemfive_pid #endif #if SupportsSystemv() && !defined(TINY) -_init_systemfive_stack: # determinism ftw! -#if SupportsWindows() || SupportsMetal() + +// Create a stack with deterministic readable addresses. +// If ape_execve() already created us a stack that meets +// the requirements of STATIC_STACK_SIZE() then we skip. +_init_systemfive_stack: +#if SupportsWindows() || SupportsMetal() || SupportsOpenbsd() testb $WINDOWS|METAL,__hostos(%rip) jnz _init_systemfive_done #endif @@ -512,6 +538,14 @@ syscon_windows:/* .globl syscon_windows #endif +#ifdef SYSDEBUG + .rodata.str1.1 +.Llog: .ascii STRACE_PROLOGUE + .ascii "bell system five system call support" + .asciz " %'u magnums loaded on %s%n" + .previous +#endif /* DEBUGSYS */ + .weak ape_stack_vaddr .weak ape_stack_memsz .weak ape_stack_align diff --git a/libc/sysv/sysv.mk b/libc/sysv/sysv.mk index 1b01db90e7f..42d389fc766 100644 --- a/libc/sysv/sysv.mk +++ b/libc/sysv/sysv.mk @@ -22,6 +22,7 @@ LIBC_SYSV_ARTIFACTS += LIBC_SYSV_A LIBC_SYSV_A = o/$(MODE)/libc/sysv/sysv.a LIBC_SYSV_A_HDRS = $(filter %.h,$(LIBC_SYSV_A_FILES)) LIBC_SYSV_A_INCS = $(filter %.inc,$(LIBC_SYSV_A_FILES)) +LIBC_SYSV_A_SRCS_C = $(filter %.c,$(LIBC_SYSV_A_FILES)) LIBC_SYSV_A_SRCS_A = $(filter %.s,$(LIBC_SYSV_A_FILES)) LIBC_SYSV_A_SRCS_S = $(filter %.S,$(LIBC_SYSV_A_FILES)) LIBC_SYSV_A_CHECKS = $(LIBC_SYSV_A).pkg @@ -36,15 +37,19 @@ LIBC_SYSV_A_FILES := \ libc/sysv/restorert.S \ libc/sysv/syscall.S \ libc/sysv/systemfive.S \ + libc/sysv/strace.greg.c \ + libc/sysv/describeos.greg.c \ $(wildcard libc/sysv/consts/*) \ $(wildcard libc/sysv/errfuns/*) LIBC_SYSV_A_SRCS = \ $(LIBC_SYSV_A_SRCS_A) \ + $(LIBC_SYSV_A_SRCS_C) \ $(LIBC_SYSV_A_SRCS_S) LIBC_SYSV_A_OBJS = \ $(LIBC_SYSV_A_SRCS_A:%.s=o/$(MODE)/%.o) \ + $(LIBC_SYSV_A_SRCS_C:%.c=o/$(MODE)/%.o) \ $(LIBC_SYSV_A_SRCS_S:%.S=o/$(MODE)/%.o) LIBC_SYSV_A_DEPS := \ diff --git a/libc/unicode/unicode-properties.txt b/libc/unicode/unicode-properties.txt index bbd3eaea283..f208c7cfb9f 100644 --- a/libc/unicode/unicode-properties.txt +++ b/libc/unicode/unicode-properties.txt @@ -28,3 +28,10 @@ Cf = Other, format Cs = Other, surrogate Co = Other, private use Cn = Other, not assigned (including noncharacters) + +W Wide Naturally wide character, e.g. Hiragana. +Na Narrow Naturally narrow character, e.g. ISO Basic Latin alphabet. +F Fullwidth Wide variant with compatibility normalisation to naturally narrow character, e.g. fullwidth Latin script. +H Halfwidth Narrow variant with compatibility normalisation to naturally wide character, e.g. half-width kana. Includes U+20A9 (₩) as an exception. +A Ambiguous Characters included in East Asian DBCS codes but also in European SBCS codes, e.g. Greek alphabet. Duospaced behaviour can consequently vary. +N Neutral Characters which do not appear in East Asian DBCS codes, e.g. Devanagari. diff --git a/libc/x/x.h b/libc/x/x.h index 3166a0bb584..a4d2b5ea2ab 100644 --- a/libc/x/x.h +++ b/libc/x/x.h @@ -122,6 +122,11 @@ int xvspawn(void (*)(void *), void *, struct rusage *); #if defined(__GNUC__) && !defined(__STRICT_ANSI__) #define xasprintf(FMT, ...) (xasprintf)(PFLINK(FMT), ##__VA_ARGS__) #define xvasprintf(FMT, VA) (xvasprintf)(PFLINK(FMT), VA) +#define xsigaction(SIG, HANDLER, FLAGS, MASK, OLD) \ + ({ \ + __SIGACTION_YOINK(SIG); \ + xsigaction(SIG, HANDLER, FLAGS, MASK, OLD); \ + }) #endif COSMOPOLITAN_C_END_ diff --git a/libc/x/xsigaction.c b/libc/x/xsigaction.c index de964a8577a..3a64fda0f3e 100644 --- a/libc/x/xsigaction.c +++ b/libc/x/xsigaction.c @@ -39,8 +39,8 @@ * @asyncsignalsafe * @vforksafe */ -int xsigaction(int sig, void *handler, uint64_t flags, uint64_t mask, - struct sigaction *old) { +int(xsigaction)(int sig, void *handler, uint64_t flags, uint64_t mask, + struct sigaction *old) { /* This API is superior to sigaction() because (1) it offers feature parity; (2) compiler emits 1/3rd as much binary code at call-site; and (3) it removes typing that just whines without added saftey. */ diff --git a/libc/zipos/zipos.internal.h b/libc/zipos/zipos.internal.h index e659160bab5..9d1cb41230f 100644 --- a/libc/zipos/zipos.internal.h +++ b/libc/zipos/zipos.internal.h @@ -1,7 +1,7 @@ #ifndef COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_ #define COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_ #include "libc/calls/calls.h" -#include "libc/calls/sysdebug.internal.h" +#include "libc/calls/strace.internal.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ diff --git a/test/libc/sock/inet_ntop_test.c b/test/libc/sock/inet_ntop_test.c index 261bbcd700c..a98ab7671c4 100644 --- a/test/libc/sock/inet_ntop_test.c +++ b/test/libc/sock/inet_ntop_test.c @@ -41,17 +41,17 @@ TEST(inet_ntop, testBadFamily) { uint8_t localhost[4] = {127, 0, 0, 1}; ASSERT_EQ(NULL, inet_ntop(666, localhost, buf, sizeof(buf))); EXPECT_EQ(EAFNOSUPPORT, errno); - ASSERT_STREQ("", buf); + ASSERT_STREQ("hi", buf); } TEST(inet_ntop, testNoSpace) { char *buf = memcpy(malloc(16), "hi", 3); uint8_t localhost[4] = {127, 0, 0, 1}; - ASSERT_EQ(NULL, inet_ntop(AF_INET, localhost, buf, 0)); + EXPECT_EQ(NULL, inet_ntop(AF_INET, localhost, buf, 1)); EXPECT_EQ(ENOSPC, errno); ASSERT_STREQ("hi", buf); ASSERT_EQ(NULL, inet_ntop(AF_INET, localhost, buf, 7)); - ASSERT_STREQ("", buf); + ASSERT_STREQ("hi", buf); free(buf); } diff --git a/third_party/chibicc/test/test.mk b/third_party/chibicc/test/test.mk index 61824fda495..e42be50b0ae 100644 --- a/third_party/chibicc/test/test.mk +++ b/third_party/chibicc/test/test.mk @@ -39,6 +39,7 @@ THIRD_PARTY_CHIBICC_TEST_CHECKS = \ $(THIRD_PARTY_CHIBICC_TEST_HDRS:%=o/$(MODE)/%.ok) THIRD_PARTY_CHIBICC_TEST_DIRECTDEPS = \ + LIBC_CALLS \ LIBC_FMT \ LIBC_INTRIN \ LIBC_MEM \ diff --git a/tool/build/lib/elfwriter_zip.c b/tool/build/lib/elfwriter_zip.c index 0f48e002720..3501bb0d199 100644 --- a/tool/build/lib/elfwriter_zip.c +++ b/tool/build/lib/elfwriter_zip.c @@ -155,8 +155,8 @@ void elfwriter_zip(struct ElfWriter *elf, const char *symbol, const char *name, lfilehdrsize = kZipLfileHdrMinSize + namesize; crc = crc32_z(0, data, uncompsize); GetDosLocalTime(mtim.tv_sec, &mtime, &mdate); - if (IsUtf8(name, namesize)) gflags |= kZipGflagUtf8; - if (S_ISREG(mode) && IsText(data, size)) { + if (_isutf8(name, namesize)) gflags |= kZipGflagUtf8; + if (S_ISREG(mode) && _istext(data, size)) { iattrs |= kZipIattrText; } commentsize = kZipCdirHdrLinkableSize - (CFILE_HDR_SIZE + namesize); diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 0eaf4a705d9..8eefef98942 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -3322,8 +3322,8 @@ static void StoreAsset(char *path, size_t pathlen, char *data, size_t datalen, INFOF("Storing asset %`'s", path); disk = gflags = iattrs = 0; - if (IsUtf8(path, pathlen)) gflags |= kZipGflagUtf8; - if (IsText(data, datalen)) iattrs |= kZipIattrText; + if (_isutf8(path, pathlen)) gflags |= kZipGflagUtf8; + if (_istext(data, datalen)) iattrs |= kZipIattrText; crc = crc32_z(0, data, datalen); if (datalen < 100) { method = kZipCompressionNone;