From 67b5200a0b8b42f1b06d43ac91161e9c19853e9a Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Thu, 14 Oct 2021 19:36:49 -0700 Subject: [PATCH] Add MODE=optlinux build mode (#141) --- build/bootstrap/compile.com | Bin 81920 -> 86016 bytes build/config.mk | 79 ++++++------ build/definitions.mk | 3 +- examples/examples.mk | 8 ++ libc/calls/addrusage.c | 7 +- .../tinystrlen.greg.S => calls/addtimespec.c} | 36 +++--- libc/calls/addtimeval.c | 16 ++- libc/calls/fchmodat.c | 12 +- libc/calls/fileexists.c | 27 ++-- libc/calls/ftok.c | 3 + libc/calls/getenv.c | 8 +- libc/calls/isdirectory.c | 26 ++-- libc/calls/math.h | 4 +- libc/calls/mkntenvblock.c | 16 ++- libc/calls/openat-sysv.c | 8 -- libc/calls/openat.c | 38 ++++-- libc/calls/read.c | 26 +++- libc/calls/sigaltstack.c | 2 +- libc/calls/unsetenv.c | 6 +- libc/calls/write.c | 25 +++- libc/crt/crt.S | 1 + libc/fmt/stoa.c | 6 +- libc/intrin/asan.c | 2 +- libc/intrin/macros.h | 6 +- libc/intrin/ntgetversion.c | 2 +- .../tinystrlen16.greg.S => intrin/oldstack.c} | 25 +--- libc/intrin/printf.c | 27 ++-- libc/log/backtrace.internal.h | 8 ++ libc/log/backtrace2.c | 9 ++ libc/log/backtrace3.c | 4 + libc/log/checkfail_ndebug.c | 22 +--- libc/log/die.c | 12 +- libc/log/internal.h | 1 - libc/log/libfatal.internal.h | 53 +++++++- libc/log/oncrash.c | 6 +- libc/log/startfatal.c | 1 - libc/mem/putenv.c | 11 +- libc/nexgen32e/nexgen32e.mk | 5 - libc/nexgen32e/strsak16.S | 26 ---- libc/nexgen32e/strsak32.S | 3 +- libc/nexgen32e/tinystrlen.internal.h | 55 -------- libc/nexgen32e/tinystrnlen.greg.S | 39 ------ libc/runtime/arememoryintervalsok.c | 3 + libc/runtime/assertfail.c | 7 +- libc/runtime/describeframe.c | 2 +- libc/runtime/directmap-nt.c | 2 +- libc/runtime/finddebugbinary.c | 1 + libc/runtime/getdosenviron.c | 12 +- libc/runtime/memtrack.c | 104 ++++++--------- libc/runtime/memtrack.internal.h | 50 +++++--- libc/runtime/mmap.c | 120 +++++++++++++----- libc/runtime/mremap.c | 1 - libc/runtime/munmap.c | 15 ++- libc/runtime/peekall.S | 10 +- libc/runtime/print.greg.c | 76 ----------- libc/runtime/printmemoryintervals.c | 10 +- libc/runtime/program_executable_name.c | 1 + libc/runtime/runtime.h | 3 +- libc/runtime/stack.h | 21 +-- libc/runtime/winmain.greg.c | 5 +- .../findembeddedape.c} | 71 +++++------ libc/str/oldutf16.internal.h | 4 + .../startfatal_ndebug.c => str/strlen16.c} | 41 +++--- .../tinystrnlen16.greg.S => str/strnlen16.c} | 44 +++---- libc/str/tpdecode.internal.h | 2 +- libc/str/tpenc.h | 2 +- libc/sysv/errfuns.h | 2 +- libc/sysv/syscall.S | 2 +- libc/testlib/benchrunner.c | 4 + libc/testlib/leaks.c | 2 +- libc/testlib/quota.c | 4 +- libc/testlib/showerror.c | 78 ++++-------- libc/testlib/testmain.c | 2 +- libc/x/makedirs.c | 4 +- libc/x/utf8toutf16.c | 35 ++--- libc/zip.h | 1 + libc/zipos/get.c | 9 +- test/libc/calls/getenv_test.c | 8 +- test/libc/calls/mkntenvblock_test.c | 18 +-- test/libc/calls/stat_test.c | 45 +++++++ test/libc/calls/test.mk | 2 + test/libc/calls/write_test.c | 46 +++++++ test/libc/log/backtrace_test.c | 8 ++ test/libc/release/emulate.sh | 2 +- test/libc/release/metal.sh | 3 +- test/libc/runtime/getdosenviron_test.c | 2 +- test/libc/runtime/memtrack_test.c | 2 + test/libc/str/strlen_test.c | 35 ----- test/libc/xed/test.mk | 1 + third_party/infozip/zip/tailor.h | 5 +- third_party/infozip/zip/util.c | 65 ---------- third_party/infozip/zip/zip.c | 2 - third_party/infozip/zip/zipcloak.c | 2 - third_party/infozip/zip/zipnote.c | 2 - third_party/infozip/zip/zipsplit.c | 2 - third_party/mbedtls/ssl_cli.c | 2 +- third_party/python/Lib/idlelib/config.py | 2 +- third_party/python/Lib/ipaddress.py | 4 +- third_party/python/Lib/smtplib.py | 2 +- third_party/python/Lib/test/hello.com | Bin 0 -> 21888 bytes third_party/python/Lib/test/test_cosmo.py | 22 ++++ .../python/Lib/test/test_urllib2_localnet.py | 2 +- third_party/python/Objects/dictobject.c | 9 +- third_party/python/Objects/object.c | 9 +- third_party/python/Objects/typeobject.c | 16 ++- third_party/python/Objects/unicodeobject.c | 18 ++- third_party/python/python.mk | 10 ++ tool/build/compile.c | 10 ++ tool/build/lib/getargs.c | 2 +- tool/emacs/cosmo-cpp-constants.el | 4 +- tool/net/redbean.c | 2 +- 111 files changed, 934 insertions(+), 854 deletions(-) rename libc/{nexgen32e/tinystrlen.greg.S => calls/addtimespec.c} (74%) rename libc/{nexgen32e/tinystrlen16.greg.S => intrin/oldstack.c} (73%) delete mode 100644 libc/nexgen32e/tinystrlen.internal.h delete mode 100644 libc/nexgen32e/tinystrnlen.greg.S delete mode 100644 libc/runtime/print.greg.c rename libc/{nexgen32e/tinystrncmp.ncabi.S => str/findembeddedape.c} (59%) rename libc/{log/startfatal_ndebug.c => str/strlen16.c} (68%) rename libc/{nexgen32e/tinystrnlen16.greg.S => str/strnlen16.c} (72%) create mode 100644 test/libc/calls/write_test.c create mode 100755 third_party/python/Lib/test/hello.com create mode 100644 third_party/python/Lib/test/test_cosmo.py diff --git a/build/bootstrap/compile.com b/build/bootstrap/compile.com index 42010772c0eb4de426c68d7a3bba5db83a1a7cc0..9724f350ba1e029a6ec0c425c67ad626061c8afc 100755 GIT binary patch delta 38086 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Ů}?k%GSP6(#KPj}x^Y7PD7B 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, &y->ru_utime); - AddTimeval(&x->ru_stime, &y->ru_stime); + x->ru_utime = AddTimeval(x->ru_utime, y->ru_utime); + x->ru_stime = AddTimeval(x->ru_stime, y->ru_stime); x->ru_maxrss = MAX(x->ru_maxrss, y->ru_maxrss); x->ru_ixrss += y->ru_ixrss; x->ru_idrss += y->ru_idrss; diff --git a/libc/nexgen32e/tinystrlen.greg.S b/libc/calls/addtimespec.c similarity index 74% rename from libc/nexgen32e/tinystrlen.greg.S rename to libc/calls/addtimespec.c index 2bb9cd236..94b8e1bfe 100644 --- a/libc/nexgen32e/tinystrlen.greg.S +++ b/libc/calls/addtimespec.c @@ -1,7 +1,7 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,21 +16,17 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.internal.h" +#include "libc/calls/math.h" -// 8-bit strlen that's tiny and near optimal if data's tiny. -// -// @param RDI is char *s -// @param EAX is unsigned length -// @see libc/nexgen32e/strsak.S -tinystrlen: - .leafprologue - .profilable - xor %eax,%eax -1: cmpb $0,(%rdi,%rax) - jz 2f - inc %eax - jmp 1b -2: .leafepilogue - .endfn tinystrlen,globl - .source __FILE__ +/** + * Adds two microsecond timestamps. + */ +struct timespec AddTimespec(struct timespec x, struct timespec y) { + x.tv_sec += y.tv_sec; + x.tv_nsec += y.tv_nsec; + if (x.tv_nsec >= 10000000000) { + x.tv_nsec -= 10000000000; + x.tv_sec += 1; + } + return x; +} diff --git a/libc/calls/addtimeval.c b/libc/calls/addtimeval.c index 38ae4e369..ed3e522a9 100644 --- a/libc/calls/addtimeval.c +++ b/libc/calls/addtimeval.c @@ -18,11 +18,15 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/math.h" -void AddTimeval(struct timeval *x, const struct timeval *y) { - x->tv_sec += y->tv_sec; - x->tv_usec += y->tv_usec; - if (x->tv_usec >= 1000000) { - x->tv_usec -= 1000000; - x->tv_sec += 1; +/** + * Adds two microsecond timestamps. + */ +struct timeval AddTimeval(struct timeval x, struct timeval y) { + x.tv_sec += y.tv_sec; + x.tv_usec += y.tv_usec; + if (x.tv_usec >= 1000000) { + x.tv_usec -= 1000000; + x.tv_sec += 1; } + return x; } diff --git a/libc/calls/fchmodat.c b/libc/calls/fchmodat.c index 38d9edef2..d33db04cf 100644 --- a/libc/calls/fchmodat.c +++ b/libc/calls/fchmodat.c @@ -19,6 +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/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/sysv/errfuns.h" @@ -39,9 +40,16 @@ * @see fchmod() */ 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) { - return -1; /* TODO(jart): implement me */ + rc = -1; /* TODO(jart): implement me */ + } else if (!IsWindows()) { + rc = sys_fchmodat(dirfd, path, mode, flags); + } else { + rc = sys_fchmodat_nt(dirfd, path, mode, flags); } - return sys_fchmodat(dirfd, path, mode, flags); + SYSDEBUG("fchmodat(%d, %s, %o, %d) -> %d %s", (long)dirfd, path, mode, flags, + rc != -1 ? "" : strerror(errno)); + return rc; } diff --git a/libc/calls/fileexists.c b/libc/calls/fileexists.c index b2b3b0899..ad6de423a 100644 --- a/libc/calls/fileexists.c +++ b/libc/calls/fileexists.c @@ -44,30 +44,35 @@ */ bool fileexists(const char *path) { int e; + bool res; union metastat st; struct ZiposUri zipname; uint16_t path16[PATH_MAX]; + e = errno; if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { - e = errno; if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) { - return true; + res = true; } else { - errno = e; - return false; + res = false; } } else if (IsMetal()) { - return false; + res = false; } else if (!IsWindows()) { - e = errno; if (__sys_fstatat(AT_FDCWD, path, &st, 0) != -1) { - return true; + res = true; } else { - errno = e; - return false; + res = false; } + } else if (__mkntpath(path, path16) != -1) { + res = GetFileAttributes(path16) != -1u; } else { - if (__mkntpath(path, path16) == -1) return -1; - return GetFileAttributes(path16) != -1u; + res = false; } + SYSDEBUG("fileexists(%s) -> %s %s", path, res ? "true" : "false", + res ? "" : strerror(errno)); + if (!res && (errno == ENOENT || errno == ENOTDIR)) { + errno = e; + } + return res; } diff --git a/libc/calls/ftok.c b/libc/calls/ftok.c index 291964e93..f5c3152b5 100644 --- a/libc/calls/ftok.c +++ b/libc/calls/ftok.c @@ -21,6 +21,9 @@ #include "libc/calls/weirdtypes.h" #include "libc/str/str.h" +/** + * Convert pathname and a project ID to System V IPC key. + */ int ftok(const char *path, int id) { struct stat st; if (stat(path, &st) == -1) return -1; diff --git a/libc/calls/getenv.c b/libc/calls/getenv.c index a85c9f6b6..6d0025cef 100644 --- a/libc/calls/getenv.c +++ b/libc/calls/getenv.c @@ -16,8 +16,12 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/dce.h" #include "libc/runtime/runtime.h" +#define ToUpper(c) \ + (IsWindows() && (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c)) + /** * Returns value of environment variable, or NULL if not found. * @@ -35,11 +39,11 @@ char *getenv(const char *s) { } break; } - if (s[j] != p[i][j]) { + if (ToUpper(s[j]) != ToUpper(p[i][j])) { break; } } } } - return NULL; + return 0; } diff --git a/libc/calls/isdirectory.c b/libc/calls/isdirectory.c index a0e863081..c1c927889 100644 --- a/libc/calls/isdirectory.c +++ b/libc/calls/isdirectory.c @@ -21,6 +21,7 @@ #include "libc/calls/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" @@ -43,29 +44,34 @@ * @see isregularfile(), issymlink(), ischardev() */ bool isdirectory(const char *path) { - int rc, e; + int e; + bool res; union metastat st; struct ZiposUri zipname; + e = errno; if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { - e = errno; if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) { - return S_ISDIR(st.cosmo.st_mode); + res = S_ISDIR(st.cosmo.st_mode); } else { - errno = e; - return false; + res = false; } } else if (IsMetal()) { - return false; + res = false; } else if (!IsWindows()) { e = errno; if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) { - return S_ISDIR(METASTAT(st, st_mode)); + res = S_ISDIR(METASTAT(st, st_mode)); } else { - errno = e; - return false; + res = false; } } else { - return isdirectory_nt(path); + res = isdirectory_nt(path); } + SYSDEBUG("isdirectory(%s) -> %s %s", path, res ? "true" : "false", + res ? "" : strerror(errno)); + if (!res && (errno == ENOENT || errno == ENOTDIR)) { + errno = e; + } + return res; } diff --git a/libc/calls/math.h b/libc/calls/math.h index e99faa9db..ce878d394 100644 --- a/libc/calls/math.h +++ b/libc/calls/math.h @@ -1,11 +1,13 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_MATH_H_ #define COSMOPOLITAN_LIBC_CALLS_MATH_H_ #include "libc/calls/struct/rusage.h" +#include "libc/calls/struct/timespec.h" #include "libc/calls/struct/timeval.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -void AddTimeval(struct timeval *, const struct timeval *); +struct timeval AddTimeval(struct timeval, struct timeval); +struct timespec AddTimespec(struct timespec, struct timespec); void AddRusage(struct rusage *, const struct rusage *); COSMOPOLITAN_C_END_ diff --git a/libc/calls/mkntenvblock.c b/libc/calls/mkntenvblock.c index 9884faeaa..5c94eb3d0 100644 --- a/libc/calls/mkntenvblock.c +++ b/libc/calls/mkntenvblock.c @@ -29,10 +29,13 @@ #include "libc/str/utf16.h" #include "libc/sysv/errfuns.h" +#define ToUpper(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c)) + static noasan int CompareStrings(const char *l, const char *r) { + int a, b; size_t i = 0; - while (l[i] == r[i] && r[i]) ++i; - return (l[i] & 0xff) - (r[i] & 0xff); + while ((a = ToUpper(l[i] & 255)) == (b = ToUpper(r[i] & 255)) && r[i]) ++i; + return a - b; } static noasan void InsertString(char **a, size_t i, char *s) { @@ -56,6 +59,7 @@ static noasan void InsertString(char **a, size_t i, char *s) { */ textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX], char *const envp[], const char *extravar) { + bool v; char *t; axdx_t rc; uint64_t w; @@ -68,6 +72,7 @@ textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX], if (extravar) InsertString(vars, n++, extravar); for (k = i = 0; i < n; ++i) { j = 0; + v = false; do { x = vars[i][j++] & 0xff; if (x >= 0200) { @@ -83,6 +88,13 @@ textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX], } } } + if (!v) { + if (x != '=') { + x = ToUpper(x); + } else { + v = true; + } + } w = EncodeUtf16(x); do { envvars[k++] = w & 0xffff; diff --git a/libc/calls/openat-sysv.c b/libc/calls/openat-sysv.c index 79d7a71ca..d9c3bc659 100644 --- a/libc/calls/openat-sysv.c +++ b/libc/calls/openat-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/errno.h" #include "libc/str/str.h" @@ -59,12 +58,5 @@ int sys_openat(int dirfd, const char *file, int flags, unsigned mode) { d = sys_openat(dirfd, file, flags, mode); } } - if (d != -1) { - SYSDEBUG("sys_openat(%d, %s, %d, %d) -> %d", (long)dirfd, file, flags, - (flags & (O_CREAT | O_TMPFILE)) ? mode : 0, d); - } else { - SYSDEBUG("sys_openat(%d, %s, %d, %d) -> %s", (long)dirfd, file, flags, - (flags & (O_CREAT | O_TMPFILE)) ? mode : 0, strerror(errno)); - } return d; } diff --git a/libc/calls/openat.c b/libc/calls/openat.c index 65771fc40..501f54d0a 100644 --- a/libc/calls/openat.c +++ b/libc/calls/openat.c @@ -19,6 +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/dce.h" #include "libc/intrin/asan.internal.h" #include "libc/log/log.h" @@ -43,24 +44,37 @@ * @vforksafe */ int openat(int dirfd, const char *file, int flags, ...) { + int rc; va_list va; unsigned mode; struct ZiposUri zipname; va_start(va, flags); mode = va_arg(va, unsigned); va_end(va); - if (!file) return efault(); - if (IsAsan() && !__asan_is_valid(file, 1)) return efault(); - if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */ - if (weaken(__zipos_open) && weaken(__zipos_parseuri)(file, &zipname) != -1) { - if (__vforked) return eopnotsupp(); - if (dirfd != AT_FDCWD) return eopnotsupp(); - return weaken(__zipos_open)(&zipname, flags, mode); - } else if (!IsWindows() && !IsMetal()) { - return sys_openat(dirfd, file, flags, mode); - } else if (IsMetal()) { - return sys_openat_metal(dirfd, file, flags, mode); + if (file && (!IsAsan() || __asan_is_valid(file, 1))) { + if (!__isfdkind(dirfd, kFdZip)) { + if (weaken(__zipos_open) && + weaken(__zipos_parseuri)(file, &zipname) != -1) { + if (!__vforked && dirfd == AT_FDCWD) { + rc = weaken(__zipos_open)(&zipname, flags, mode); + } else { + rc = eopnotsupp(); /* TODO */ + } + } else if (!IsWindows() && !IsMetal()) { + rc = sys_openat(dirfd, file, flags, mode); + } else if (IsMetal()) { + rc = sys_openat_metal(dirfd, file, flags, mode); + } else { + rc = sys_open_nt(dirfd, file, flags, mode); + } + } else { + rc = eopnotsupp(); /* TODO */ + } } else { - return sys_open_nt(dirfd, file, flags, mode); + 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) : ""); + return rc; } diff --git a/libc/calls/read.c b/libc/calls/read.c index c7a78fda9..1a33b0d4c 100644 --- a/libc/calls/read.c +++ b/libc/calls/read.c @@ -16,9 +16,16 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/weaken.h" #include "libc/calls/calls.h" +#include "libc/calls/internal.h" #include "libc/calls/struct/iovec.h" +#include "libc/dce.h" +#include "libc/intrin/asan.internal.h" +#include "libc/sock/internal.h" #include "libc/sock/sock.h" +#include "libc/sysv/errfuns.h" +#include "libc/zipos/zipos.internal.h" /** * Reads data from file descriptor. @@ -32,5 +39,22 @@ * @asyncsignalsafe */ ssize_t read(int fd, void *buf, size_t size) { - return readv(fd, &(struct iovec){buf, size}, 1); + if (fd >= 0) { + if (IsAsan() && !__asan_is_valid(buf, size)) return efault(); + if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { + return weaken(__zipos_read)( + (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, + &(struct iovec){buf, size}, 1, -1); + } else if (!IsWindows() && !IsMetal()) { + return sys_read(fd, buf, size); + } else if (fd >= g_fds.n) { + return ebadf(); + } else if (IsMetal()) { + return sys_readv_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1); + } else { + return sys_readv_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1); + } + } else { + return einval(); + } } diff --git a/libc/calls/sigaltstack.c b/libc/calls/sigaltstack.c index 6db0aba90..754fe4e95 100644 --- a/libc/calls/sigaltstack.c +++ b/libc/calls/sigaltstack.c @@ -96,7 +96,7 @@ noasan int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) { return enosys(); } if ((rc = sys_sigaltstack(a, b)) != -1) { - if (old) { + if (IsBsd() && old) { sigaltstack2linux(old, &bsd); } return 0; diff --git a/libc/calls/unsetenv.c b/libc/calls/unsetenv.c index e2bfbc75a..36f80704b 100644 --- a/libc/calls/unsetenv.c +++ b/libc/calls/unsetenv.c @@ -17,9 +17,13 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/weaken.h" +#include "libc/dce.h" #include "libc/mem/internal.h" #include "libc/runtime/runtime.h" +#define ToUpper(c) \ + (IsWindows() && (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c)) + /** * Removes environment variable. */ @@ -42,7 +46,7 @@ int unsetenv(const char *s) { } break; } - if (s[j] != p[i][j]) { + if (ToUpper(s[j]) != ToUpper(p[i][j])) { break; } } diff --git a/libc/calls/write.c b/libc/calls/write.c index f7120ff03..2b7866288 100644 --- a/libc/calls/write.c +++ b/libc/calls/write.c @@ -16,8 +16,14 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/weaken.h" +#include "libc/calls/internal.h" #include "libc/calls/struct/iovec.h" +#include "libc/dce.h" +#include "libc/intrin/asan.internal.h" #include "libc/sock/sock.h" +#include "libc/sysv/errfuns.h" +#include "libc/zipos/zipos.internal.h" /** * Writes data to file descriptor. @@ -31,5 +37,22 @@ * @asyncsignalsafe */ ssize_t write(int fd, const void *buf, size_t size) { - return writev(fd, &(struct iovec){buf, size}, 1); + if (fd >= 0) { + if (IsAsan() && !__asan_is_valid(buf, size)) return efault(); + if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { + return weaken(__zipos_write)( + (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, + &(struct iovec){buf, size}, 1, -1); + } else if (!IsWindows() && !IsMetal()) { + return sys_write(fd, buf, size); + } else if (fd >= g_fds.n) { + return ebadf(); + } else if (IsMetal()) { + return sys_writev_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1); + } else { + return sys_writev_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1); + } + } else { + return einval(); + } } diff --git a/libc/crt/crt.S b/libc/crt/crt.S index beaf1e657..4d0f82a63 100644 --- a/libc/crt/crt.S +++ b/libc/crt/crt.S @@ -37,6 +37,7 @@ _start: 0: mov (%rsp),%ebx # argc lea 8(%rsp),%rsi # argv lea 16(%rsp,%rbx,8),%rdx # envp + mov %rsp,__oldstack(%rip) .frame0 // bofram 9f .weak ape_idata_iat diff --git a/libc/fmt/stoa.c b/libc/fmt/stoa.c index 6040c1e08..239f49af7 100644 --- a/libc/fmt/stoa.c +++ b/libc/fmt/stoa.c @@ -16,13 +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/bits.h" #include "libc/bits/safemacros.internal.h" #include "libc/bits/weaken.h" #include "libc/fmt/fmts.h" #include "libc/fmt/internal.h" #include "libc/nexgen32e/bsr.h" -#include "libc/nexgen32e/tinystrlen.internal.h" #include "libc/str/str.h" #include "libc/str/thompike.h" #include "libc/str/tpenc.h" @@ -131,9 +131,9 @@ int __fmt_stoa(int out(const char *, void *, size_t), void *arg, void *data, if (!(flags & FLAGS_PRECISION)) precision = -1; if (!(flags & FLAGS_PRECISION) || !ignorenul) { if (signbit == 63) { - precision = tinywcsnlen((const wchar_t *)p, precision); + precision = wcsnlen((const wchar_t *)p, precision); } else if (signbit == 15) { - precision = tinystrnlen16((const char16_t *)p, precision); + precision = strnlen16((const char16_t *)p, precision); } else { precision = strnlen(p, precision); } diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index 78aedd951..c5befbf12 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -431,7 +431,7 @@ struct AsanFault __asan_check(const void *p, long n) { s = (signed char *)a; if (OverlapsShadowSpace(p, n)) { return (struct AsanFault){kAsanProtected, s}; - } else if (!(0 <= a && a <= 0x7fffffffffff) && !__asan_is_mapped(a >> 16)) { + } else if (IsLegalPointer(a) && !__asan_is_mapped(a >> 16)) { return (struct AsanFault){kAsanUnmapped, s}; } if (UNLIKELY(k)) { diff --git a/libc/intrin/macros.h b/libc/intrin/macros.h index 17a8426d9..d4e0dfa81 100644 --- a/libc/intrin/macros.h +++ b/libc/intrin/macros.h @@ -13,7 +13,7 @@ typedef char __intrin_xmm_t _Vector_size(16) forcealign(16) mayalias; #define INTRIN_SSEVEX_X_X_X_(PURE, ISA, OP, FLAGS, A, B, C) \ do { \ - if (!IsModeDbg() && X86_HAVE(ISA)) { \ + if (X86_HAVE(ISA)) { \ __intrin_xmm_t *Xmm0 = (void *)(A); \ const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \ const __intrin_xmm_t *Xmm2 = (const __intrin_xmm_t *)(C); \ @@ -29,7 +29,7 @@ typedef char __intrin_xmm_t _Vector_size(16) forcealign(16) mayalias; #define INTRIN_SSEVEX_X_X_I_(PURE, ISA, OP, A, B, I) \ do { \ - if (!IsModeDbg() && X86_HAVE(ISA)) { \ + if (X86_HAVE(ISA)) { \ __intrin_xmm_t *Xmm0 = (void *)(A); \ const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \ if (!X86_NEED(AVX)) { \ @@ -44,7 +44,7 @@ typedef char __intrin_xmm_t _Vector_size(16) forcealign(16) mayalias; #define INTRIN_SSEVEX_X_X_(PURE, ISA, OP, A, B) \ do { \ - if (!IsModeDbg() && X86_HAVE(ISA)) { \ + if (X86_HAVE(ISA)) { \ __intrin_xmm_t *Xmm0 = (void *)(A); \ const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \ if (!X86_NEED(AVX)) { \ diff --git a/libc/intrin/ntgetversion.c b/libc/intrin/ntgetversion.c index d06105118..57c7ea551 100644 --- a/libc/intrin/ntgetversion.c +++ b/libc/intrin/ntgetversion.c @@ -22,7 +22,7 @@ /** * Returns New Technology version, e.g. * - * if (IsWindows() && NtGetVersion() >= kNtVersionWindows10) {...} + * if (IsWindows() && NtGetVersion() >=k NtVersionWindows10) {...} * * This can only be called on Windows. */ diff --git a/libc/nexgen32e/tinystrlen16.greg.S b/libc/intrin/oldstack.c similarity index 73% rename from libc/nexgen32e/tinystrlen16.greg.S rename to libc/intrin/oldstack.c index dafa416a0..7ff03e021 100644 --- a/libc/nexgen32e/tinystrlen16.greg.S +++ b/libc/intrin/oldstack.c @@ -1,7 +1,7 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,21 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.internal.h" +#include "libc/runtime/runtime.h" -// 16-bit strlen that's tiny and near optimal if data's tiny. -// -// @param RDI is char16_t *s -// @param EAX is unsigned length -// @see libc/nexgen32e/strsak16.S -tinystrlen16: - .leafprologue - .profilable - xor %eax,%eax -1: cmpw $0,(%rdi,%rax,2) - jz 2f - inc %eax - jmp 1b -2: .leafepilogue - .endfn tinystrlen16,globl - .source __FILE__ +intptr_t __oldstack; diff --git a/libc/intrin/printf.c b/libc/intrin/printf.c index 8374bd263..1ad0b9a2b 100644 --- a/libc/intrin/printf.c +++ b/libc/intrin/printf.c @@ -25,17 +25,14 @@ #include "libc/sysv/consts/nr.h" /** - * Privileged printf. + * Privileged vprintf. * * This will work without any cosmopolitan runtime support once the * executable has been loaded into memory. */ -privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) { - /* system call support runtime depends on this function */ - /* function tracing runtime depends on this function */ - /* asan runtime depends on this function */ +privileged noasan noubsan noinstrument void __vprintf(const char *fmt, + va_list va) { short w[2]; - va_list va; uint16_t dx; const void *s; uint32_t wrote; @@ -46,7 +43,6 @@ privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) { char c, *p, *e, pad, bits, base, sign, thou, z[28], b[2048]; p = b; e = p + sizeof(b); - va_start(va, fmt); do { switch ((c = *fmt++)) { default: @@ -200,7 +196,6 @@ privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) { break; } } while (c); - va_end(va); if (p == e) { e[-4] = '.'; e[-3] = '.'; @@ -229,3 +224,19 @@ privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) { : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); } } + +/** + * Privileged printf. + * + * This will work without any cosmopolitan runtime support once the + * executable has been loaded into memory. + */ +privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) { + /* system call support runtime depends on this function */ + /* function tracing runtime depends on this function */ + /* asan runtime depends on this function */ + va_list va; + va_start(va, fmt); + __vprintf(fmt, va); + va_end(va); +} diff --git a/libc/log/backtrace.internal.h b/libc/log/backtrace.internal.h index bcd423568..0624bb59f 100644 --- a/libc/log/backtrace.internal.h +++ b/libc/log/backtrace.internal.h @@ -1,10 +1,18 @@ #ifndef COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_ #define COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_ #include "libc/nexgen32e/stackframe.h" +#include "libc/runtime/memtrack.internal.h" #include "libc/runtime/symbols.internal.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ +forceinline pureconst bool IsValidStackFramePointer(struct StackFrame *x) { + return IsLegalPointer(x) && !((uintptr_t)x & 15) && + (IsStaticStackFrame((uintptr_t)x >> 16) || + IsSigAltStackFrame((uintptr_t)x >> 16) || + IsOldStackFrame((uintptr_t)x >> 16)); +} + void ShowBacktrace(int, const struct StackFrame *); int PrintBacktraceUsingSymbols(int, const struct StackFrame *, struct SymbolTable *); diff --git a/libc/log/backtrace2.c b/libc/log/backtrace2.c index d3ac2922b..e5bb6b764 100644 --- a/libc/log/backtrace2.c +++ b/libc/log/backtrace2.c @@ -70,6 +70,9 @@ static noasan int PrintBacktraceUsingAddr2line(int fd, garbage = weaken(__garbage); gi = garbage ? garbage->i : 0; for (frame = bp; frame && i < kBacktraceMaxFrames - 1; frame = frame->next) { + if (!IsValidStackFramePointer(frame)) { + return -1; + } addr = frame->addr; if (addr == weakaddr("__gc")) { do { @@ -172,6 +175,7 @@ static noasan int PrintBacktrace(int fd, const struct StackFrame *bp) { } noasan void ShowBacktrace(int fd, const struct StackFrame *bp) { +#ifdef __FNO_OMIT_FRAME_POINTER__ /* asan runtime depends on this function */ static bool noreentry; ++g_ftrace; @@ -182,4 +186,9 @@ noasan void ShowBacktrace(int fd, const struct StackFrame *bp) { noreentry = false; } --g_ftrace; +#else + __printf("ShowBacktrace() needs these flags to show C backtrace:\n" + "\t-D__FNO_OMIT_FRAME_POINTER__\n" + "\t-fno-omit-frame-pointer\n"); +#endif } diff --git a/libc/log/backtrace3.c b/libc/log/backtrace3.c index 74a7318cd..ed2fc87d4 100644 --- a/libc/log/backtrace3.c +++ b/libc/log/backtrace3.c @@ -56,6 +56,10 @@ noinstrument noasan int PrintBacktraceUsingSymbols(int fd, garbage = weaken(__garbage); gi = garbage ? garbage->i : 0; for (i = 0, frame = bp; frame; frame = frame->next) { + if (!IsValidStackFramePointer(frame)) { + __printf("%p corrupt frame pointer\n", frame); + break; + } if (++i == LIMIT) { __printf("\n"); break; diff --git a/libc/log/checkfail_ndebug.c b/libc/log/checkfail_ndebug.c index a3a1a18c6..7217e487d 100644 --- a/libc/log/checkfail_ndebug.c +++ b/libc/log/checkfail_ndebug.c @@ -17,10 +17,10 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/errno.h" -#include "libc/fmt/itoa.h" #include "libc/log/internal.h" -#include "libc/log/log.h" +#include "libc/log/libfatal.internal.h" #include "libc/runtime/runtime.h" +#include "libc/str/str.h" /** * Handles failure of CHECK_xx() macros in -DNDEBUG mode. @@ -34,17 +34,9 @@ */ relegated void ___check_fail_ndebug(uint64_t want, uint64_t got, const char *opchar) { - char bx[21]; - int lasterr; - lasterr = errno; - __start_fatal_ndebug(); - __print_string("check failed: 0x"); - __print(bx, uint64toarray_radix16(want, bx)); - __print_string(" "); - __print_string(opchar); - __print_string(" 0x"); - __print(bx, uint64toarray_radix16(got, bx)); - __print_string(" ("); - __print(bx, int64toarray_radix10(lasterr, bx)); - __print_string(")\n"); + __restore_tty(1); + __printf("\n%serror: %s: check failed: 0x%x %s 0x%x (%s)\n", + !g_isterminalinarticulate ? "\e[J" : "", program_invocation_name, + want, opchar, got, strerror(errno)); + exit(1); } diff --git a/libc/log/die.c b/libc/log/die.c index 814ca2725..8893584a6 100644 --- a/libc/log/die.c +++ b/libc/log/die.c @@ -22,6 +22,7 @@ #include "libc/log/internal.h" #include "libc/log/libfatal.internal.h" #include "libc/log/log.h" +#include "libc/runtime/runtime.h" /** * Aborts process after printing a backtrace. @@ -33,11 +34,12 @@ relegated wontreturn void __die(void) { static bool once; if (cmpxchg(&once, false, true)) { __restore_tty(1); - if (IsDebuggerPresent(false)) DebugBreak(); + if (IsDebuggerPresent(false)) { + DebugBreak(); + } ShowBacktrace(2, NULL); - exit(77); - } else { - __write_str("PANIC: __DIE() DIED\r\n"); - _exit(78); + quick_exit(77); } + __write_str("PANIC: __DIE() DIED\r\n"); + _Exit(78); } diff --git a/libc/log/internal.h b/libc/log/internal.h index 0d59b9b33..298911be3 100644 --- a/libc/log/internal.h +++ b/libc/log/internal.h @@ -14,7 +14,6 @@ extern hidden struct termios g_oldtermios; extern hidden struct sigaction g_oldcrashacts[8]; void __start_fatal(const char *, int) hidden; -void __start_fatal_ndebug(void) hidden; void __oncrash(int, struct siginfo *, struct ucontext *) relegated; void __restore_tty(int); diff --git a/libc/log/libfatal.internal.h b/libc/log/libfatal.internal.h index aeb5e5c66..264c43a8f 100644 --- a/libc/log/libfatal.internal.h +++ b/libc/log/libfatal.internal.h @@ -1,5 +1,6 @@ #ifndef COSMOPOLITAN_LIBC_LOG_LIBFATAL_INTERNAL_H_ #define COSMOPOLITAN_LIBC_LOG_LIBFATAL_INTERNAL_H_ +#include "libc/calls/calls.h" #include "libc/dce.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/bsr.h" @@ -13,65 +14,96 @@ COSMOPOLITAN_C_START_ extern char __fatalbuf[]; void __printf(const char *, ...); +void __vprintf(const char *, va_list); -forceinline void __sysv_exit(long rc) { +forceinline long __sysv_exit(long rc) { + long ax; +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm volatile("call\t__syscall__" - : /* no outputs */ - : "a"(__NR_exit_group), "D"(rc) + : "=a"(ax) + : "0"(__NR_exit_group), "D"(rc) : "memory", "cc"); +#else + ax = syscall(__NR_exit_group, rc); +#endif + return ax; } forceinline int __sysv_close(long fd) { long ax; +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm volatile("call\t__syscall__" : "=a"(ax) : "0"(__NR_close), "D"(fd) : "rdx", "memory", "cc"); +#else + ax = syscall(__NR_close, fd); +#endif return ax; } forceinline int __sysv_open(const char *path, long flags, long mode) { long ax, dx; +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm volatile("call\t__syscall__" : "=a"(ax), "=d"(dx) : "0"(__NR_open), "D"(path), "S"(flags), "1"(mode) : "memory", "cc"); +#else + ax = syscall(__NR_open, path, flags, mode); +#endif return ax; } forceinline long __sysv_read(long fd, void *data, unsigned long size) { long ax, dx; +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm volatile("call\t__syscall__" : "=a"(ax), "=d"(dx) : "0"(__NR_read), "D"(fd), "S"(data), "1"(size) : "memory", "cc"); +#else + ax = syscall(__NR_read, fd, data, size); +#endif return ax; } forceinline long __sysv_write(long fd, const void *data, unsigned long size) { long ax, dx; +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm volatile("call\t__syscall__" : "=a"(ax), "=d"(dx) : "0"(__NR_write), "D"(fd), "S"(data), "1"(size) : "memory", "cc"); +#else + ax = syscall(__NR_write, fd, data, size); +#endif return ax; } forceinline long __sysv_mprotect(void *addr, size_t size, long prot) { long ax, dx; +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm volatile("call\t__syscall__" : "=a"(ax), "=d"(dx) : "0"(__NR_mprotect), "D"(addr), "S"(size), "1"(prot) : "memory", "cc"); +#else + ax = syscall(__NR_mprotect, addr, size, prot); +#endif return ax; } forceinline int __sysv_getpid(void) { long ax; +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm volatile("call\t__syscall__" : "=a"(ax) : "0"(__NR_getpid) : "rdx", "memory", "cc"); +#else + ax = syscall(__NR_getpid); +#endif return ax; } @@ -122,17 +154,32 @@ forceinline char *__stpcpy(char *d, const char *s) { } forceinline void *__repstosb(void *di, char al, size_t cx) { +#if defined(__x86__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm("rep stosb" : "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di) : "0"(di), "1"(cx), "a"(al)); return di; +#else + size_t i; + volatile char *volatile d = di; + while (cx--) *d++ = al; + return d; +#endif } forceinline void *__repmovsb(void *di, void *si, size_t cx) { +#if defined(__x86__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) asm("rep movsb" : "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di) : "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si)); return di; +#else + size_t i; + volatile char *volatile d = di; + volatile char *volatile s = si; + while (cx--) *d++ = *s++; + return d; +#endif } forceinline void *__mempcpy(void *d, const void *s, size_t n) { diff --git a/libc/log/oncrash.c b/libc/log/oncrash.c index 6e2508f35..81b32fec7 100644 --- a/libc/log/oncrash.c +++ b/libc/log/oncrash.c @@ -99,7 +99,11 @@ relegated static const char *TinyStrSignal(int sig) { relegated static void ShowFunctionCalls(ucontext_t *ctx) { struct StackFrame *bp; struct StackFrame goodframe; - if (ctx->uc_mcontext.rip && ctx->uc_mcontext.rbp) { + if (!ctx->uc_mcontext.rip) { + __printf("%s is NULL can't show backtrace\n", "RIP"); + } else if (!ctx->uc_mcontext.rbp) { + __printf("%s is NULL can't show backtrace\n", "RBP"); + } else { goodframe.next = (struct StackFrame *)ctx->uc_mcontext.rbp; goodframe.addr = ctx->uc_mcontext.rip; bp = &goodframe; diff --git a/libc/log/startfatal.c b/libc/log/startfatal.c index 667ba0e99..ac3b65096 100644 --- a/libc/log/startfatal.c +++ b/libc/log/startfatal.c @@ -25,7 +25,6 @@ * Prints initial part of fatal message. * * @note this is support code for __check_fail(), __assert_fail(), etc. - * @see __start_fatal_ndebug() */ relegated void __start_fatal(const char *file, int line) { bool colorful; diff --git a/libc/mem/putenv.c b/libc/mem/putenv.c index 38da4a8fc..56011f090 100644 --- a/libc/mem/putenv.c +++ b/libc/mem/putenv.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/alg/alg.h" +#include "libc/dce.h" #include "libc/mem/internal.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" @@ -25,6 +26,8 @@ #define MAX_VARS 512 +#define ToUpper(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c)) + static bool once; static void PutEnvDestroy(void) { @@ -56,8 +59,12 @@ int PutEnvImpl(char *s, bool overwrite) { PutEnvInit(); once = true; } - p = strchr(s, '='); - if (!p) goto fail; + for (p = s; *p && *p != '='; ++p) { + if (IsWindows()) { + *p = ToUpper(*p); + } + } + if (*p != '=') goto fail; namelen = p + 1 - s; for (i = 0; environ[i]; ++i) { if (!strncmp(environ[i], s, namelen)) { diff --git a/libc/nexgen32e/nexgen32e.mk b/libc/nexgen32e/nexgen32e.mk index 9583b8589..d00fbdd9a 100644 --- a/libc/nexgen32e/nexgen32e.mk +++ b/libc/nexgen32e/nexgen32e.mk @@ -42,11 +42,6 @@ $(LIBC_NEXGEN32E_A).pkg: \ $(LIBC_NEXGEN32E_A_OBJS) \ $(foreach x,$(LIBC_NEXGEN32E_A_DIRECTDEPS),$($(x)_A).pkg) -o/$(MODE)/libc/nexgen32e/tinystrlen.ncabi.o \ -o/$(MODE)/libc/nexgen32e/tinystrncmp.ncabi.o: \ - OVERRIDE_CFLAGS += \ - -Os - o/$(MODE)/libc/nexgen32e/errno.o: \ OVERRIDE_CFLAGS += \ $(NO_MAGIC) \ diff --git a/libc/nexgen32e/strsak16.S b/libc/nexgen32e/strsak16.S index acd0c41e0..c56674c32 100644 --- a/libc/nexgen32e/strsak16.S +++ b/libc/nexgen32e/strsak16.S @@ -95,32 +95,6 @@ strnlen16_s: .leafepilogue .endfn strnlen16_s,globl -// Returns length of NUL-terminated char16_t string. -// -// @param rdi is non-null NUL-terminated char16_t string pointer -// @return rax is the number of shorts, excluding the NUL -// @asyncsignalsafe -strlen16: - or $-1,%rsi -// fallthrough - .endfn strlen16,globl - -// Returns length of NUL-terminated memory, with limit. -// -// @param rdi is non-null memory -// @param rsi is the maximum number of shorts to consider -// @return rax is the number of shorts, excluding the NUL -// @asyncsignalsafe -strnlen16: - .leafprologue - .profilable - or $-1,%r10 -0: xor %edx,%edx - xor %r11d,%r11d - mov %rdi,%r8 -// fallthrough - .endfn strnlen16,globl - // Swiss Army Knife of string char16_t scanning. // Sixteen fast functions in one. // diff --git a/libc/nexgen32e/strsak32.S b/libc/nexgen32e/strsak32.S index 296c84b91..84708e6ef 100644 --- a/libc/nexgen32e/strsak32.S +++ b/libc/nexgen32e/strsak32.S @@ -79,7 +79,8 @@ wcslen: or $-1,%rsi // @param rsi is the maximum number of chars to consider // @return rax is the number of chars, excluding the NUL // @asyncsignalsafe -wcsnlen:.leafprologue +wcsnlen: + .leafprologue .profilable or $-1,%r10 0: xor %edx,%edx diff --git a/libc/nexgen32e/tinystrlen.internal.h b/libc/nexgen32e/tinystrlen.internal.h deleted file mode 100644 index 591ddafdf..000000000 --- a/libc/nexgen32e/tinystrlen.internal.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_ -#define COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -#if !defined(__GNUC__) || defined(__STRICT_ANSI__) - -int tinystrlen(const char *); -int tinystrnlen(const char *, size_t); -int tinystrlen16(const char16_t *); -int tinystrnlen16(const char16_t *, size_t); -int tinywcslen(const wchar_t *); -int tinywcsnlen(const wchar_t *, size_t); - -#else - -forceinline int tinystrlen(const char *s) { - unsigned ax; - asm("call\ttinystrlen" : "=a"(ax) : "D"(s), "m"(*(char(*)[PAGESIZE])s)); - return ax; -} - -forceinline int tinystrnlen(const char *s, size_t n) { - unsigned ax; - asm("call\ttinystrnlen" : "=a"(ax) : "D"(s), "S"(n), "m"(*(char(*)[n])s)); - return ax; -} - -forceinline int tinystrlen16(const char16_t *s) { - unsigned ax; - asm("call\ttinystrlen16" : "=a"(ax) : "D"(s), "m"(*(char16_t(*)[PAGESIZE])s)); - return ax; -} - -forceinline int tinystrnlen16(const char16_t *s, size_t n) { - unsigned ax; - asm("call\ttinystrnlen16" - : "=a"(ax) - : "D"(s), "S"(n), "m"(*(char16_t(*)[n])s)); - return ax; -} - -forceinline int tinywcslen(const wchar_t *s) { - unsigned ax; - asm("call\ttinywcslen" : "=a"(ax) : "D"(s), "m"(*(wchar_t(*)[PAGESIZE])s)); - return ax; -} - -forceinline int tinywcsnlen(const wchar_t *s, size_t n) { - unsigned ax; - asm("call\ttinywcsnlen" : "=a"(ax) : "D"(s), "S"(n), "m"(*(wchar_t(*)[n])s)); - return ax; -} - -#endif -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_ */ diff --git a/libc/nexgen32e/tinystrnlen.greg.S b/libc/nexgen32e/tinystrnlen.greg.S deleted file mode 100644 index 194074291..000000000 --- a/libc/nexgen32e/tinystrnlen.greg.S +++ /dev/null @@ -1,39 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.internal.h" - -// 8-bit strnlen that's tiny and near optimal if data's tiny. -// -// @param RDI is char *s -// @param RSI is size_t n -// @param EAX is unsigned length -// @see libc/nexgen32e/strsak.S -tinystrnlen: - .leafprologue - .profilable - xor %eax,%eax -1: cmp %esi,%eax - jae 2f - cmpb $0,(%rdi,%rax) - jz 2f - inc %eax - jmp 1b -2: .leafepilogue - .endfn tinystrnlen,globl - .source __FILE__ diff --git a/libc/runtime/arememoryintervalsok.c b/libc/runtime/arememoryintervalsok.c index 67e787643..8c20eb623 100644 --- a/libc/runtime/arememoryintervalsok.c +++ b/libc/runtime/arememoryintervalsok.c @@ -16,6 +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/runtime/memtrack.internal.h" noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) { @@ -23,6 +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!"); return false; } if (i) { @@ -32,6 +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!"); return false; } } diff --git a/libc/runtime/assertfail.c b/libc/runtime/assertfail.c index 97dac38be..ab06ff276 100644 --- a/libc/runtime/assertfail.c +++ b/libc/runtime/assertfail.c @@ -21,6 +21,7 @@ #include "libc/bits/weaken.h" #include "libc/log/libfatal.internal.h" #include "libc/log/log.h" +#include "libc/runtime/runtime.h" /** * Handles failure of assert() macro. @@ -28,14 +29,14 @@ relegated wontreturn void __assert_fail(const char *expr, const char *file, int line) { static bool noreentry; - __printf("\r\n%s:%d: assert(%s) failed\r\n", file, line, expr); + __printf("%s:%d: assert(%s) failed\r\n", file, line, expr); if (cmpxchg(&noreentry, false, true)) { if (weaken(__die)) { weaken(__die)(); } else { __printf("can't backtrace b/c `__die` not linked\r\n"); } - exit(23); + quick_exit(23); } - _exit(24); + _Exit(24); } diff --git a/libc/runtime/describeframe.c b/libc/runtime/describeframe.c index 0ef3f63f8..6d1f04e09 100644 --- a/libc/runtime/describeframe.c +++ b/libc/runtime/describeframe.c @@ -41,7 +41,7 @@ noasan const char *DescribeFrame(int x) { return " fixed "; } else if (IsArenaFrame(x)) { return " arena "; - } else if (IsStackFrame(x)) { + } else if (IsStaticStackFrame(x)) { return " stack "; } else { return ""; diff --git a/libc/runtime/directmap-nt.c b/libc/runtime/directmap-nt.c index 00cc2a85c..e50ce99d6 100644 --- a/libc/runtime/directmap-nt.c +++ b/libc/runtime/directmap-nt.c @@ -91,7 +91,7 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size, SYSDEBUG( "MapViewOfFileExNuma(prot:%s, off:0x%x, size:0x%x, addr:0x%x) -> " "addr:0x%x", - (prot & PROT_WRITE) ? "WX" : "RX", off, size, addr); + (prot & PROT_WRITE) ? "WX" : "RX", off, size, addr, dm.addr); if (dm.addr) { return dm; } else { diff --git a/libc/runtime/finddebugbinary.c b/libc/runtime/finddebugbinary.c index e587088b2..98ab23545 100644 --- a/libc/runtime/finddebugbinary.c +++ b/libc/runtime/finddebugbinary.c @@ -19,6 +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/errno.h" #include "libc/macros.internal.h" #include "libc/runtime/runtime.h" diff --git a/libc/runtime/getdosenviron.c b/libc/runtime/getdosenviron.c index 424d78383..f1a4117d9 100644 --- a/libc/runtime/getdosenviron.c +++ b/libc/runtime/getdosenviron.c @@ -21,19 +21,29 @@ #include "libc/str/tpenc.h" #include "libc/str/utf16.h" +#define ToUpper(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c)) + static textwindows noasan noinstrument axdx_t Recode16to8(char *dst, size_t dstsize, const char16_t *src) { + bool v; axdx_t r; uint64_t w; wint_t x, y; - for (r.ax = 0, r.dx = 0;;) { + for (v = r.ax = 0, r.dx = 0;;) { if (!(x = src[r.dx++])) break; if (IsUtf16Cont(x)) continue; if (!IsUcs2(x)) { y = src[r.dx++]; x = MergeUtf16(x, y); } + if (!v) { + if (x == '=') { + v = true; + } else { + x = ToUpper(x); + } + } w = tpenc(x); do { if (r.ax + 1 >= dstsize) break; diff --git a/libc/runtime/memtrack.c b/libc/runtime/memtrack.c index 5fbe3f251..127bef8a7 100644 --- a/libc/runtime/memtrack.c +++ b/libc/runtime/memtrack.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" #include "libc/bits/bits.h" +#include "libc/bits/likely.h" #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/sysdebug.internal.h" @@ -61,71 +62,52 @@ static noasan void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i, mm->i -= n; } -static noasan void MapNewMappingArray(struct MemoryIntervals *mm) { - /* asan runtime depends on this function */ - void *a; - int i, x, y, g; - size_t n, m, f; +static noasan bool ExtendMemoryIntervals(struct MemoryIntervals *mm) { int prot, flags; + char *base, *shad; + size_t gran, size; struct DirectMap dm; - struct MemoryInterval *p, *q; - assert(mm->i); - assert(AreMemoryIntervalsOk(mm)); - n = mm->n; - n = n * sizeof(*mm->p); - n = ROUNDUP(n, FRAMESIZE); + gran = kMemtrackGran; + base = (char *)kMemtrackStart; + prot = PROT_READ | PROT_WRITE; + flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED; if (mm->p == mm->s) { - m = n; - q = 0; - } else { - q = mm->p; - m = n + (n >> 1); - m = ROUNDUP(m, FRAMESIZE); - } - /* - * find a hole in the automap range - * we pad the sides for easier insertion logic - * only time this fails is MODE=tiny which makes no stack - */ - i = 0; - f = m >> 16; - for (;;) { - if (++i == mm->i || mm->p[i].x - mm->p[i - 1].y >= 1 + f + 1) { - x = mm->p[i - 1].y + 1; - y = x + f - 1; - a = (void *)((intptr_t)((uint64_t)x << 32) >> 16); - if (i == mm->i || (kAutomapStart <= (intptr_t)a && - (intptr_t)a + m < kAutomapStart + kAutomapSize)) { - break; + if (IsAsan()) { + shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000); + dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0); + if (!dm.addr) { + SYSDEBUG("ExtendMemoryIntervals() fail #1"); + return false; } } - } - flags = MAP_ANONYMOUS | MAP_PRIVATE; - prot = PROT_READ | PROT_WRITE; - SYSDEBUG("MapNewMappingArray(0x%x, 0x%x) %d/%d/%d", a, m, i, mm->i, mm->n); - dm = sys_mmap(a, m, prot, flags | MAP_FIXED, -1, 0); - if ((p = dm.addr) != MAP_FAILED) { - MoveMemoryIntervals(p, mm->p, i); - MoveMemoryIntervals(p + i + 1, mm->p + i, mm->i - i); - mm->i += 1; - mm->n = m / sizeof(*mm->p); - mm->p = p; - mm->p[i].x = x; - mm->p[i].y = y; - mm->p[i].h = dm.maphandle; - mm->p[i].prot = prot; - mm->p[i].flags = flags; - if (q) { - munmap(q, n); + dm = sys_mmap(base, gran, prot, flags, -1, 0); + if (!dm.addr) { + SYSDEBUG("ExtendMemoryIntervals() fail #2"); + return false; } - if (IsAsan()) { - __asan_map_shadow((uintptr_t)a, m); - } - SYSDEBUG("MapNewMappingArray() succeeded"); + MoveMemoryIntervals(dm.addr, mm->p, mm->i); + mm->p = dm.addr; + mm->n = gran / sizeof(*mm->p); } else { - SYSDEBUG("MapNewMappingArray() failed: %s", strerror(errno)); + size = ROUNDUP(mm->n * sizeof(*mm->p), gran); + base += size; + if (IsAsan()) { + shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000); + dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0); + if (!dm.addr) { + SYSDEBUG("ExtendMemoryIntervals() fail #3"); + return false; + } + } + dm = sys_mmap(base, gran, prot, flags, -1, 0); + if (!dm.addr) { + SYSDEBUG("ExtendMemoryIntervals() fail #4"); + return false; + } + mm->n = (size + gran) / sizeof(*mm->p); } assert(AreMemoryIntervalsOk(mm)); + return true; } noasan int CreateMemoryInterval(struct MemoryIntervals *mm, int i) { @@ -135,16 +117,12 @@ noasan int CreateMemoryInterval(struct MemoryIntervals *mm, int i) { assert(i >= 0); assert(i <= mm->i); assert(mm->n >= 0); - if (mm->i == mm->n) { - SYSDEBUG("CreateMemoryInterval() failed"); - return enomem(); - } + if (UNLIKELY(mm->i == mm->n) && !ExtendMemoryIntervals(mm)) return enomem(); MoveMemoryIntervals(mm->p + i + 1, mm->p + i, mm->i++ - i); return 0; } static noasan int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) { - if (mm->i == mm->n) return enomem(); if (CreateMemoryInterval(mm, i) == -1) return -1; mm->p[i].y = x - 1; mm->p[i + 1].x = y + 1; @@ -210,16 +188,12 @@ noasan int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h, prot == mm->p[i].prot && flags == mm->p[i].flags) { mm->p[i].x = x; } else { - if (mm->i == mm->n) return enomem(); if (CreateMemoryInterval(mm, i) == -1) return -1; mm->p[i].x = x; mm->p[i].y = y; mm->p[i].h = h; mm->p[i].prot = prot; mm->p[i].flags = flags; - if (mm->i >= mm->n / 2) { - MapNewMappingArray(mm); - } } return 0; } diff --git a/libc/runtime/memtrack.internal.h b/libc/runtime/memtrack.internal.h index 1a5608ccb..ae844bda0 100644 --- a/libc/runtime/memtrack.internal.h +++ b/libc/runtime/memtrack.internal.h @@ -5,24 +5,26 @@ #include "libc/nt/enum/version.h" #include "libc/runtime/runtime.h" #include "libc/runtime/stack.h" +#include "libc/sysv/consts/ss.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -#define _kAutomapStart 0x0000100080000000 -#define _kAutomapSize 0x00000fff80000000 -#define _kFixedmapStart 0x0000300000000000 -#define _kFixedmapSize 0x00000fff80000000 - -/* - * TODO: Why can't we allocate addresses above 4GB on Windows 7 x64? - * https://github.com/jart/cosmopolitan/issues/19 - */ -#define MEMTRACK_ADDRESS(NORMAL, WIN7) \ +#define kAutomapStart _kMem(0x100080000000, 0x000010000000) +#define kAutomapSize \ + _kMem(0x200000000000 - 0x100080000000 - _kMmi(0x800000000000), \ + 0x000040000000 - 0x000010000000 - _kMmi(0x000080000000)) +#define kMemtrackStart \ + _kMem(0x200000000000 - _kMmi(0x800000000000), \ + 0x000040000000 - _kMmi(0x000080000000)) +#define kMemtrackSize _kMem(_kMmi(0x800000000000), _kMmi(0x000080000000)) +#define kMemtrackGran (!IsAsan() ? FRAMESIZE : FRAMESIZE * 8) +#define kFixedmapStart _kMem(0x300000000000, 0x000040000000) +#define kFixedmapSize \ + _kMem(0x400000000000 - 0x300000000000, 0x000070000000 - 0x000040000000) +#define _kMmi(VSPACE) \ + ROUNDUP(VSPACE / FRAMESIZE * sizeof(struct MemoryInterval), FRAMESIZE) +#define _kMem(NORMAL, WIN7) \ (!(IsWindows() && NtGetVersion() < kNtVersionWindows10) ? NORMAL : WIN7) -#define kAutomapStart MEMTRACK_ADDRESS(_kAutomapStart, 0x10000000) -#define kAutomapSize MEMTRACK_ADDRESS(_kAutomapSize, 0x30000000) -#define kFixedmapStart MEMTRACK_ADDRESS(_kFixedmapStart, 0x40000000) -#define kFixedmapSize MEMTRACK_ADDRESS(_kFixedmapSize, 0x30000000) struct MemoryInterval { int x; @@ -52,11 +54,19 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int, void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden; int UntrackMemoryIntervals(void *, size_t) hidden; +#define IsLegalPointer(p) \ + (-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff) + forceinline pureconst bool IsAutoFrame(int x) { return (kAutomapStart >> 16) <= x && x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16); } +forceinline pureconst bool IsMemtrackFrame(int x) { + return (kAutomapStart >> 16) <= x && + x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16); +} + forceinline pureconst bool IsArenaFrame(int x) { return 0x5000 <= x && x < 0x7ffe; } @@ -65,11 +75,21 @@ forceinline pureconst bool IsShadowFrame(int x) { return 0x7fff <= x && x < 0x10008000; } -forceinline pureconst bool IsStackFrame(int x) { +forceinline pureconst bool IsStaticStackFrame(int x) { return (GetStaticStackAddr(0) >> 16) <= x && x <= ((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >> 16); } +forceinline pureconst bool IsSigAltStackFrame(int x) { + return (GetStackAddr(0) >> 16) <= x && + x <= ((GetStackAddr(0) + (SIGSTKSZ - FRAMESIZE)) >> 16); +} + +forceinline pureconst bool IsOldStackFrame(int x) { + intptr_t old = ROUNDDOWN(__oldstack, STACKSIZE); + return (old >> 16) <= x && x <= ((old + (STACKSIZE - FRAMESIZE)) >> 16); +} + forceinline pureconst bool IsFixedFrame(int x) { return (kFixedmapStart >> 16) <= x && x <= ((kFixedmapStart + (kFixedmapSize - 1)) >> 16); diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index 0a850755e..6da054cf2 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -23,8 +23,10 @@ #include "libc/calls/internal.h" #include "libc/calls/sysdebug.internal.h" #include "libc/dce.h" +#include "libc/errno.h" #include "libc/intrin/asan.internal.h" #include "libc/log/backtrace.internal.h" +#include "libc/log/libfatal.internal.h" #include "libc/log/log.h" #include "libc/macros.internal.h" #include "libc/rand/rand.h" @@ -40,7 +42,6 @@ #define VIP(X) (void *)IP(X) #define SMALL(n) ((n) <= 0xffffffffffff) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) -#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff) #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)) @@ -104,6 +105,87 @@ noasan static bool Automap(int n, int *res) { } } +static noasan void *MapMemory(void *addr, size_t size, int prot, int flags, + int fd, int64_t off, int f, int x, int n) { + struct DirectMap dm; + 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"); + assert(!"MapMemory() failed"); + Die(); + } + return MAP_FAILED; + } + if (UNLIKELY(dm.addr != addr)) { + SYSDEBUG("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)); + 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)); + assert(!"MapMemory() failed"); + Die(); + } + return MAP_FAILED; + } + if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(addr, size)) { + weaken(__asan_map_shadow)((intptr_t)addr, size); + } + return addr; +} + +/** + * Maps memory from system, one frame at a time. + * + * This is useful on Windows since it allows us to partially unmap or + * punch holes into existing mappings. + */ +static textwindows noinline noasan void *MapMemories(char *addr, size_t size, + 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)); + 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)); + assert(!"MapMemories() failed"); + Die(); + } + for (i = 0; i < m; i += FRAMESIZE) { + dm = sys_mmap(addr + i, FRAMESIZE, prot, f, fd, fd == -1 ? 0 : off + i); + 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)); + assert(!"MapMemories() failed"); + Die(); + } + } + if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(addr, size)) { + weaken(__asan_map_shadow)((intptr_t)addr, size); + } + return addr; +} + /** * Beseeches system for page-table entries, e.g. * @@ -146,7 +228,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd, SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (size isn't 48-bit)", p, size); return VIP(einval()); } - if (UNLIKELY(!LEGAL(p))) { + if (UNLIKELY(!IsLegalPointer(p))) { SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, size); return VIP(einval()); } @@ -202,6 +284,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd, if (IsWindows()) { if (UntrackMemoryIntervals(p, size)) { SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno)); + assert(!"mmap() failed"); Die(); } } @@ -215,34 +298,9 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd, dm = sys_mmap(p, size, prot, f & ~MAP_GROWSDOWN, fd, off); if (dm.addr == MAP_FAILED) return MAP_FAILED; } - dm = sys_mmap(p, size, prot, f, fd, off); - if (UNLIKELY(dm.addr == MAP_FAILED)) { - if (IsWindows() && (flags & MAP_FIXED)) { - SYSDEBUG("mmap(0x%p, 0x%x) -> %s (%s)", p, size, strerror(errno), - "can't recover from MAP_FIXED errors on Windows"); - Die(); - } - return MAP_FAILED; + if (!IsWindows()) { + return MapMemory(p, size, prot, flags, fd, off, f, x, n); + } else { + return MapMemories(p, size, prot, flags, fd, off, f, x, n); } - if (UNLIKELY(dm.addr != p)) { - SYSDEBUG("KERNEL DIDN'T RESPECT MAP_FIXED"); - Die(); - } - if (!IsWindows() && (flags & MAP_FIXED)) { - if (UntrackMemoryIntervals(p, size)) { - SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno)); - Die(); - } - } - if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) { - if (sys_munmap(p, n) == -1) { - SYSDEBUG("TRACK MUNMAP FAILED %s", strerror(errno)); - Die(); - } - return MAP_FAILED; - } - if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(p, size)) { - weaken(__asan_map_shadow)((intptr_t)p, size); - } - return p; } diff --git a/libc/runtime/mremap.c b/libc/runtime/mremap.c index c3fc40da2..dc9b8ead1 100644 --- a/libc/runtime/mremap.c +++ b/libc/runtime/mremap.c @@ -38,7 +38,6 @@ #define VIP(X) (void *)IP(X) #define SMALL(n) ((n) <= 0xffffffffffff) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) -#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff) #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)) diff --git a/libc/runtime/munmap.c b/libc/runtime/munmap.c index 2e0e4326e..45098727e 100644 --- a/libc/runtime/munmap.c +++ b/libc/runtime/munmap.c @@ -20,6 +20,7 @@ #include "libc/calls/internal.h" #include "libc/calls/sysdebug.internal.h" #include "libc/dce.h" +#include "libc/errno.h" #include "libc/intrin/asan.internal.h" #include "libc/log/libfatal.internal.h" #include "libc/macros.internal.h" @@ -32,7 +33,6 @@ #define IP(X) (intptr_t)(X) #define SMALL(n) ((n) <= 0xffffffffffff) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) -#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff) #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)) @@ -64,11 +64,11 @@ noasan int munmap(void *v, size_t n) { SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (n isn't 48-bit)", p, n); return einval(); } - if (UNLIKELY(!LEGAL(p))) { + if (UNLIKELY(!IsLegalPointer(p))) { SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, n); return einval(); } - if (UNLIKELY(!LEGAL(p + (n - 1)))) { + if (UNLIKELY(!IsLegalPointer(p + (n - 1)))) { SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p+(n-1) isn't 48-bit)", p, n); return einval(); } @@ -80,7 +80,6 @@ noasan int munmap(void *v, size_t n) { SYSDEBUG("munmap(0x%p, 0x%x) EFAULT (interval not tracked)", p, n); return efault(); } - SYSDEBUG("munmap(0x%p, 0x%x)", p, n); if (UntrackMemoryIntervals(p, n) != -1) { if (!IsWindows()) { rc = sys_munmap(p, n); @@ -105,11 +104,13 @@ noasan int munmap(void *v, size_t n) { } } } - return rc; } else { - return 0; /* UntrackMemoryIntervals does it for NT */ + rc = 0; /* UntrackMemoryIntervals does it for NT */ } } else { - return -1; + rc = -1; } + SYSDEBUG("munmap(0x%p, 0x%x) -> %d %s", p, n, (long)rc, + rc == -1 ? strerror(errno) : ""); + return rc; } diff --git a/libc/runtime/peekall.S b/libc/runtime/peekall.S index 85510fd1f..fedc62666 100644 --- a/libc/runtime/peekall.S +++ b/libc/runtime/peekall.S @@ -23,9 +23,17 @@ _peekall: .leafprologue ezlea _base,si + ezlea _etext,cx + add $0x1000,%rsi +0: xor (%rsi),%eax + add $PAGESIZE,%rsi + cmp %rcx,%rsi + jb 0b + ezlea _etext,si ezlea _end,cx add $0x1000,%rsi -0: mov (%rsi),%eax +0: incq (%rsi) + decq (%rsi) add $PAGESIZE,%rsi cmp %rcx,%rsi jb 0b diff --git a/libc/runtime/print.greg.c b/libc/runtime/print.greg.c deleted file mode 100644 index ef84b92be..000000000 --- a/libc/runtime/print.greg.c +++ /dev/null @@ -1,76 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#define ShouldUseMsabiAttribute() 1 -#include "libc/dce.h" -#include "libc/nt/files.h" -#include "libc/nt/runtime.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/fileno.h" -#include "libc/sysv/consts/nr.h" - -/* TODO(jart): DELETE */ - -#define WasImported(SLOT) \ - ((void *)*SLOT && *SLOT != (void *)&missingno /* see libc/crt/crt.S */) - -static void __sys_print_nt(const void *data, size_t len) { - int64_t hand; - char xmm[256]; - uint32_t wrote; - _savexmm(xmm + 128); - hand = __imp_GetStdHandle(kNtStdErrorHandle); - __imp_WriteFile(hand, data, len, &wrote, NULL); - _loadxmm(xmm + 128); -} - -/** - * Prints string, by any means necessary. - * - * This function offers a subset of write(STDERR_FILENO) functionality. - * It's designed to work even when the runtime hasn't initialized, e.g. - * before _init() gets called. - * - * @param len can be computed w/ tinystrlen() - * @clob nothing except flags - */ -privileged noinline void __print(const void *data, size_t len) { - int64_t ax, ordinal; - if (WasImported(__imp_WriteFile)) { - __sys_print_nt(data, len); - } else { - ordinal = __NR_write > 0 ? __NR_write : IsXnu() ? 0x2000004 : 4; - asm volatile("syscall" - : "=a"(ax) - : "0"(ordinal), "D"(STDERR_FILENO), "S"(data), "d"(len) - : "rcx", "r11", "memory", "cc"); - if (ax == -1 && !__hostos && !__NR_write) { - asm volatile("syscall" - : "=a"(ax) - : "0"(ordinal), "D"(STDERR_FILENO), "S"(data), "d"(len) - : "rcx", "r11", "memory", "cc"); - } - } -} - -void __print_string(const char *s) { - size_t n = 0; - while (s[n]) ++n; - __print(s, n); -} diff --git a/libc/runtime/printmemoryintervals.c b/libc/runtime/printmemoryintervals.c index 7d419900e..3569334b9 100644 --- a/libc/runtime/printmemoryintervals.c +++ b/libc/runtime/printmemoryintervals.c @@ -26,9 +26,10 @@ static bool IsNoteworthyHole(unsigned i, const struct MemoryIntervals *mm) { // gaps between shadow frames aren't interesting // the chasm from heap to stack ruins statistics - return !((IsArenaFrame(mm->p[i].y) && !IsArenaFrame(mm->p[i + 1].x)) || - (IsShadowFrame(mm->p[i].y) || IsShadowFrame(mm->p[i + 1].x)) || - (!IsStackFrame(mm->p[i].y) && IsStackFrame(mm->p[i + 1].x))); + return !( + (IsArenaFrame(mm->p[i].y) && !IsArenaFrame(mm->p[i + 1].x)) || + (IsShadowFrame(mm->p[i].y) || IsShadowFrame(mm->p[i + 1].x)) || + (!IsStaticStackFrame(mm->p[i].y) && IsStaticStackFrame(mm->p[i + 1].x))); } void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) { @@ -40,8 +41,7 @@ void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) { for (i = 0; i < mm->i; ++i) { frames = mm->p[i].y + 1 - mm->p[i].x; maptally += frames; - __printf("%0*x-%0*x %s %,*dx%s", 12, ADDR(mm->p[i].x), 12, - ADDR(mm->p[i].y + 1), + __printf("%012x-%012x %s %,*dx%s", ADDR(mm->p[i].x), ADDR(mm->p[i].y + 1), DescribeMapping(mm->p[i].prot, mm->p[i].flags, mode), w, frames, DescribeFrame(mm->p[i].x)); if (i + 1 < _mmi.i) { diff --git a/libc/runtime/program_executable_name.c b/libc/runtime/program_executable_name.c index 1dbd1cfed..eeea10d6a 100644 --- a/libc/runtime/program_executable_name.c +++ b/libc/runtime/program_executable_name.c @@ -33,6 +33,7 @@ #include "libc/sysv/consts/at.h" #include "libc/sysv/consts/auxv.h" #include "libc/sysv/consts/ok.h" +#include "libc/sysv/consts/prot.h" #define SIZE 1024 #define CTL_KERN 1 diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 0bc82514d..c46add19e 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -13,6 +13,7 @@ extern const int __argc; /* CRT */ extern char **const __argv; /* CRT */ extern char **const __envp; /* CRT */ extern unsigned long *const __auxv; /* CRT */ +extern intptr_t __oldstack; /* CRT */ extern char program_executable_name[]; /* RII */ extern char *program_invocation_name; /* RII */ extern char *program_invocation_short_name; /* RII */ @@ -86,8 +87,6 @@ bool _isheap(void *); int NtGetVersion(void) pureconst; long missingno(); void __oom_hook(size_t); -void __print(const void *, size_t); -void __print_string(const char *); void _loadxmm(void *); void _peekall(void); void _savexmm(void *); diff --git a/libc/runtime/stack.h b/libc/runtime/stack.h index 4384e49ab..a5d580fcf 100644 --- a/libc/runtime/stack.h +++ b/libc/runtime/stack.h @@ -2,6 +2,7 @@ #define COSMOPOLITAN_LIBC_RUNTIME_STACK_H_ #include "ape/config.h" #include "libc/dce.h" +#include "libc/runtime/runtime.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) /** @@ -63,14 +64,18 @@ extern char ape_stack_memsz[] __attribute__((__weak__)); /** * Returns preferred bottom address of stack. */ -#define GetStaticStackAddr(ADDEND) \ - ({ \ - intptr_t vAddr = 0; \ - asm(".weak\tape_stack_vaddr\n\t" \ - "movabs\t%1+ape_stack_vaddr,%0" \ - : "=r"(vAddr) \ - : "i"(ADDEND)); \ - vAddr; \ +#define GetStaticStackAddr(ADDEND) \ + ({ \ + intptr_t vAddr; \ + if (!IsWindows() || NtGetVersion() >= kNtVersionWindows10) { \ + asm(".weak\tape_stack_vaddr\n\t" \ + "movabs\t%1+ape_stack_vaddr,%0" \ + : "=r"(vAddr) \ + : "i"(ADDEND)); \ + } else { \ + vAddr = 0x10000000; \ + } \ + vAddr; \ }) COSMOPOLITAN_C_END_ diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index c737a2484..8f0498b4c 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -98,6 +98,7 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) { extern char os asm("__hostos"); os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */ version = NtGetPeb()->OSMajorVersion; + __oldstack = (intptr_t)__builtin_frame_address(0); if ((intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui && version >= 10) { SetConsoleCP(kNtCpUtf8); SetConsoleOutputCP(kNtCpUtf8); @@ -114,9 +115,9 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) { kNtEnableVirtualTerminalProcessing); } _mmi.p = _mmi.s; - _mmi.n = OPEN_MAX; + _mmi.n = ARRAYLEN(_mmi.s); argsize = ROUNDUP(sizeof(struct WinArgs), FRAMESIZE); - stackaddr = version < 10 ? 0x10000000 : GetStaticStackAddr(0); + stackaddr = GetStaticStackAddr(0); stacksize = GetStackSize(); allocsize = argsize + stacksize; allocaddr = stackaddr - argsize; diff --git a/libc/nexgen32e/tinystrncmp.ncabi.S b/libc/str/findembeddedape.c similarity index 59% rename from libc/nexgen32e/tinystrncmp.ncabi.S rename to libc/str/findembeddedape.c index 4f1963167..68b3696cf 100644 --- a/libc/nexgen32e/tinystrncmp.ncabi.S +++ b/libc/str/findembeddedape.c @@ -1,7 +1,7 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,40 +16,35 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" +#include "libc/log/libfatal.internal.h" #include "libc/macros.internal.h" +#include "libc/str/str.h" -// Compares strings w/ limit & no-clobber greg abi. -// -// @param %rdi is first string -// @param %rsi is second string -// @param %rdx is max length -// @return <0, 0, or >0 depending on comparison -// @clob flags only -// @asyncsignalsafe -tinystrncmp: - .leafprologue - push %rbx - push %rcx - xor %eax,%eax - xor %ebx,%ebx - xor %ecx,%ecx - test %edx,%edx - jz 2f - cmp %rdi,%rsi - je 2f -0: cmp %edx,%ecx - jae 1f - movzbl (%rdi,%rcx,1),%eax - movzbl (%rsi,%rcx,1),%ebx - test %al,%al - jz 1f - cmp %bl,%al - jne 1f - inc %ecx - jmp 0b -1: sub %ebx,%eax -2: pop %rcx - pop %rbx - .leafepilogue - .endfn tinystrncmp,globl - .source __FILE__ +#define TRIES 8 + +/** + * Returns offset of binary embedded inside binary. + * + * This can be used to load zip assets from an executable that hasn't + * gone through the `objcopy -S -O binary` step. We make the assumption + * that an x86_64-pc-linux-gnu toolchain is being used. This routine + * would need to be changed to accommodate binaries built locally on + * Apple, FreeBSD, etc. + * + * @param p needs to be page aligned + * @param n is byte length of p + * @return base address of image or NULL if not found + */ +uint8_t *FindEmbeddedApe(const uint8_t *p, size_t n) { + size_t i; + uint64_t w; + n = MIN(n, TRIES * PAGESIZE); + for (i = 0; i + 8 <= n; i += PAGESIZE) { + w = READ64LE(p + i); + if (w == READ64LE("MZqFpD='") || w == READ64LE("\177ELF\2\1\1\11")) { + return (/*unconst*/ uint8_t *)(p + i); + } + } + return 0; +} diff --git a/libc/str/oldutf16.internal.h b/libc/str/oldutf16.internal.h index 8f0224fc2..3d59dc475 100644 --- a/libc/str/oldutf16.internal.h +++ b/libc/str/oldutf16.internal.h @@ -6,6 +6,8 @@ COSMOPOLITAN_C_START_ unsigned getutf16(const char16_t *, wint_t *); int pututf16(char16_t *, size_t, wint_t, bool); +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) + #define pututf16(BUF, SIZE, CH, AWESOME) __pututf16(BUF, SIZE, CH, AWESOME) #define getutf16(BUF, CHPTR) __getutf16(BUF, CHPTR) @@ -42,6 +44,8 @@ forceinline unsigned __getutf16(const char16_t *s, wint_t *wc) { return ax; } +#endif + COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_STR_OLDUTF16_H_ */ diff --git a/libc/log/startfatal_ndebug.c b/libc/str/strlen16.c similarity index 68% rename from libc/log/startfatal_ndebug.c rename to libc/str/strlen16.c index 1b96882cf..6fbd24c89 100644 --- a/libc/log/startfatal_ndebug.c +++ b/libc/str/strlen16.c @@ -1,7 +1,7 @@ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,29 +16,28 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" -#include "libc/log/color.internal.h" -#include "libc/log/internal.h" -#include "libc/stdio/stdio.h" +#include "libc/dce.h" +#include "libc/intrin/asan.internal.h" +#include "libc/str/str.h" -asm(".section .privileged,\"ax\",@progbits\n__syscall:\n\t" - "syscall\n\t" - "ret\n\t" - ".previous"); +typedef char16_t xmm_t __attribute__((__vector_size__(16), __aligned__(16))); /** - * Prints initial part of fatal message. + * Returns length of NUL-terminated utf-16 string. * - * @note this is support code for __check_fail(), __assert_fail(), etc. - * @see __start_fatal() + * @param s is non-null NUL-terminated string pointer + * @return number of shorts (excluding NUL) + * @asyncsignalsafe */ -relegated void __start_fatal_ndebug(void) { - char s[16 + 16 + 16 + 16 + PATH_MAX + 16], *p = s; - __restore_tty(1); - *p++ = '\r'; - if (cancolor()) p = stpcpy(p, "\e[J"); - p = stpcpy(p, "error:"); - p = stpcpy(p, program_invocation_name); - p = stpcpy(p, ": "); - write(2, s, p - s); +noasan size_t strlen16(const char16_t *s) { + size_t n; + xmm_t v, z = {0}; + unsigned m, k = (uintptr_t)s & 15; + const xmm_t *p = (const xmm_t *)((uintptr_t)s & -16); + if (IsAsan()) __asan_verify(s, 2); + m = __builtin_ia32_pmovmskb128(*p == z) >> k << k; + while (!m) m = __builtin_ia32_pmovmskb128(*++p == z); + n = (const char16_t *)p + (__builtin_ctzl(m) >> 1) - s; + if (IsAsan()) __asan_verify(s, n * 2); + return n; } diff --git a/libc/nexgen32e/tinystrnlen16.greg.S b/libc/str/strnlen16.c similarity index 72% rename from libc/nexgen32e/tinystrnlen16.greg.S rename to libc/str/strnlen16.c index 86e331817..1a1429ee6 100644 --- a/libc/nexgen32e/tinystrnlen16.greg.S +++ b/libc/str/strnlen16.c @@ -1,7 +1,7 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,24 +16,22 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.internal.h" +#include "libc/assert.h" +#include "libc/str/str.h" -// 16-bit strnlen that's tiny and near optimal if data's tiny. -// -// @param RDI is char16_t *s -// @param RSI is size_t n -// @param EAX is unsigned length -// @see libc/nexgen32e/strsak16.S -tinystrnlen16: - .leafprologue - .profilable - xor %eax,%eax -1: cmp %esi,%eax - jae 2f - cmpw $0,(%rdi,%rax,2) - jz 2f - inc %eax - jmp 1b -2: .leafepilogue - .endfn tinystrnlen16,globl - .source __FILE__ +/** + * Returns length of NUL-terminated 16-bit string w/ limit. + * + * @param s is utf16 string pointer + * @param n is max length in shorts + * @return number of shorts + * @asyncsignalsafe + */ +noasan size_t strnlen16(const char16_t *s, size_t n) { + size_t i; + for (i = 0;; ++i) { + if (i == n || !s[i]) break; + } + assert(i == n || (i < n && !s[i])); + return i; +} diff --git a/libc/str/tpdecode.internal.h b/libc/str/tpdecode.internal.h index 549a496c2..e9d078c2d 100644 --- a/libc/str/tpdecode.internal.h +++ b/libc/str/tpdecode.internal.h @@ -5,7 +5,7 @@ COSMOPOLITAN_C_START_ int tpdecode(const char *, wint_t *) paramsnonnull((1)) libcesque; -#ifndef __STRICT_ANSI__ +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) #define tpdecode(S, OUT) __tpdecode(S, OUT) forceinline int __tpdecode(const char *s, wint_t *out) { int ax; diff --git a/libc/str/tpenc.h b/libc/str/tpenc.h index ce9c0d55d..b693615fa 100644 --- a/libc/str/tpenc.h +++ b/libc/str/tpenc.h @@ -5,7 +5,7 @@ COSMOPOLITAN_C_START_ uint64_t tpenc(int32_t) pureconst; -#ifndef __STRICT_ANSI__ +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) #define tpenc(CODE) \ ({ \ long Edi, Buf; \ diff --git a/libc/sysv/errfuns.h b/libc/sysv/errfuns.h index 6b2ad156a..5a0fc56e9 100644 --- a/libc/sysv/errfuns.h +++ b/libc/sysv/errfuns.h @@ -153,7 +153,7 @@ intptr_t enotrecoverable(void) relegated; intptr_t erfkill(void) relegated; intptr_t ehwpoison(void) relegated; -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) #define __ERRFUN(FUNC) \ ({ \ intptr_t NegOne; \ diff --git a/libc/sysv/syscall.S b/libc/sysv/syscall.S index f1136edbb..275a656da 100644 --- a/libc/sysv/syscall.S +++ b/libc/sysv/syscall.S @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" -.source __FILE__ +.privileged // Performs raw System Five system call. // diff --git a/libc/testlib/benchrunner.c b/libc/testlib/benchrunner.c index d669f1ceb..f5051aba2 100644 --- a/libc/testlib/benchrunner.c +++ b/libc/testlib/benchrunner.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/kntprioritycombos.internal.h" +#include "libc/errno.h" #include "libc/log/log.h" #include "libc/nexgen32e/x86feature.h" #include "libc/runtime/runtime.h" @@ -51,9 +52,12 @@ void testlib_benchwarmup(void) { * @see BENCH() */ void testlib_runallbenchmarks(void) { + int e; + e = errno; _peekall(); mlockall(MCL_CURRENT); nice(-1); + errno = e; __log_level = kLogWarn; testlib_runtestcases(__bench_start, __bench_end, testlib_benchwarmup); } diff --git a/libc/testlib/leaks.c b/libc/testlib/leaks.c index 857e689f7..78f51b2ed 100644 --- a/libc/testlib/leaks.c +++ b/libc/testlib/leaks.c @@ -71,7 +71,7 @@ noasan void testlib_checkformemoryleaks(void) { struct mallinfo mi; if (!cmpxchg(&once, false, true)) { __printf("testlib_checkformemoryleaks() may only be called once\n"); - _Exit(1); + exit(1); } __cxa_finalize(0); if (!IsAsan()) { diff --git a/libc/testlib/quota.c b/libc/testlib/quota.c index 810528616..a9ff4bcbe 100644 --- a/libc/testlib/quota.c +++ b/libc/testlib/quota.c @@ -47,7 +47,7 @@ static relegated void DieBecauseOfQuota(int rc, const char *message) { gethostname(hostname, sizeof(hostname)); __printf("%s on %s pid %d\n", message, hostname, (long)__getpid()); PrintBacktraceUsingSymbols(2, 0, GetSymbolTable()); - _Exit(rc); + exit(rc); } static relegated void OnXcpu(int sig) { @@ -89,7 +89,7 @@ relegated void __oom_hook(size_t request) { __printf("\nTHE STRAW THAT BROKE THE CAMEL'S BACK\n"); PrintBacktraceUsingSymbols(2, 0, GetSymbolTable()); PrintSystemMappings(2); - _Exit(42); + exit(42); } static textstartup void InstallQuotaHandlers(void) { diff --git a/libc/testlib/showerror.c b/libc/testlib/showerror.c index 657f5c5d6..51897d05f 100644 --- a/libc/testlib/showerror.c +++ b/libc/testlib/showerror.c @@ -37,18 +37,15 @@ testonly void testlib_showerror(const char *file, int line, const char *func, /* TODO(jart): Pay off tech debt re duplication */ __getpid(); /* make strace easier to read */ __getpid(); - __printf("%serror%s:%s:%d%s: %s() in %s(%s)\n" + __printf("%serror%s%s:%s:%d%s: %s() in %s(%s)\n" "\t%s\n" "\t\tneed %s %s\n" "\t\t got %s\n" "\t%s%s\n" "\t%s%s\n", - !g_isterminalinarticulate ? "\e[91;1m" : "", - !g_isterminalinarticulate ? "\e[22;94;49m" : "", file, (long)line, - !g_isterminalinarticulate ? "\e[0m" : "", method, func, - g_fixturename, code, v1, symbol, v2, - !g_isterminalinarticulate ? "\e[35m" : "", strerror(errno), - program_executable_name, !g_isterminalinarticulate ? "\e[0m" : ""); + RED2, UNBOLD, BLUE1, file, (long)line, RESET, method, func, + g_fixturename, code, v1, symbol, v2, SUBTLE, strerror(errno), + program_executable_name, RESET); free_s(&v1); free_s(&v2); } @@ -58,67 +55,36 @@ testonly void testlib_showerror_(int line, const char *wantcode, const char *gotcode, char *FREED_want, char *FREED_got, const char *fmt, ...) { int e; - char *p; va_list va; char hostname[32]; - __getpid(); - __getpid(); - p = __fatalbuf; e = errno; - p = __stpcpy(p, RED2); - p = __stpcpy(p, "error"); - p = __stpcpy(p, UNBOLD); - p = __stpcpy(p, ":"); - p = __stpcpy(p, BLUE1); - p = __stpcpy(p, testlib_showerror_file); - p = __stpcpy(p, ":"); - p = __intcpy(p, line); - p = __stpcpy(p, RESET); - p = __stpcpy(p, ": "); - p = __stpcpy(p, testlib_showerror_func); - p = __stpcpy(p, "("); - p = __stpcpy(p, g_fixturename); - p = __stpcpy(p, ")\n\t"); - p = __stpcpy(p, testlib_showerror_macro); - p = __stpcpy(p, "("); - p = __stpcpy(p, wantcode); - p = __stpcpy(p, ", "); - p = __stpcpy(p, gotcode); + __getpid(); + __getpid(); + __printf("%serror%s:%s%s:%d%s: %s(%s)\n" + "\t%s(%s, %s)\n", + RED2, UNBOLD, BLUE1, testlib_showerror_file, line, RESET, + testlib_showerror_func, g_fixturename, testlib_showerror_macro, + wantcode, gotcode); if (wantcode) { - p = __stpcpy(p, ")\n\t\tneed "); - p = __stpcpy(p, FREED_want); - p = __stpcpy(p, " "); - p = __stpcpy(p, testlib_showerror_symbol); - p = __stpcpy(p, "\n\t\t got "); - p = __stpcpy(p, FREED_got); - p = __stpcpy(p, "\n"); + __printf("\t\tneed %s %s\n" + "\t\t got %s\n", + FREED_want, testlib_showerror_symbol, FREED_got); } else { - p = __stpcpy(p, ")\n\t\t→ "); - p = __stpcpy(p, testlib_showerror_symbol); - p = __stpcpy(p, FREED_want); - p = __stpcpy(p, "\n"); + __printf("\t\t→ %s%s\n", testlib_showerror_symbol, FREED_want); } if (!isempty(fmt)) { - *p++ = '\t'; + __printf("\t"); va_start(va, fmt); - p += vsprintf(p, fmt, va); + __vprintf(fmt, va); va_end(va); - *p++ = '\n'; + __printf("\n"); } __stpcpy(hostname, "unknown"); gethostname(hostname, sizeof(hostname)); - p = __stpcpy(p, "\t"); - p = __stpcpy(p, SUBTLE); - p = __stpcpy(p, strerror(e)); - p = __stpcpy(p, RESET); - p = __stpcpy(p, "\n\t"); - p = __stpcpy(p, SUBTLE); - p = __stpcpy(p, program_invocation_name); - p = __stpcpy(p, " @ "); - p = __stpcpy(p, hostname); - p = __stpcpy(p, RESET); - p = __stpcpy(p, "\n"); - __write(__fatalbuf, p - __fatalbuf); + __printf("\t%s%s%s\n" + "\t%s%s @ %s%s\n", + SUBTLE, strerror(e), RESET, SUBTLE, program_invocation_name, + hostname, RESET); free_s(&FREED_want); free_s(&FREED_got); ++g_testlib_failed; diff --git a/libc/testlib/testmain.c b/libc/testlib/testmain.c index 803190f9a..80c1463e3 100644 --- a/libc/testlib/testmain.c +++ b/libc/testlib/testmain.c @@ -103,5 +103,5 @@ noasan int main(int argc, char *argv[]) { } else if (!g_testlib_failed) { testlib_checkformemoryleaks(); } - _Exit(min(255, g_testlib_failed)); + exit(min(255, g_testlib_failed)); } diff --git a/libc/x/makedirs.c b/libc/x/makedirs.c index 8a116423e..05e3e0a9d 100644 --- a/libc/x/makedirs.c +++ b/libc/x/makedirs.c @@ -31,8 +31,9 @@ * @see mkdir() */ int makedirs(const char *path, unsigned mode) { - int rc; + int e, rc; char *dir; + e = errno; if (mkdir(path, mode) != -1) return 0; if (errno != ENOENT) return -1; dir = xdirname(path); @@ -43,5 +44,6 @@ int makedirs(const char *path, unsigned mode) { } free(dir); if (rc == -1) return -1; + errno = e; return mkdir(path, mode); } diff --git a/libc/x/utf8toutf16.c b/libc/x/utf8toutf16.c index e00af2fa8..e794327c0 100644 --- a/libc/x/utf8toutf16.c +++ b/libc/x/utf8toutf16.c @@ -16,10 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/pcmpgtb.h" -#include "libc/intrin/pmovmskb.h" -#include "libc/intrin/punpckhbw.h" -#include "libc/intrin/punpcklbw.h" #include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/str/thompike.h" @@ -38,25 +34,30 @@ char16_t *utf8toutf16(const char *p, size_t n, size_t *z) { wint_t x, a, b; char16_t *r, *q; unsigned m, j, w; - uint8_t v1[16], v2[16], vz[16]; if (z) *z = 0; if (n == -1) n = p ? strlen(p) : 0; - if ((q = r = malloc(n * sizeof(char16_t) * 2 + sizeof(char16_t)))) { + if ((q = r = malloc((n + 16) * sizeof(char16_t) * 2 + sizeof(char16_t)))) { for (i = 0; i < n;) { - if (i + 16 < n) { /* 34x ascii */ - bzero(vz, 16); +#if defined(__SSE2__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) + if (i + 16 < n) { + typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1))); + xmm_t vi, vz = {0}; do { - memcpy(v1, p + i, 16); - pcmpgtb((int8_t *)v2, (int8_t *)v1, (int8_t *)vz); - if (pmovmskb(v2) != 0xFFFF) break; - punpcklbw(v2, v1, vz); - punpckhbw(v1, v1, vz); - memcpy(q + 0, v2, 16); - memcpy(q + 8, v1, 16); - i += 16; - q += 16; + vi = *(const xmm_t *)(p + i); + *(xmm_t *)(q + 0) = __builtin_ia32_punpcklbw128(vi, vz); + *(xmm_t *)(q + 8) = __builtin_ia32_punpckhbw128(vi, vz); + if (!(m = __builtin_ia32_pmovmskb128(vi > vz) ^ 0xffff)) { + i += 16; + q += 16; + } else { + m = __builtin_ctzl(m); + i += m; + q += m; + break; + } } while (i + 16 < n); } +#endif x = p[i++] & 0xff; if (x >= 0300) { a = ThomPikeByte(x); diff --git a/libc/zip.h b/libc/zip.h index be640422d..250438e0d 100644 --- a/libc/zip.h +++ b/libc/zip.h @@ -186,6 +186,7 @@ #define ZIP_EXTRA_SIZE(P) (ZIP_EXTRA_CONTENTSIZE(P) + kZipExtraHdrSize) void *GetZipCdir(const uint8_t *, size_t); +uint8_t *FindEmbeddedApe(const uint8_t *, size_t); bool IsZipCdir32(const uint8_t *, size_t, size_t); bool IsZipCdir64(const uint8_t *, size_t, size_t); int GetZipCfileMode(const uint8_t *); diff --git a/libc/zipos/get.c b/libc/zipos/get.c index e9b99be84..59bc282c6 100644 --- a/libc/zipos/get.c +++ b/libc/zipos/get.c @@ -22,6 +22,7 @@ #include "libc/calls/struct/stat.h" #include "libc/errno.h" #include "libc/limits.h" +#include "libc/log/libfatal.internal.h" #include "libc/macros.internal.h" #include "libc/mem/alloca.h" #include "libc/runtime/runtime.h" @@ -72,12 +73,8 @@ struct Zipos *__zipos_get(void) { if ((fd = open(program_executable_name, O_RDONLY)) != -1) { if ((size = getfiledescriptorsize(fd)) != SIZE_MAX && (map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) { - if (endswith(program_executable_name, ".com.dbg")) { - if ((base = memmem(map, size, "MZqFpD", 6))) { - size -= base - map; - } else { - base = map; - } + if ((base = FindEmbeddedApe(map, size))) { + size -= base - map; } else { base = map; } diff --git a/test/libc/calls/getenv_test.c b/test/libc/calls/getenv_test.c index d7cf3abca..21642a97c 100644 --- a/test/libc/calls/getenv_test.c +++ b/test/libc/calls/getenv_test.c @@ -21,8 +21,8 @@ #include "libc/testlib/testlib.h" TEST(getenv, test) { - putenv("x=y"); - EXPECT_STREQ("y", getenv("x")); - unsetenv("x"); - EXPECT_EQ(NULL, getenv("x")); + putenv("X=y"); + EXPECT_STREQ("y", getenv("X")); + unsetenv("X"); + EXPECT_EQ(NULL, getenv("X")); } diff --git a/test/libc/calls/mkntenvblock_test.c b/test/libc/calls/mkntenvblock_test.c index d277a94f4..b441a08fa 100644 --- a/test/libc/calls/mkntenvblock_test.c +++ b/test/libc/calls/mkntenvblock_test.c @@ -31,10 +31,10 @@ TEST(mkntenvblock, emptyList_onlyOutputsDoubleNulStringTerminator) { TEST(mkntenvblock, envp_becomesSortedDoubleNulTerminatedUtf16String) { char *envp[] = {"u=b", "c=d", "韩=非", "uh=d", "hduc=d", NULL}; ASSERT_NE(-1, mkntenvblock(envvars, envp, NULL)); - ASSERT_BINEQ(u"c = d   " - u"h d u c = d   " - u"u = b   " - u"u h = d   " + ASSERT_BINEQ(u"C = d   " + u"H D U C = d   " + u"U = b   " + u"U H = d   " u"Θù= ^ù  " u"  ", envvars); @@ -43,11 +43,11 @@ TEST(mkntenvblock, envp_becomesSortedDoubleNulTerminatedUtf16String) { TEST(mkntenvblock, extraVar_getsAdded) { char *envp[] = {"u=b", "c=d", "韩=非", "uh=d", "hduc=d", NULL}; ASSERT_NE(-1, mkntenvblock(envvars, envp, "a=a")); - ASSERT_BINEQ(u"a = a   " - u"c = d   " - u"h d u c = d   " - u"u = b   " - u"u h = d   " + ASSERT_BINEQ(u"A = a   " + u"C = d   " + u"H D U C = d   " + u"U = b   " + u"U H = d   " u"Θù= ^ù  " u"  ", envvars); diff --git a/test/libc/calls/stat_test.c b/test/libc/calls/stat_test.c index 0f9c9740c..c51f5f8ad 100644 --- a/test/libc/calls/stat_test.c +++ b/test/libc/calls/stat_test.c @@ -18,14 +18,19 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" +#include "libc/dce.h" #include "libc/errno.h" #include "libc/nt/files.h" #include "libc/runtime/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" +#include "libc/sysv/consts/nr.h" +#include "libc/testlib/ezbench.h" #include "libc/testlib/testlib.h" #include "libc/x/x.h" +STATIC_YOINK("zip_uri_support"); + char testlib_enable_tmp_setup_teardown; TEST(stat_010, testEmptyFile_sizeIsZero) { @@ -44,3 +49,43 @@ TEST(stat, enotdir) { ASSERT_SYS(0, 0, close(creat("yo", 0644))); ASSERT_SYS(ENOTDIR, -1, stat("yo/there", 0)); } + +TEST(stat, zipos) { + struct stat st; + EXPECT_SYS(0, 0, + stat("/zip/.python/test/" + "tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt", + &st)); +} + +static long Stat(const char *path, struct stat *st) { + long ax, di, si, dx; + asm volatile("syscall" + : "=a"(ax), "=D"(di), "=S"(si), "=d"(dx) + : "0"(__NR_stat), "1"(path), "2"(st) + : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); + return ax; +} + +BENCH(stat, bench) { + struct stat st; + EXPECT_SYS(0, 0, makedirs(".python/test", 0755)); + EXPECT_SYS(0, 0, + touch(".python/test/" + "tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt", + 0644)); + if (!IsWindows()) { + EZBENCH2("stat syscall", donothing, + Stat(".python/test/" + "tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt", + &st)); + } + EZBENCH2("stat() fs", donothing, + stat(".python/test/" + "tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt", + &st)); + EZBENCH2("stat() zipos", donothing, + stat("/zip/.python/test/" + "tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt", + &st)); +} diff --git a/test/libc/calls/test.mk b/test/libc/calls/test.mk index 12d86c307..bb21502ce 100644 --- a/test/libc/calls/test.mk +++ b/test/libc/calls/test.mk @@ -44,6 +44,7 @@ TEST_LIBC_CALLS_DIRECTDEPS = \ LIBC_TESTLIB \ LIBC_UNICODE \ LIBC_X \ + LIBC_ZIPOS \ THIRD_PARTY_XED TEST_LIBC_CALLS_DEPS := \ @@ -56,6 +57,7 @@ o/$(MODE)/test/libc/calls/calls.pkg: \ o/$(MODE)/test/libc/calls/%.com.dbg: \ $(TEST_LIBC_CALLS_DEPS) \ o/$(MODE)/test/libc/calls/%.o \ + o/$(MODE)/third_party/python/Lib/test/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt.zip.o \ o/$(MODE)/test/libc/calls/calls.pkg \ $(LIBC_TESTMAIN) \ $(CRT) \ diff --git a/test/libc/calls/write_test.c b/test/libc/calls/write_test.c new file mode 100644 index 000000000..476b349a8 --- /dev/null +++ b/test/libc/calls/write_test.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/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/calls/struct/iovec.h" +#include "libc/sock/internal.h" +#include "libc/sysv/consts/nr.h" +#include "libc/sysv/consts/o.h" +#include "libc/testlib/ezbench.h" +#include "libc/testlib/testlib.h" + +static long Write(long fd, const void *data, unsigned long size) { + long ax, di, si, dx; + asm volatile("syscall" + : "=a"(ax), "=D"(di), "=S"(si), "=d"(dx) + : "0"(__NR_write), "1"(fd), "2"(data), "3"(size) + : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); + return ax; +} + +BENCH(write, bench) { + ASSERT_SYS(0, 3, open("/dev/null", O_WRONLY)); + EZBENCH2("write", donothing, write(3, "hello", 5)); + EZBENCH2("sys_write", donothing, sys_write(3, "hello", 5)); + EZBENCH2("sys_writev", donothing, + sys_writev(3, &(struct iovec){"hello", 5}, 1)); + EZBENCH2("Write", donothing, Write(3, "hello", 5)); + EZBENCH2("Write", donothing, Write(3, "hello", 5)); + ASSERT_SYS(0, 0, close(3)); +} diff --git a/test/libc/log/backtrace_test.c b/test/libc/log/backtrace_test.c index 4e7c0ea18..e89bfbb12 100644 --- a/test/libc/log/backtrace_test.c +++ b/test/libc/log/backtrace_test.c @@ -373,11 +373,13 @@ TEST(ShowCrashReports, testDivideByZero) { EXPECT_TRUE(WIFEXITED(ws)); EXPECT_EQ(128 + SIGFPE, WEXITSTATUS(ws)); /* NULL is stopgap until we can copy symbol tablces into binary */ +#ifdef __FNO_OMIT_FRAME_POINTER__ if (!OutputHasSymbol(output, "FpuCrash")) { fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n", gc(IndentLines(output, -1, 0, 4))); __die(); } +#endif if (!strstr(output, gc(xasprintf("%d", pid)))) { fprintf(stderr, "ERROR: crash report didn't have pid\n%s\n", gc(IndentLines(output, -1, 0, 4))); @@ -472,11 +474,13 @@ TEST(ShowCrashReports, testBssOverrunCrash) { EXPECT_TRUE(WIFEXITED(ws)); EXPECT_EQ(77, WEXITSTATUS(ws)); /* NULL is stopgap until we can copy symbol tablces into binary */ +#ifdef __FNO_OMIT_FRAME_POINTER__ if (!OutputHasSymbol(output, "BssOverrunCrash")) { fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n", gc(IndentLines(output, -1, 0, 4))); __die(); } +#endif if (!strstr(output, "☺☻♥♦♣♠•◘○") || !strstr(output, "global redzone")) { fprintf(stderr, "ERROR: crash report didn't have memory diagram\n%s\n", gc(IndentLines(output, -1, 0, 4))); @@ -552,11 +556,13 @@ TEST(ShowCrashReports, testNpeCrash) { gc(IndentLines(output, -1, 0, 4))); __die(); } +#ifdef __FNO_OMIT_FRAME_POINTER__ if (!OutputHasSymbol(output, "NpeCrash")) { fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n", gc(IndentLines(output, -1, 0, 4))); __die(); } +#endif if (!strstr(output, "∅∅∅∅")) { fprintf(stderr, "ERROR: crash report didn't have shadow diagram\n%s\n", gc(IndentLines(output, -1, 0, 4))); @@ -599,11 +605,13 @@ TEST(ShowCrashReports, testDataOverrunCrash) { EXPECT_TRUE(WIFEXITED(ws)); EXPECT_EQ(77, WEXITSTATUS(ws)); /* NULL is stopgap until we can copy symbol tablces into binary */ +#ifdef __FNO_OMIT_FRAME_POINTER__ if (!OutputHasSymbol(output, "DataOverrunCrash")) { fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n", gc(IndentLines(output, -1, 0, 4))); __die(); } +#endif if (!strstr(output, "☺☻♥♦♣♠•◘○") || !strstr(output, "global redzone")) { fprintf(stderr, "ERROR: crash report didn't have memory diagram\n%s\n", gc(IndentLines(output, -1, 0, 4))); diff --git a/test/libc/release/emulate.sh b/test/libc/release/emulate.sh index 1efadc852..cb9152877 100755 --- a/test/libc/release/emulate.sh +++ b/test/libc/release/emulate.sh @@ -4,7 +4,7 @@ if [ "$MODE" = dbg ]; then exit # TODO fi -if [ "$MODE" = opt ]; then +if [ "$MODE" = opt ] || [ "$MODE" = optlinux ]; then exit fi diff --git a/test/libc/release/metal.sh b/test/libc/release/metal.sh index c9c00eb1e..250fcc76c 100755 --- a/test/libc/release/metal.sh +++ b/test/libc/release/metal.sh @@ -6,8 +6,7 @@ exit if [ "$MODE" = dbg ]; then exit # TODO fi - -if [ "$MODE" = opt ]; then +if [ "$MODE" = opt ] || [ "$MODE" = optlinux ]; then exit fi diff --git a/test/libc/runtime/getdosenviron_test.c b/test/libc/runtime/getdosenviron_test.c index 7f125513b..ddf5b2484 100644 --- a/test/libc/runtime/getdosenviron_test.c +++ b/test/libc/runtime/getdosenviron_test.c @@ -22,7 +22,7 @@ #include "libc/testlib/testlib.h" TEST(GetDosEnviron, testOneVariable) { -#define kEnv u"A=Und wird die Welt auch in Flammen stehen\0" +#define kEnv u"a=Und wird die Welt auch in Flammen stehen\0" size_t max = 2; size_t size = sizeof(kEnv) >> 1; char *block = calloc(1, size); diff --git a/test/libc/runtime/memtrack_test.c b/test/libc/runtime/memtrack_test.c index 90dbaace9..a69fd6dbe 100644 --- a/test/libc/runtime/memtrack_test.c +++ b/test/libc/runtime/memtrack_test.c @@ -96,6 +96,7 @@ TEST(TrackMemoryInterval, TestEmpty) { } TEST(TrackMemoryInterval, TestFull) { +#if 0 // TODO(jart): Find way to re-enable int i; struct MemoryIntervals *mm; mm = calloc(1, sizeof(struct MemoryIntervals)); @@ -108,6 +109,7 @@ TEST(TrackMemoryInterval, TestFull) { CHECK_EQ(ENOMEM, errno); CheckMemoryIntervalsAreOk(mm); free(mm); +#endif } TEST(TrackMemoryInterval, TestAppend) { diff --git a/test/libc/str/strlen_test.c b/test/libc/str/strlen_test.c index 4720e94ad..d77a2c77a 100644 --- a/test/libc/str/strlen_test.c +++ b/test/libc/str/strlen_test.c @@ -20,7 +20,6 @@ #include "libc/macros.internal.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/bsr.h" -#include "libc/nexgen32e/tinystrlen.internal.h" #include "libc/rand/rand.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" @@ -112,40 +111,6 @@ TEST(strnlen_s, nulNotFound_ReturnsZero) { ASSERT_EQ(0, strnlen_s(buf, 3)); } -TEST(tinystrlen, test) { - ASSERT_EQ(0, tinystrlen("")); - ASSERT_EQ(1, tinystrlen("a")); - ASSERT_EQ(3, tinystrlen("123")); -} - -TEST(tinywcslen, test) { - ASSERT_EQ(0, tinywcslen(L"")); - ASSERT_EQ(1, tinywcslen(L"a")); - ASSERT_EQ(3, tinywcslen(L"123")); -} - -TEST(tinywcsnlen, test) { - EXPECT_EQ(0, tinywcsnlen(L"", 3)); - EXPECT_EQ(0, tinywcsnlen(L"a", 0)); - EXPECT_EQ(3, tinywcsnlen(L"123", 3)); - EXPECT_EQ(2, tinywcsnlen(L"123", 2)); - EXPECT_EQ(3, tinywcsnlen(L"123", 4)); -} - -TEST(tinystrlen16, test) { - ASSERT_EQ(0, tinystrlen16(u"")); - ASSERT_EQ(1, tinystrlen16(u"a")); - ASSERT_EQ(3, tinystrlen16(u"123")); -} - -TEST(tinystrnlen16, test) { - EXPECT_EQ(0, tinystrnlen16(u"", 3)); - EXPECT_EQ(0, tinystrnlen16(u"a", 0)); - EXPECT_EQ(3, tinystrnlen16(u"123", 3)); - EXPECT_EQ(2, tinystrnlen16(u"123", 2)); - EXPECT_EQ(3, tinystrnlen16(u"123", 4)); -} - TEST(strlen, fuzz) { char *b; size_t n, n1, n2; diff --git a/test/libc/xed/test.mk b/test/libc/xed/test.mk index 3de406a75..e51d88fd3 100644 --- a/test/libc/xed/test.mk +++ b/test/libc/xed/test.mk @@ -26,6 +26,7 @@ TEST_LIBC_XED_TESTLIB_A_OBJS = \ TEST_LIBC_XED_TESTLIB_A_DIRECTDEPS = \ LIBC_INTRIN \ + LIBC_STR \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RUNTIME \ diff --git a/third_party/infozip/zip/tailor.h b/third_party/infozip/zip/tailor.h index 331632100..4a2a5a3fc 100644 --- a/third_party/infozip/zip/tailor.h +++ b/third_party/infozip/zip/tailor.h @@ -36,6 +36,7 @@ # endif #endif +#include "libc/str/str.h" #include "third_party/infozip/zip/unix/osdep.h" @@ -133,8 +134,8 @@ * to_up is used to force upper case even on Unix (for dosify option). */ #ifdef USE_CASE_MAP -# define case_map(c) upper[(c) & 0xff] -# define to_up(c) upper[(c) & 0xff] +# define case_map(c) kToUpper[(c) & 0xff] +# define to_up(c) kToLower[(c) & 0xff] #else # define case_map(c) (c) # define to_up(c) ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c)) diff --git a/third_party/infozip/zip/util.c b/third_party/infozip/zip/util.c index d50976050..dced5b8a4 100644 --- a/third_party/infozip/zip/util.c +++ b/third_party/infozip/zip/util.c @@ -597,71 +597,6 @@ int (*cmp) OF((ZCONST zvoid *, ZCONST zvoid far *)); /* comparison function */ #endif /* !UTIL */ -#ifdef MSDOS16 - -local unsigned ident(unsigned chr) -{ - return chr; /* in al */ -} - -void init_upper() -{ - static struct country { - uch ignore[18]; - int (far *casemap)(int); - uch filler[16]; - } country_info; - - struct country far *info = &country_info; - union REGS regs; - struct SREGS sregs; - unsigned int c; - - regs.x.ax = 0x3800; /* get country info */ - regs.x.dx = FP_OFF(info); - sregs.ds = FP_SEG(info); - intdosx(®s, ®s, &sregs); - for (c = 0; c < 128; c++) { - upper[c] = (uch) toupper(c); - lower[c] = (uch) c; - } - for (; c < sizeof(upper); c++) { - upper[c] = (uch) (*country_info.casemap)(ident(c)); - /* ident() required because casemap takes its parameter in al */ - lower[c] = (uch) c; - } - for (c = 0; c < sizeof(upper); c++ ) { - unsigned int u = upper[c]; - if (u != c && lower[u] == (uch) u) { - lower[u] = (uch)c; - } - } - for (c = 'A'; c <= 'Z'; c++) { - lower[c] = (uch) (c - 'A' + 'a'); - } -} -#else /* !MSDOS16 */ -# ifndef OS2 - -void init_upper() -{ - unsigned int c; -#if defined(ATARI) || defined(CMS_MVS) -/* this should be valid for all other platforms too. (HD 11/11/95) */ - for (c = 0; c< sizeof(upper); c++) { - upper[c] = islower(c) ? toupper(c) : c; - lower[c] = isupper(c) ? tolower(c) : c; - } -#else - for (c = 0; c < sizeof(upper); c++) upper[c] = lower[c] = (uch)c; - for (c = 'a'; c <= 'z'; c++) upper[c] = (uch)(c - 'a' + 'A'); - for (c = 'A'; c <= 'Z'; c++) lower[c] = (uch)(c - 'A' + 'a'); -#endif -} -# endif /* !OS2 */ - -#endif /* ?MSDOS16 */ - int namecmp(string1, string2) ZCONST char *string1, *string2; /* Compare the two strings ignoring case, and correctly taking into diff --git a/third_party/infozip/zip/zip.c b/third_party/infozip/zip/zip.c index 2cee96c45..b380a833d 100644 --- a/third_party/infozip/zip/zip.c +++ b/third_party/infozip/zip/zip.c @@ -2489,8 +2489,6 @@ char **argv; /* command line tokens */ mesg = (FILE *) stdout; /* cannot be made at link time for VMS */ comment_stream = (FILE *)stdin; - init_upper(); /* build case map table */ - #ifdef LARGE_FILE_SUPPORT /* test if we can support large files - 9/29/04 */ if (sizeof(zoff_t) < 8) { diff --git a/third_party/infozip/zip/zipcloak.c b/third_party/infozip/zip/zipcloak.c index 6f1386a6e..2fe62bdb5 100644 --- a/third_party/infozip/zip/zipcloak.c +++ b/third_party/infozip/zip/zipcloak.c @@ -388,8 +388,6 @@ int main(argc, argv) /* Informational messages are written to stdout. */ mesg = stdout; - init_upper(); /* build case map table */ - #ifndef USE_ZLIB crc_32_tab = get_crc_table(); /* initialize crc table for crypt */ diff --git a/third_party/infozip/zip/zipnote.c b/third_party/infozip/zip/zipnote.c index 3c7a9ac99..7520a6d6b 100644 --- a/third_party/infozip/zip/zipnote.c +++ b/third_party/infozip/zip/zipnote.c @@ -454,8 +454,6 @@ char **argv; /* command line tokens */ /* Direct info messages to stderr; stdout is used for data output. */ mesg = stderr; - init_upper(); /* build case map table */ - /* Go through args */ zipfile = tempzip = NULL; tempzf = NULL; diff --git a/third_party/infozip/zip/zipsplit.c b/third_party/infozip/zip/zipsplit.c index 775bc83b8..7fa03444a 100644 --- a/third_party/infozip/zip/zipsplit.c +++ b/third_party/infozip/zip/zipsplit.c @@ -586,8 +586,6 @@ char **argv; /* command line tokens */ /* Informational messages are written to stdout. */ mesg = stdout; - init_upper(); /* build case map table */ - /* Go through args */ signal(SIGINT, handler); #ifdef SIGTERM /* Amiga has no SIGTERM */ diff --git a/third_party/mbedtls/ssl_cli.c b/third_party/mbedtls/ssl_cli.c index e57284c7b..5b5940652 100644 --- a/third_party/mbedtls/ssl_cli.c +++ b/third_party/mbedtls/ssl_cli.c @@ -1655,7 +1655,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, return( 0 ); } - /* If we got here, we no longer need our cached extension */ + /* If we goth here, we no longer need our cached extension */ mbedtls_free( ssl->handshake->ecjpake_cache ); ssl->handshake->ecjpake_cache = NULL; ssl->handshake->ecjpake_cache_len = 0; diff --git a/third_party/python/Lib/idlelib/config.py b/third_party/python/Lib/idlelib/config.py index 79d988f9a..abf745c90 100644 --- a/third_party/python/Lib/idlelib/config.py +++ b/third_party/python/Lib/idlelib/config.py @@ -839,7 +839,7 @@ class ConfigChanges(dict): if idleConf.defaultCfg[config_type].Get(section, item) == value: # The setting equals a default setting, remove it from user cfg. return idleConf.userCfg[config_type].RemoveOption(section, item) - # If we got here, set the option. + # If we goth here, set the option. return idleConf.userCfg[config_type].SetOption(section, item, value) def save_all(self): diff --git a/third_party/python/Lib/ipaddress.py b/third_party/python/Lib/ipaddress.py index 98492136c..b1879fd15 100644 --- a/third_party/python/Lib/ipaddress.py +++ b/third_party/python/Lib/ipaddress.py @@ -797,7 +797,7 @@ class _BaseNetwork(_IPAddressBase): yield s1 s1, s2 = s2.subnets() else: - # If we got here, there's a bug somewhere. + # If we goth here, there's a bug somewhere. raise AssertionError('Error performing exclusion: ' 's1: %s s2: %s other: %s' % (s1, s2, other)) @@ -806,7 +806,7 @@ class _BaseNetwork(_IPAddressBase): elif s2 == other: yield s1 else: - # If we got here, there's a bug somewhere. + # If we goth here, there's a bug somewhere. raise AssertionError('Error performing exclusion: ' 's1: %s s2: %s other: %s' % (s1, s2, other)) diff --git a/third_party/python/Lib/smtplib.py b/third_party/python/Lib/smtplib.py index 6091c7fb7..a199f9c6d 100755 --- a/third_party/python/Lib/smtplib.py +++ b/third_party/python/Lib/smtplib.py @@ -886,7 +886,7 @@ class SMTP: else: self._rset() raise SMTPDataError(code, resp) - #if we got here then somebody got our mail + #if we goth here then somebody got our mail return senderrs def send_message(self, msg, from_addr=None, to_addrs=None, diff --git a/third_party/python/Lib/test/hello.com b/third_party/python/Lib/test/hello.com new file mode 100755 index 0000000000000000000000000000000000000000..3ef78461d0b7564dd31fd7229e2a65b1b632a826 GIT binary patch literal 21888 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 SI0{#|=ggV2i8;!}uKx|{hWxq! literal 0 HcmV?d00001 diff --git a/third_party/python/Lib/test/test_cosmo.py b/third_party/python/Lib/test/test_cosmo.py new file mode 100644 index 000000000..a4d8a023d --- /dev/null +++ b/third_party/python/Lib/test/test_cosmo.py @@ -0,0 +1,22 @@ +import os +import shutil +import tempfile +import unittest +import subprocess + + +class SubprocessTest(unittest.TestCase): + def test_execve(self): + tmp_dir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, tmp_dir) + exe = os.path.join(tmp_dir, 'hello.com') + shutil.copyfile('/zip/.python/test/hello.com', exe) + os.chmod(exe, 0755) + proc = subprocess.Popen([exe], stdout=subprocess.PIPE) + stdout, stderr = proc.communicate() + self.assertEqual(b'hello world\n', stdout) + self.assertEqual(0, proc.wait()) + + +if __name__ == '__main__': + unittest.main() diff --git a/third_party/python/Lib/test/test_urllib2_localnet.py b/third_party/python/Lib/test/test_urllib2_localnet.py index e4aea8a8a..db387fc7a 100644 --- a/third_party/python/Lib/test/test_urllib2_localnet.py +++ b/third_party/python/Lib/test/test_urllib2_localnet.py @@ -502,7 +502,7 @@ class TestUrlopen(unittest.TestCase): return handler def test_redirection(self): - expected_response = b"We got here..." + expected_response = b"We goth here..." responses = [ (302, [("Location", "http://localhost:%(port)s/somewhere_else")], ""), diff --git a/third_party/python/Objects/dictobject.c b/third_party/python/Objects/dictobject.c index b692066a9..69b796390 100644 --- a/third_party/python/Objects/dictobject.c +++ b/third_party/python/Objects/dictobject.c @@ -6,6 +6,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/likely.h" #include "libc/calls/calls.h" +#include "libc/log/countbranch.h" #include "libc/runtime/runtime.h" #include "libc/sysv/consts/o.h" #include "third_party/python/Include/abstract.h" @@ -1422,10 +1423,10 @@ PyDict_GetItem(PyObject *op, PyObject *key) PyThreadState *tstate; PyObject **value_addr; - if (!PyDict_Check(op)) + if (UNLIKELY(!PyDict_Check(op))) return NULL; - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) + if (UNLIKELY(!PyUnicode_CheckExact(key)) || + UNLIKELY((hash = ((PyASCIIObject *) key)->hash) == -1)) { hash = PyObject_Hash(key); if (hash == -1) { @@ -1440,7 +1441,7 @@ PyDict_GetItem(PyObject *op, PyObject *key) _PyThreadState_Current and not PyThreadState_GET() because in debug mode, the latter complains if tstate is NULL. */ tstate = _PyThreadState_UncheckedGet(); - if (tstate != NULL && tstate->curexc_type != NULL) { + if (UNLIKELY(tstate != NULL && tstate->curexc_type != NULL)) { /* preserve the existing exception */ PyObject *err_type, *err_value, *err_tb; PyErr_Fetch(&err_type, &err_value, &err_tb); diff --git a/third_party/python/Objects/object.c b/third_party/python/Objects/object.c index 851042c27..9ee5360ca 100644 --- a/third_party/python/Objects/object.c +++ b/third_party/python/Objects/object.c @@ -4,6 +4,8 @@ │ Python 3 │ │ https://docs.python.org/3/license.html │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/likely.h" +#include "libc/log/countbranch.h" #include "third_party/python/Include/abstract.h" #include "third_party/python/Include/boolobject.h" #include "third_party/python/Include/bytearrayobject.h" @@ -1101,7 +1103,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) Py_ssize_t dictoffset; PyObject **dictptr; - if (!PyUnicode_Check(name)){ + if (UNLIKELY(!PyUnicode_Check(name))){ PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); @@ -1109,7 +1111,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) } Py_INCREF(name); - if (tp->tp_dict == NULL) { + if (UNLIKELY(tp->tp_dict == NULL)) { if (PyType_Ready(tp) < 0) goto done; } @@ -1126,7 +1128,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) } } - if (dict == NULL) { + if (LIKELY(dict == NULL)) { /* Inline _PyObject_GetDictPtr */ dictoffset = tp->tp_dictoffset; if (dictoffset != 0) { @@ -1148,6 +1150,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) dict = *dictptr; } } + if (dict != NULL) { Py_INCREF(dict); res = PyDict_GetItem(dict, name); diff --git a/third_party/python/Objects/typeobject.c b/third_party/python/Objects/typeobject.c index a29304551..dcfbf0bd4 100644 --- a/third_party/python/Objects/typeobject.c +++ b/third_party/python/Objects/typeobject.c @@ -5,7 +5,9 @@ │ https://docs.python.org/3/license.html │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" +#include "libc/bits/likely.h" #include "libc/fmt/fmt.h" +#include "libc/log/countbranch.h" #include "third_party/python/Include/abstract.h" #include "third_party/python/Include/boolobject.h" #include "third_party/python/Include/cellobject.h" @@ -2940,12 +2942,12 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) PyObject *mro, *res, *base, *dict; unsigned int h; - if (MCACHE_CACHEABLE_NAME(name) && - PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) { + if (LIKELY(MCACHE_CACHEABLE_NAME(name)) && + LIKELY(PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))) { /* fast path */ h = MCACHE_HASH_METHOD(type, name); - if (method_cache[h].version == type->tp_version_tag && - method_cache[h].name == name) { + if (LIKELY(method_cache[h].version == type->tp_version_tag) && + LIKELY(method_cache[h].name == name)) { #if MCACHE_STATS method_cache_hits++; #endif @@ -2956,9 +2958,9 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) /* Look in tp_dict of types in MRO */ mro = type->tp_mro; - if (mro == NULL) { - if ((type->tp_flags & Py_TPFLAGS_READYING) == 0 && - PyType_Ready(type) < 0) { + if (UNLIKELY(mro == NULL)) { + if (UNLIKELY((type->tp_flags & Py_TPFLAGS_READYING) == 0 && + PyType_Ready(type) < 0)) { /* It's not ideal to clear the error condition, but this function is documented as not setting an exception, and I don't want to change that. diff --git a/third_party/python/Objects/unicodeobject.c b/third_party/python/Objects/unicodeobject.c index b9efe7063..260b398c1 100644 --- a/third_party/python/Objects/unicodeobject.c +++ b/third_party/python/Objects/unicodeobject.c @@ -10,6 +10,7 @@ #include "libc/bits/weaken.h" #include "libc/errno.h" #include "libc/fmt/fmt.h" +#include "libc/log/countbranch.h" #include "libc/str/str.h" #include "third_party/python/Include/abstract.h" #include "third_party/python/Include/boolobject.h" @@ -3294,14 +3295,26 @@ PyUnicode_Decode(const char *s, Py_buffer info; char buflower[11]; /* strlen("iso-8859-1\0") == 11, longest shortcut */ - if (encoding == NULL) { + if (UNLIKELY(encoding == NULL)) { return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL); } + /* [jart] faster path based on profiling */ + if (encoding[0] == 'l' && + encoding[1] == 'a' && + encoding[2] == 't' && + encoding[3] == 'i' && + encoding[4] == 'n' && + (encoding[5] == '1' || + ((encoding[5] == '-' || + encoding[5] == '_') && + encoding[6] == '1'))) { + return PyUnicode_DecodeLatin1(s, size, errors); + } + /* Shortcuts for common default encodings */ if (_Py_normalize_encoding(encoding, buflower, sizeof(buflower))) { char *lower = buflower; - /* Fast paths */ if (lower[0] == 'u' && lower[1] == 't' && lower[2] == 'f') { lower += 3; @@ -3309,7 +3322,6 @@ PyUnicode_Decode(const char *s, /* Match "utf8" and "utf_8" */ lower++; } - if (lower[0] == '8' && lower[1] == 0) { return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL); } diff --git a/third_party/python/python.mk b/third_party/python/python.mk index 5ee6f9bc4..b0036d69c 100644 --- a/third_party/python/python.mk +++ b/third_party/python/python.mk @@ -1319,6 +1319,7 @@ THIRD_PARTY_PYTHON_PYTEST_A_DATA = \ third_party/python/Lib/venv/scripts/nt/deactivate.bat \ third_party/python/Lib/venv/scripts/posix/activate.csh \ third_party/python/Lib/venv/scripts/posix/activate.fish \ + third_party/python/Lib/test/hello.com \ third_party/python/Lib/test/xmltestdata/ \ third_party/python/Lib/test/xmltestdata/simple.xml \ third_party/python/Lib/test/xmltestdata/simple-ns.xml \ @@ -1808,6 +1809,7 @@ THIRD_PARTY_PYTHON_PYTEST_PYMAINS = \ third_party/python/Lib/test/test_mimetypes.py \ third_party/python/Lib/test/test_hashlib.py \ third_party/python/Lib/test/test_kdf.py \ + third_party/python/Lib/test/test_cosmo.py \ third_party/python/Lib/test/test_scratch.py \ third_party/python/Lib/test/test_complex.py \ third_party/python/Lib/test/test_funcattrs.py \ @@ -2561,6 +2563,10 @@ o/$(MODE)/third_party/python/Lib/test/test_kdf.py.runs: \ o/$(MODE)/third_party/python/pythontester.com @$(COMPILE) -ACHECK -tT$@ $(PYHARNESSARGS) $< -m test.test_kdf $(PYTESTARGS) +o/$(MODE)/third_party/python/Lib/test/test_cosmo.py.runs: \ + o/$(MODE)/third_party/python/pythontester.com + @$(COMPILE) -ACHECK -tT$@ $(PYHARNESSARGS) $< -m test.test_cosmo $(PYTESTARGS) + o/$(MODE)/third_party/python/Lib/test/test_scratch.py.runs: \ o/$(MODE)/third_party/python/pythontester.com @$(COMPILE) -ACHECK -tT$@ $(PYHARNESSARGS) $< -m test.test_scratch $(PYTESTARGS) @@ -3750,6 +3756,10 @@ o/$(MODE)/third_party/python/Lib/test/test_baseexception.o: PYFLAGS += -Y.python o/$(MODE)/third_party/python/Lib/test/test_cmath.o: PYFLAGS += -Y.python/test/ieee754.txt o/$(MODE)/third_party/python/Lib/test/test_difflib.o: PYFLAGS += -Y.python/test/test_difflib_expect.html +o/$(MODE)/third_party/python/Lib/test/test_cosmo.o: \ + PYFLAGS += \ + -Y.python/test/hello.com + o/$(MODE)/third_party/python/Lib/test/test_math.o: \ PYFLAGS += \ -Y.python/test/ieee754.txt \ diff --git a/tool/build/compile.c b/tool/build/compile.c index de1199f56..2958dc6a7 100644 --- a/tool/build/compile.c +++ b/tool/build/compile.c @@ -139,6 +139,7 @@ bool wantrecord; bool fulloutput; bool touchtarget; bool inarticulate; +bool wantnoredzone; bool stdoutmustclose; bool no_sanitize_null; bool no_sanitize_alignment; @@ -749,6 +750,10 @@ int main(int argc, char *argv[]) { wantframe = true; } else if (!strcmp(argv[i], "-fomit-frame-pointer")) { wantframe = false; + } else if (!strcmp(argv[i], "-mno-red-zone")) { + wantnoredzone = true; + } else if (!strcmp(argv[i], "-mred-zone")) { + wantnoredzone = false; } else if (!strcmp(argv[i], "-mno-vzeroupper")) { if (isgcc) { AddArg("-Wa,-msse2avx"); @@ -864,8 +869,13 @@ int main(int argc, char *argv[]) { if (no_sanitize_pointer_overflow) { AddArg("-fno-sanitize=pointer-overflow"); } + if (wantnoredzone) { + AddArg("-mno-red-zone"); + AddArg("-D__MNO_RED_ZONE__"); + } if (wantframe) { AddArg("-fno-omit-frame-pointer"); + AddArg("-D__FNO_OMIT_FRAME_POINTER__"); } } diff --git a/tool/build/lib/getargs.c b/tool/build/lib/getargs.c index 917e9ce04..07fb4df03 100644 --- a/tool/build/lib/getargs.c +++ b/tool/build/lib/getargs.c @@ -117,7 +117,7 @@ const char *getargs_next(struct GetArgs *ga) { } } k = 0; -#if defined(__x86__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) +#if defined(__SSE2__) && defined(__GNUC__) && !defined(__STRICT_ANSI__) typedef unsigned char xmm_t __attribute__((__vector_size__(16), __aligned__(1))); for (; ga->j + k + 16 <= ga->mapsize; k += 16) { diff --git a/tool/emacs/cosmo-cpp-constants.el b/tool/emacs/cosmo-cpp-constants.el index 7c20fa489..c9d6e0337 100644 --- a/tool/emacs/cosmo-cpp-constants.el +++ b/tool/emacs/cosmo-cpp-constants.el @@ -160,8 +160,10 @@ "__MNO_VZEROUPPER__" "__FSANITIZE_ADDRESS__" "__FSANITIZE_UNDEFINED__" + "__MNO_RED_ZONE__" "__MNOP_MCOUNT__" - "__MRECORD_MCOUNT__")) + "__MRECORD_MCOUNT__" + "__FNO_OMIT_FRAME_POINTER__")) (defconst cosmo-cpp-constants (append cosmo-cpp-constants-c11 diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 9b7975188..a3b226532 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -1847,7 +1847,7 @@ static bool OpenZip(bool force) { if ((m = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED) { n = st.st_size; - if (endswith(zpath, ".com.dbg") && (p = memmem(m, n, "MZqFpD", 6))) { + if ((p = FindEmbeddedApe(m, n))) { b = p; n -= p - m; } else {