From 14e192e5ba820c60fa4aef48c1a646b151723603 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Fri, 18 Mar 2022 18:07:28 -0700 Subject: [PATCH] Introduce --strace flag for system call tracing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is similar to the --ftrace (c function call trace) flag, except it's less noisy since it only logs system calls to stderr. Having this flag is valuable because (1) system call tracing tells us a lot about the behavior of complex programs and (2) it's usually very hard to get system call tracing on various operating systems, e.g. strace, ktrace, dtruss, truss, nttrace, etc. Especially on Apple platforms where even with the special boot trick, debuggers still aren't guaranteed to work. make -j8 o//examples o//examples/hello.com --strace This is enabled by default in MODE=, MODE=opt, and MODE=dbg. In MODE=dbg extra information will be printed. make -j8 MODE=dbg o/dbg/examples o/dbg/examples/hello.com --strace |& less This change also changes: - Rename IsText() → _istext() - Rename IsUtf8() → _isutf8() - Fix madvise() on Windows NT - Fix empty string case of inet_ntop() - vfork() wrapper now saves and restores errno - Update xsigaction() to yoink syscall support --- build/config.mk | 8 +- libc/calls/chdir.c | 13 +- libc/calls/close.c | 4 +- libc/calls/commandv.c | 4 +- libc/{runtime => calls}/describeframe.c | 18 ++- libc/{runtime => calls}/describemapping.c | 23 ++-- libc/{runtime => calls}/directmap-metal.c | 0 libc/{runtime => calls}/directmap-nt.c | 22 ++-- libc/{runtime => calls}/directmap.c | 24 ++-- libc/calls/dup.c | 4 +- libc/calls/dup2.c | 15 ++- libc/calls/dup3.c | 10 +- libc/calls/execve.c | 64 +++++----- libc/calls/fchmodat.c | 9 +- libc/calls/fchownat.c | 15 ++- libc/calls/fcntl.c | 6 + libc/calls/fdatasync.c | 8 +- libc/calls/fileexists.c | 3 +- libc/calls/flock.c | 8 +- libc/calls/fstat-nt.c | 8 +- libc/calls/fstat-sysv.c | 2 - libc/calls/fstat.c | 15 ++- libc/calls/fstatat.c | 24 +++- libc/calls/fsync.c | 8 +- libc/calls/ftruncate.c | 15 ++- libc/calls/g_fds_init.S | 4 +- libc/calls/getcwd.c | 13 +- libc/calls/getitimer.c | 22 +++- libc/calls/getpgid.c | 8 +- libc/calls/getrlimit.c | 16 ++- libc/calls/getsid.c | 6 +- libc/calls/getuid.c | 15 ++- libc/calls/ioctl_siocgifconf.c | 1 + libc/calls/ioctl_tcgets.c | 19 +-- libc/calls/ioctl_tcsets.c | 2 + libc/calls/isdirectory.c | 5 +- libc/calls/isexecutable.c | 7 +- libc/calls/isregularfile.c | 2 +- libc/calls/linkat.c | 23 ++-- libc/calls/lseek.c | 12 +- libc/calls/madvise-nt.c | 5 +- libc/calls/madvise.c | 17 ++- libc/calls/mkdirat.c | 18 +-- libc/calls/mknod.c | 8 +- libc/calls/mkntpath.c | 6 +- libc/calls/mkntpathat.c | 4 +- libc/{runtime => calls}/mman.greg.c | 0 .../mremap-sysv.greg.c} | 12 +- libc/{runtime => calls}/munmap-metal.c | 0 libc/{runtime => calls}/munmap-sysv.c | 6 +- libc/calls/ntaccesscheck.c | 12 +- libc/calls/ntspawn.c | 4 +- libc/calls/openat.c | 7 +- libc/calls/pause.c | 2 + libc/calls/program_executable_name.c | 4 +- libc/calls/readlinkat-nt.c | 18 +-- libc/calls/readlinkat.c | 13 +- libc/calls/releasefd.c | 2 +- libc/calls/renameat.c | 23 ++-- libc/calls/sched_yield.c | 5 +- libc/calls/setrlimit.c | 16 ++- libc/calls/sigaction.c | 38 ++++-- libc/calls/sigaltstack.c | 51 ++++---- libc/calls/sigprocmask.c | 70 ++++++++--- libc/calls/sigsuspend.c | 15 ++- libc/calls/sigwinch-nt.c | 6 +- libc/calls/strace.internal.h | 34 +++++ libc/calls/strace_rlimit.c | 40 ++++++ libc/calls/strace_sigaction.greg.c | 31 +++++ libc/calls/strace_sigset.greg.c | 28 +++++ libc/calls/strace_stat.greg.c | 29 +++++ libc/calls/sysdebug.internal.h | 15 --- libc/calls/wait4-nt.c | 8 +- libc/calls/wait4.c | 15 ++- libc/calls/wincrash.c | 4 +- libc/intrin/asan.c | 2 + libc/intrin/exit.greg.c | 2 + libc/intrin/getenv.c | 4 +- libc/intrin/psrldq.c | 1 - libc/intrin/quick_exit.c | 2 + libc/intrin/somanyasan.S | 4 +- libc/intrin/stracef.greg.c | 28 +++++ libc/log/libfatal.internal.h | 20 +++ libc/mem/putenv.c | 4 +- libc/mem/setenv.c | 4 +- libc/runtime/arememoryintervalsok.c | 6 +- libc/runtime/clearenv.c | 2 + libc/runtime/cosmo.S | 25 +++- libc/runtime/dsohandle.S | 2 + libc/runtime/exit.c | 2 + libc/runtime/finddebugbinary.c | 63 ++++------ libc/runtime/fork-nt.c | 19 ++- libc/runtime/fork.c | 6 +- libc/runtime/ftrace-hook.S | 2 +- .../{ftraceinit.c => ftraceinit.greg.c} | 25 +--- libc/runtime/interceptflag.greg.c | 46 +++++++ libc/runtime/internal.h | 1 + libc/runtime/memtrack.c | 10 +- libc/runtime/memtrack.internal.h | 4 +- libc/runtime/memtracknt.c | 6 +- libc/runtime/mmap.c | 74 ++++++----- libc/runtime/mremap.c | 33 +++-- libc/runtime/munmap.c | 27 ++-- libc/runtime/opensymboltable.c | 4 +- libc/runtime/printargs.c | 116 ++++++++++++++++++ libc/runtime/straceinit.greg.c | 37 ++++++ libc/runtime/vfork.S | 31 +++-- libc/runtime/winmain.greg.c | 6 + libc/sock/accept4.c | 22 ++-- libc/sock/bind.c | 22 ++-- libc/sock/connect.c | 25 ++-- libc/sock/getpeername.c | 19 ++- libc/sock/getsockname.c | 19 ++- libc/sock/inet_ntop.c | 13 +- libc/sock/internal.h | 11 +- libc/sock/listen.c | 10 +- libc/sock/poll.c | 15 ++- libc/sock/shutdown.c | 10 +- libc/sock/sock.h | 27 ++-- libc/sock/sockdebug.c | 114 +++++++++++++++++ libc/sock/sockdebug.h | 14 +++ libc/sock/socket.c | 21 ++-- libc/stdio/fopen.c | 4 +- libc/str/istext.c | 2 +- libc/str/isutf8.c | 2 +- libc/str/str.h | 4 +- .../describeos.c => sysv/describeos.greg.c} | 20 ++- libc/sysv/strace.greg.c | 21 ++++ libc/sysv/systemfive.S | 48 ++++++-- libc/sysv/sysv.mk | 5 + libc/unicode/unicode-properties.txt | 7 ++ libc/x/x.h | 5 + libc/x/xsigaction.c | 4 +- libc/zipos/zipos.internal.h | 2 +- test/libc/sock/inet_ntop_test.c | 6 +- third_party/chibicc/test/test.mk | 1 + tool/build/lib/elfwriter_zip.c | 4 +- tool/net/redbean.c | 4 +- 138 files changed, 1519 insertions(+), 631 deletions(-) rename libc/{runtime => calls}/describeframe.c (89%) rename libc/{runtime => calls}/describemapping.c (88%) rename libc/{runtime => calls}/directmap-metal.c (100%) rename libc/{runtime => calls}/directmap-nt.c (87%) rename libc/{runtime => calls}/directmap.c (80%) rename libc/{runtime => calls}/mman.greg.c (100%) rename libc/{runtime/mremap-sysv.c => calls/mremap-sysv.greg.c} (85%) rename libc/{runtime => calls}/munmap-metal.c (100%) rename libc/{runtime => calls}/munmap-sysv.c (93%) create mode 100644 libc/calls/strace.internal.h create mode 100644 libc/calls/strace_rlimit.c create mode 100644 libc/calls/strace_sigaction.greg.c create mode 100644 libc/calls/strace_sigset.greg.c create mode 100644 libc/calls/strace_stat.greg.c delete mode 100644 libc/calls/sysdebug.internal.h create mode 100644 libc/intrin/stracef.greg.c rename libc/runtime/{ftraceinit.c => ftraceinit.greg.c} (84%) create mode 100644 libc/runtime/interceptflag.greg.c create mode 100644 libc/runtime/printargs.c create mode 100644 libc/runtime/straceinit.greg.c create mode 100644 libc/sock/sockdebug.c create mode 100644 libc/sock/sockdebug.h rename libc/{runtime/describeos.c => sysv/describeos.greg.c} (86%) create mode 100644 libc/sysv/strace.greg.c diff --git a/build/config.mk b/build/config.mk index f2b48affa..ceb7f9764 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 101f6dfb8..07b57656d 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 680120710..ae30694a1 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 fde8e689a..be7b86d30 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 6d1f04e09..1dc78593f 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 3dffeab43..93e4f9d74 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 e50ce99d6..d083fe371 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 ab1a121b8..a07365028 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 13b9ee6e3..e8c010801 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 4ec133e97..108f739df 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 fc6e19858..717518fd7 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 8e9fa67ae..f7a278ecb 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]); - } - kprintf("}, {"); - for (i = 0; envp[i]; ++i) { - if (i) kprintf(", "); - kprintf("%s", envp[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()) { - return sys_execve(program, argv, envp); + if (!prog || !argv || !envp || + (IsAsan() && + (!__asan_is_valid(prog, 1) || !__asan_is_valid_strlist(argv) || + !__asan_is_valid_strlist(envp)))) { + rc = efault(); } else { - return sys_execve_nt(program, argv, envp); +#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"); + } +#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); + } + } + if (!IsWindows()) { + rc = sys_execve(prog, argv, envp); + } else { + rc = sys_execve_nt(prog, 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 d33db04cf..75db6c761 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 4b408dcf6..e4b55f6e8 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 230fcb045..40ce8f3da 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 7da2a6f30..2f63c4281 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 ad6de423a..164b0bee9 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 c8f7af7f9..8d6a1a058 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 fd4bce286..c2909562a 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 f8ac0f054..e05714552 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 e41f50834..3ae6364b9 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 db489f107..1dc1357d3 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 39a8b4476..99b6286ec 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 a55b2fca4..5c17d5780 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 4e7d3a999..b444acd84 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 536d8df79..caa17091f 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 476df9bda..57b8937a9 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(); - } - if (!IsWindows()) { - return sys_getitimer(which, curvalue); + rc = efault(); + } else if (!IsWindows()) { + rc = sys_getitimer(which, curvalue); + } else if (!curvalue) { + rc = efault(); } else { - if (!curvalue) return efault(); - return sys_setitimer_nt(which, 0, curvalue); + rc = sys_setitimer_nt(which, 0, 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 { + STRACE("getitimer(%d, 0) → %d% m", which, rc); + } + return rc; } diff --git a/libc/calls/getpgid.c b/libc/calls/getpgid.c index 8f8d0cac5..8ae485a7e 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 c651a3f70..17f117bde 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 a2f057528..4c29139f2 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 f801a93f7..34eb2702f 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 debafc1b4..a1b41bea4 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 564fcb772..5e9a7aa83 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 a89abb0b8..4f665b2db 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 c1c927889..2b92d3115 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 f79f7ca6d..f8de085a6 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 66d0022d4..ca938c130 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 2df6171c0..05ef16efb 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 e391f3bef..07961309f 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 6592ff700..ce50c0002 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 d73571ae3..d4f2c7b51 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 29ccaedb4..b34f83418 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 33b13d598..63d2b9715 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 0f60e65ff..85248baad 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 a2f4e2cef..7dc8f49b7 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 76303f161..83e5dd297 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 c4db57ac6..2d93337da 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 79104c1c3..07f3a72a1 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 @@ TryAgain: 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 a9f30a27a..6f53b38d1 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 501f54d0a..00f1ad729 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 1ce657307..81ef62957 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 38845cf97..97ecf0468 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 13300daca..ade680471 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 93e4dcf81..9b946c6a9 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 2708f6968..56316ec6e 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 f98061d88..cf7eec9ce 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 c268fa279..04b744961 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 332efffcc..ae9e2b121 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 a8dd0cd49..239c90220 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 754fe4e95..3f2a74eb0 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; + rc = -1; } } else { - return enosys(); - } - if ((rc = sys_sigaltstack(a, b)) != -1) { - if (IsBsd() && old) { - sigaltstack2linux(old, &bsd); - } - 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 e9dd0202c..148a351c3 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 d699b173d..c27c6a8e8 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 a9bb56e03..b62ac6ef0 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 000000000..1e2e9ecc1 --- /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 000000000..58b4aea71 --- /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 000000000..e34df149b --- /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 000000000..f083d75c6 --- /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 000000000..475e2c023 --- /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 bc9efeb3c..000000000 --- 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 a5fa862c2..a55a4a46e 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 f74f75c6b..a6c83dcac 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 32259c4d1..62aa0b55c 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 73a0879fa..3ce36c7ef 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 a0a770238..86ca692bb 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 3aa83de4a..d6e3e6eb4 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 505d870e1..9ed38136a 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 54e37e172..1970c534c 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 41d41d4c4..a473f4a8b 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 000000000..ab5fbc4fe --- /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 7e8a77a5d..f53aad990 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 b2f6c41a9..27ff77240 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 c7e24ff26..bb9c33cdc 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 8c20eb623..1a4969a14 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 46308f92a..c37f1fb53 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 5760a93b0..f96856964 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 6e9d6d6ae..136dd405b 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 6818ff1fc..3dcaad2ce 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 5df30e39d..72c87233c 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() { - char *p; - size_t n; - static bool once; - if (!once) { - if (!(g_comdbg = getenv("COMDBG"))) { - p = program_executable_name; - n = strlen(p); - if (n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) { - g_comdbg = 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; - } - } 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; - } - } - } - once = true; - } -} - /** * 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; + static bool once; + static char *res; + static char buf[PATH_MAX + 1]; + char *p; + size_t n; + if (!once) { + if (!(res = getenv("COMDBG"))) { + p = program_executable_name; + n = strlen(p); + if (n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) { + res = p; + } else if (n > 4 && READ32LE(p + n - 4) == READ32LE(".com") && + n + 4 <= PATH_MAX) { + mempcpy(mempcpy(buf, p, n), ".dbg", 5); + if (fileexists(buf)) { + res = buf; + } + } else if (n + 8 <= PATH_MAX) { + mempcpy(mempcpy(buf, p, n), ".com.dbg", 9); + if (fileexists(buf)) { + res = buf; + } + } + } + once = true; + } + return res; } - -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 c455c792c..7aefaa140 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 5d47e474a..14a94670b 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 f17c1bb7a..a679c52b1 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 cd6af1c9f..48bbc05aa 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 000000000..026ea4dbe --- /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 3b0e05e97..1942922d1 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 127bef8a7..a3b2783f9 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 1fb01f238..18ae776f1 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 f6dc682ca..3873f1cfa 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 ee58ac8cf..0b0267441 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 dc9b8ead1..82dad601e 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 45098727e..6073bc969 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 6d2d229c4..d615ed020 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 @@ RaiseEnobufs: 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 000000000..986be2115 --- /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 000000000..5c43e462a --- /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 197d6f763..11c6e1cfb 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 35ffb0810..72c8fdb04 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 1d24bb048..85c871898 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 28cb9c689..a65c7bc6c 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 279312481..41e39882f 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 444a3e60c..0fbf32df7 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 49c7e9dbe..fac44ca1a 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 3e8fbe99c..afbc88d94 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 312826592..7126f5798 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 65c1465c1..a3500345f 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 38fa964f7..bf5e5e23f 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 2183b2f2f..7c9f3df8c 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 6eb96b9ca..95c9d7bcc 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 000000000..42e5c12c7 --- /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 000000000..f85b99bff --- /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 f668a5f00..e7b6a4d13 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 722d26480..3e78067fc 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 0a75f6021..460626572 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 983ce7282..9155c5e4a 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 1f63ad427..fca378aa8 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 ded8f3185..1b0f37c6a 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 000000000..cd75bfa5f --- /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 f2b5f9bca..8a8995720 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 1b01db90e..42d389fc7 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 bbd3eaea2..f208c7cfb 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 3166a0bb5..a4d2b5ea2 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 de964a857..3a64fda0f 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 e659160ba..9d1cb4123 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 261bbcd70..a98ab7671 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 61824fda4..e42be50b0 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 0f48e0027..3501bb0d1 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 0eaf4a705..8eefef989 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;