From cb67223051416e05c82cb0f2b212bc63ebe8a758 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Thu, 26 May 2022 23:17:19 -0700 Subject: [PATCH] Add malloc logging tool STATIC_YOINK("enable_memory_log"); --- examples/compress.c | 101 ++++++++-- examples/decompress.c | 10 +- libc/calls/syscall-sysv.internal.h | 3 +- libc/intrin/exit1.greg.c | 6 + libc/log/backtrace2.greg.c | 5 +- libc/log/memlog.c | 297 +++++++++++++++++++++++++++++ libc/nexgen32e/checkstackalign.S | 4 +- libc/runtime/clone.c | 12 +- libc/runtime/getmemtracksize.c | 27 +++ libc/runtime/memtrack.internal.h | 1 + libc/runtime/mmap.c | 17 +- libc/runtime/munmap.c | 6 +- libc/sysv/calls/__sys_gettid.s | 2 + libc/sysv/calls/break.s | 2 - libc/sysv/calls/sys_gettid.s | 2 - libc/sysv/consts.sh | 4 +- libc/sysv/consts/TIOCGPTN.S | 2 +- libc/sysv/consts/TIOCSPTLCK.S | 2 +- libc/sysv/consts/__NR_arch_prctl.S | 2 +- libc/sysv/consts/__NR_gettid.S | 2 +- libc/sysv/syscalls.sh | 5 +- test/libc/nexgen32e/pcmpstr_test.c | 27 +++ test/libc/runtime/mmap_test.c | 18 +- test/libc/runtime/munmap_test.c | 2 +- tool/net/help.txt | 21 +- 25 files changed, 502 insertions(+), 78 deletions(-) create mode 100644 libc/log/memlog.c create mode 100644 libc/runtime/getmemtracksize.c create mode 100644 libc/sysv/calls/__sys_gettid.s delete mode 100644 libc/sysv/calls/break.s delete mode 100644 libc/sysv/calls/sys_gettid.s create mode 100644 test/libc/nexgen32e/pcmpstr_test.c diff --git a/examples/compress.c b/examples/compress.c index 640672b66..58ba9b83f 100644 --- a/examples/compress.c +++ b/examples/compress.c @@ -13,12 +13,37 @@ #include "libc/log/check.h" #include "libc/mem/mem.h" #include "libc/runtime/gc.internal.h" +#include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/sysv/consts/ex.h" +#include "libc/sysv/consts/exit.h" +#include "third_party/getopt/getopt.h" #include "third_party/zlib/zlib.h" #define CHUNK 32768 +#define USAGE \ + " STDOUT\n\ +\n\ +SYNOPSIS\n\ +\n\ + Zlib Compressor\n\ +\n\ +FLAGS\n\ +\n\ + -?\n\ + -h help\n\ + -0 disable compression\n\ + -1 fastest compression\n\ + -4 coolest compression\n\ + -9 maximum compression\n\ + -F fixed strategy (advanced)\n\ + -L filtered strategy (advanced)\n\ + -R run length strategy (advanced)\n\ + -H huffman only strategy (advanced)\n\ +\n" + // clang-format off // make -j8 o//examples && dd if=/dev/urandom count=100 | tee a | o//examples/compress.com | o//examples/decompress.com >b && sha1sum a b /* @@ -35,18 +60,67 @@ # level 9 75016 compress 5.4 MB/s decompress 344 MB/s m= make -j8 MODE=$m o/$m/examples || exit -for level in $(seq 0 9); do - o/$m/examples/compress.com $level /tmp/info >/tmp/comp +for level in $(seq 1 9); do +for strategy in F L R H; do + o/$m/examples/compress.com -$strategy$level /tmp/info >/tmp/comp compspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info) - o/$m/examples/decompress.com $level /tmp/info >/dev/null + o/$m/examples/decompress.com /tmp/info >/dev/null decompspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info) - size=$(o/$m/examples/compress.com $level 1) { - level = atoi(argv[1]); - } else { - level = Z_DEFAULT_COMPRESSION; - } - rc = compressor(0, 1, level); + int rc; + level = Z_DEFAULT_COMPRESSION; + strategy = Z_DEFAULT_STRATEGY; + GetOpts(argc, argv); + rc = compressor(0, 1); if (rc == Z_OK) { return 0; } else { diff --git a/examples/decompress.c b/examples/decompress.c index 657a0a4ed..5d21d99f6 100644 --- a/examples/decompress.c +++ b/examples/decompress.c @@ -33,12 +33,14 @@ m= make -j8 MODE=$m o/$m/examples || exit for level in $(seq 0 9); do - o/$m/examples/compress.com $level /tmp/info >/tmp/comp +for strategy in F L R H; do + o/$m/examples/compress.com -$strategy$level /tmp/info >/tmp/comp compspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info) - o/$m/examples/decompress.com $level /tmp/info >/dev/null + o/$m/examples/decompress.com /tmp/info >/dev/null decompspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info) - size=$(o/$m/examples/compress.com $level p2 && p3[-1] == '\r') --p3; - __write(p1, p2 - p1); + write(2, p1, p2 - p1); got -= p3 - p1; p1 += p3 - p1; } else { - __write(p1, got); + write(2, p1, got); break; } } diff --git a/libc/log/memlog.c b/libc/log/memlog.c new file mode 100644 index 000000000..0b73d4fb5 --- /dev/null +++ b/libc/log/memlog.c @@ -0,0 +1,297 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/bits/atomic.h" +#include "libc/bits/weaken.h" +#include "libc/intrin/kprintf.h" +#include "libc/intrin/spinlock.h" +#include "libc/log/backtrace.internal.h" +#include "libc/log/log.h" +#include "libc/macros.internal.h" +#include "libc/mem/hook/hook.internal.h" +#include "libc/mem/mem.h" +#include "libc/runtime/symbols.internal.h" +#include "libc/sysv/consts/o.h" +#include "third_party/dlmalloc/dlmalloc.h" + +/** + * @fileoverview Malloc Logging + * + * If you put the following in your main file: + * + * STATIC_YOINK("enable_memory_log"); + * + * Then memory allocations with constant backtraces will be logged to + * standard error. The columns printed are + * + * MEM TID OP USAGE PTR OLD SIZE CALLER1 CALLER2 CALLER3 CALLER4 + * + * delimited by spaces. For example, to see peak malloc usage: + * + * ./myprog.com 2>log + * grep ^MEM log | sort -nk4 | tail -n10 + * + * To see the largest allocations: + * + * ./myprog.com 2>log + * grep ^MEM log | grep -v free | sort -nk7 | tail -n10 + */ + +static struct Memlog { + void (*free)(void *); + void *(*malloc)(size_t); + void *(*calloc)(size_t, size_t); + void *(*memalign)(size_t, size_t); + void *(*realloc)(void *, size_t); + void *(*realloc_in_place)(void *, size_t); + size_t (*bulk_free)(void *[], size_t); + struct Allocs { + long i, n, f; + struct Alloc { + void *addr; + long size; + } * p; + } allocs; + long usage; +} __memlog; + +_Alignas(64) static int __memlog_lock_obj; + +static void __memlog_lock(void) { + _spinlock(&__memlog_lock_obj); +} + +static void __memlog_unlock(void) { + _spunlock(&__memlog_lock_obj); +} + +static long __memlog_size(void *p) { + return malloc_usable_size(p) + 16; +} + +static void __memlog_backtrace(struct StackFrame *frame, intptr_t *a, + intptr_t *b, intptr_t *c, intptr_t *d) { + *a = *b = *c = *d = 0; + if (!frame) return; + *a = frame->addr; + if (!(frame = frame->next)) return; + *b = frame->addr; + if (!(frame = frame->next)) return; + *c = frame->addr; + if (!(frame = frame->next)) return; + *d = frame->addr; +} + +static long __memlog_find(void *p) { + long i; + for (i = 0; i < __memlog.allocs.i; ++i) { + if (__memlog.allocs.p[i].addr == p) { + return i; + } + } + return -1; +} + +static void __memlog_insert(void *p) { + long i, n, n2; + struct Alloc *p2; + n = __memlog_size(p); + for (i = __memlog.allocs.f; i < __memlog.allocs.i; ++i) { + if (!__memlog.allocs.p[i].addr) { + __memlog.allocs.p[i].addr = p; + __memlog.allocs.p[i].size = n; + __memlog.usage += n; + return; + } + } + if (i == __memlog.allocs.n) { + p2 = __memlog.allocs.p; + n2 = __memlog.allocs.n; + n2 += 1; + n2 += n2 >> 1; + if ((p2 = dlrealloc(p2, n2 * sizeof(*p2)))) { + __memlog.allocs.p = p2; + __memlog.allocs.n = n2; + } else { + return; + } + } + __memlog.allocs.p[i].addr = p; + __memlog.allocs.p[i].size = n; + __memlog.allocs.i++; + __memlog.usage += n; +} + +static void __memlog_update(void *p2, void *p) { + long i, n; + n = __memlog_size(p2); + for (i = 0; i < __memlog.allocs.i; ++i) { + if (__memlog.allocs.p[i].addr == p) { + __memlog.usage += n - __memlog.allocs.p[i].size; + __memlog.allocs.p[i].addr = p2; + __memlog.allocs.p[i].size = n; + assert(__memlog.usage >= 0); + return; + } + } + assert(!"this corruption"); +} + +static void __memlog_log(struct StackFrame *frame, const char *op, void *res, + void *old, size_t n) { + intptr_t a, b, c, d; + __memlog_backtrace(frame, &a, &b, &c, &d); + kprintf("MEM %6P %7s %12ld %14p %14p %8zu %t %t %t %t\n", op, + atomic_load(&__memlog.usage), res, old, n, a, b, c, d); +} + +static void __memlog_free(void *p) { + long i, n; + if (!p) return; + __memlog_lock(); + if ((i = __memlog_find(p)) != -1) { + n = __memlog.allocs.p[i].size; + __memlog.allocs.p[i].addr = 0; + __memlog.usage -= __memlog.allocs.p[i].size; + __memlog.allocs.f = MIN(__memlog.allocs.f, i); + assert(__memlog.usage >= 0); + } else { + kprintf("memlog could not find %p\n", p); + assert(!"this corruption"); + n = -1; + } + __memlog_unlock(); + assert(__memlog.free); + __memlog.free(p); + __memlog_log(__builtin_frame_address(0), "free", 0, p, n); +} + +static void *__memlog_malloc(size_t n) { + void *res; + assert(__memlog.malloc); + if ((res = __memlog.malloc(n))) { + __memlog_lock(); + __memlog_insert(res); + __memlog_unlock(); + __memlog_log(__builtin_frame_address(0), "malloc", res, 0, n); + } + return res; +} + +static void *__memlog_calloc(size_t n, size_t z) { + void *res; + assert(__memlog.calloc); + if ((res = __memlog.calloc(n, z))) { + __memlog_lock(); + __memlog_insert(res); + __memlog_unlock(); + __memlog_log(__builtin_frame_address(0), "malloc", res, 0, n * z); + } + return res; +} + +static void *__memlog_memalign(size_t l, size_t n) { + void *res; + assert(__memlog.memalign); + if ((res = __memlog.memalign(l, n))) { + __memlog_lock(); + __memlog_insert(res); + __memlog_unlock(); + __memlog_log(__builtin_frame_address(0), "malloc", res, 0, n); + } + return res; +} + +static void *__memlog_realloc_impl(void *p, size_t n, + void *(*f)(void *, size_t), + struct StackFrame *frame) { + void *res; + assert(f); + if ((res = f(p, n))) { + __memlog_lock(); + if (p) { + __memlog_update(res, p); + } else { + __memlog_insert(res); + } + __memlog_unlock(); + __memlog_log(frame, "realloc", res, p, n); + } + return res; +} + +static void *__memlog_realloc(void *p, size_t n) { + return __memlog_realloc_impl(p, n, __memlog.realloc, + __builtin_frame_address(0)); +} + +static void *__memlog_realloc_in_place(void *p, size_t n) { + return __memlog_realloc_impl(p, n, __memlog.realloc_in_place, + __builtin_frame_address(0)); +} + +static size_t __memlog_bulk_free(void *p[], size_t n) { + size_t i; + for (i = 0; i < n; ++i) { + __memlog_free(p[i]); + p[i] = 0; + } + return 0; +} + +static textexit void __memlog_destroy(void) { + __memlog_lock(); + hook_free = __memlog.free; + hook_malloc = __memlog.malloc; + hook_calloc = __memlog.calloc; + hook_realloc = __memlog.realloc; + hook_memalign = __memlog.memalign; + hook_bulk_free = __memlog.bulk_free; + hook_realloc_in_place = __memlog.realloc_in_place; + dlfree(__memlog.allocs.p); + __memlog.allocs.p = 0; + __memlog.allocs.i = 0; + __memlog.allocs.n = 0; + __memlog_unlock(); +} + +static textstartup void __memlog_init(void) { + GetSymbolTable(); + __memlog_lock(); + __memlog.free = hook_free; + hook_free = __memlog_free; + __memlog.malloc = hook_malloc; + hook_malloc = __memlog_malloc; + __memlog.calloc = hook_calloc; + hook_calloc = __memlog_calloc; + __memlog.realloc = hook_realloc; + hook_realloc = __memlog_realloc; + __memlog.memalign = hook_memalign; + hook_memalign = __memlog_memalign; + __memlog.bulk_free = hook_bulk_free; + hook_bulk_free = __memlog_bulk_free; + __memlog.realloc_in_place = hook_realloc_in_place; + hook_realloc_in_place = __memlog_realloc_in_place; + atexit(__memlog_destroy); + __memlog_unlock(); +} + +const void *const enable_memory_log[] initarray = { + __memlog_init, +}; diff --git a/libc/nexgen32e/checkstackalign.S b/libc/nexgen32e/checkstackalign.S index e944f1b38..d7f4173ae 100644 --- a/libc/nexgen32e/checkstackalign.S +++ b/libc/nexgen32e/checkstackalign.S @@ -25,11 +25,11 @@ CheckStackIsAligned: push %rbp mov %rsp,%rbp -/ allocate sixteen bytes +// allocate sixteen bytes push %rax push %rax -/ put a value in it +// put a value in it xorps %xmm0,%xmm0 movaps %xmm0,-16(%rbp) diff --git a/libc/runtime/clone.c b/libc/runtime/clone.c index 35b45eac4..797ccb9f3 100644 --- a/libc/runtime/clone.c +++ b/libc/runtime/clone.c @@ -199,10 +199,11 @@ static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags, wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid; wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid; wt->tls = flags & CLONE_SETTLS ? tls : 0; - _seizelock(&wt->lock); // TODO: How can we get the tid without locking? + wt->lock = 1; if ((rc = bsdthread_create(fn, arg, wt, 0, PTHREAD_START_CUSTOM_XNU)) != -1) { _spinlock(&wt->lock); rc = wt->tid; + _spunlock(&wt->lock); } return rc; } @@ -263,9 +264,7 @@ static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags, // OPEN BESIYATA DISHMAYA int __tfork(struct __tfork *params, size_t psize, struct CloneArgs *wt); -asm(".section\t.privileged,\"ax\",@progbits\n\t" - ".local\t__tfork\n" - "__tfork:\n\t" +asm("__tfork:\n\t" "push\t$8\n\t" "pop\t%rax\n\t" "mov\t%rdx,%r8\n\t" @@ -282,11 +281,10 @@ asm(".section\t.privileged,\"ax\",@progbits\n\t" "and\t$-16,%rsp\n\t" "push\t%rax\n\t" "jmp\tOpenbsdThreadMain\n\t" - ".size\t__tfork,.-__tfork\n\t" - ".previous"); + ".size\t__tfork,.-__tfork\n\t"); __attribute__((__used__, __no_reorder__)) -static privileged wontreturn void +static wontreturn void OpenbsdThreadMain(struct CloneArgs *wt) { wt->func(wt->arg); // we no longer use the stack after this point. however openbsd diff --git a/libc/runtime/getmemtracksize.c b/libc/runtime/getmemtracksize.c new file mode 100644 index 000000000..d47136b33 --- /dev/null +++ b/libc/runtime/getmemtracksize.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/runtime/memtrack.internal.h" + +noasan size_t GetMemtrackSize(struct MemoryIntervals *mm) { + size_t i, n; + for (n = i = 0; i < mm->i; ++i) { + n += ((size_t)(mm->p[i].y - mm->p[i].x) + 1) << 16; + } + return n; +} diff --git a/libc/runtime/memtrack.internal.h b/libc/runtime/memtrack.internal.h index ea64eaec6..25f9616bd 100644 --- a/libc/runtime/memtrack.internal.h +++ b/libc/runtime/memtrack.internal.h @@ -63,6 +63,7 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int, void (*)(struct MemoryIntervals *, int, int)) hidden; void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden; int UntrackMemoryIntervals(void *, size_t) hidden; +size_t GetMemtrackSize(struct MemoryIntervals *); #define IsLegalPointer(p) \ (-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff) diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index 34f5f507f..ede99f154 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -148,14 +148,6 @@ noasan static bool Automap(int count, int align, int *res) { *res + count <= FRAME(kAutomapStart + (kAutomapSize - 1)); } -noasan static size_t GetMemtrackSize(struct MemoryIntervals *mm) { - size_t i, n; - for (n = i = 0; i < mm->i; ++i) { - n += ((size_t)(mm->p[i].y - mm->p[i].x) + 1) << 16; - } - return n; -} - static noasan void *FinishMemory(void *addr, size_t size, int prot, int flags, int fd, int64_t off, int f, int x, int n, struct DirectMap dm) { @@ -491,10 +483,15 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags, noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { void *res; + size_t toto; _spinlock(&_mmi.lock); res = Mmap(addr, size, prot, flags, fd, off); +#if SYSDEBUG + toto = __strace > 0 ? GetMemtrackSize(&_mmi) : 0; +#endif _spunlock(&_mmi.lock); - STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → %p% m", addr, size, - DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off, res); + STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → %p% m (%'zu bytes total)", addr, + size, DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off, res, + toto); return res; } diff --git a/libc/runtime/munmap.c b/libc/runtime/munmap.c index b929d9648..45717017a 100644 --- a/libc/runtime/munmap.c +++ b/libc/runtime/munmap.c @@ -163,9 +163,13 @@ static noasan int Munmap(char *p, size_t n) { */ noasan int munmap(void *p, size_t n) { int rc; + size_t toto; _spinlock(&_mmi.lock); rc = Munmap(p, n); +#if SYSDEBUG + toto = __strace > 0 ? GetMemtrackSize(&_mmi) : 0; +#endif _spunlock(&_mmi.lock); - STRACE("munmap(%.12p, %'zu) → %d% m", p, n, rc); + STRACE("munmap(%.12p, %'zu) → %d% m (%'zu bytes total)", p, n, rc, toto); return rc; } diff --git a/libc/sysv/calls/__sys_gettid.s b/libc/sysv/calls/__sys_gettid.s new file mode 100644 index 000000000..d544db9db --- /dev/null +++ b/libc/sysv/calls/__sys_gettid.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall __sys_gettid,0x13712b1b0101b0ba,globl,hidden diff --git a/libc/sysv/calls/break.s b/libc/sysv/calls/break.s deleted file mode 100644 index f74a2ca91..000000000 --- a/libc/sysv/calls/break.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall break,0xffffff011fffffff,globl diff --git a/libc/sysv/calls/sys_gettid.s b/libc/sysv/calls/sys_gettid.s deleted file mode 100644 index 2e5adf58e..000000000 --- a/libc/sysv/calls/sys_gettid.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sys_gettid,0xfffffffff211e0ba,globl,hidden diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 9edf6a7bb..d73e7614e 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -2054,7 +2054,7 @@ syscon nr __NR_modify_ldt 0x009a 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR_pivot_root 0x009b 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR__sysctl 0x009c 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR_prctl 0x009d 0xfff 0xfff 0xfff 0xfff 0xfff -syscon nr __NR_arch_prctl 0x009e 0xfff 0x00a5 0x00a5 0xfff 0xfff +syscon nr __NR_arch_prctl 0x009e 0x3000003 0x00a5 0x149 0x13d 0xfff # sysarch on freebsd, _lwp_setprivate on netbsd, __set_tcb on openbsd, thread_fast_set_cthread_self on xnu syscon nr __NR_adjtimex 0x009f 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR_umount2 0x00a6 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR_swapon 0x00a7 0x2000055 0x0055 0xfff 0xfff 0xfff @@ -2065,7 +2065,7 @@ syscon nr __NR_iopl 0x00ac 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR_ioperm 0x00ad 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR_init_module 0x00af 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR_delete_module 0x00b0 0xfff 0xfff 0xfff 0xfff 0xfff -syscon nr __NR_gettid 0x00ba 0x200011e 0xfff 0xfff 0xfff 0xfff +syscon nr __NR_gettid 0x00ba 0x0100001b 432 299 311 0xfff # TODO(jart): thread_self_trap vs. gettid? syscon nr __NR_readahead 0x00bb 0xfff 0xfff 0xfff 0xfff 0xfff syscon nr __NR_setxattr 0x00bc 0x20000ec 0xfff 0xfff 0x177 0xfff syscon nr __NR_fsetxattr 0x00be 0x20000ed 0xfff 0xfff 0x179 0xfff diff --git a/libc/sysv/consts/TIOCGPTN.S b/libc/sysv/consts/TIOCGPTN.S index 6bb173cc0..2707eef9a 100644 --- a/libc/sysv/consts/TIOCGPTN.S +++ b/libc/sysv/consts/TIOCGPTN.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon termios,TIOCGPTN,0x80045430,0,0x4004740f,0,0,0 +.syscon pty,TIOCGPTN,0x80045430,0,0x4004740f,0,0,0 diff --git a/libc/sysv/consts/TIOCSPTLCK.S b/libc/sysv/consts/TIOCSPTLCK.S index f780e2c0b..702752b86 100644 --- a/libc/sysv/consts/TIOCSPTLCK.S +++ b/libc/sysv/consts/TIOCSPTLCK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon pty,TIOCSPTLCK,0x40045431,0,0,0,0,-1 +.syscon pty,TIOCSPTLCK,0x40045431,0,0,0,0,0 diff --git a/libc/sysv/consts/__NR_arch_prctl.S b/libc/sysv/consts/__NR_arch_prctl.S index 4d10be436..f6defec8c 100644 --- a/libc/sysv/consts/__NR_arch_prctl.S +++ b/libc/sysv/consts/__NR_arch_prctl.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon nr,__NR_arch_prctl,0x009e,0xfff,0x00a5,0x00a5,0xfff,0xfff +.syscon nr,__NR_arch_prctl,0x009e,0x3000003,0x00a5,0x149,0x13d,0xfff diff --git a/libc/sysv/consts/__NR_gettid.S b/libc/sysv/consts/__NR_gettid.S index d881f58ba..18f1309c6 100644 --- a/libc/sysv/consts/__NR_gettid.S +++ b/libc/sysv/consts/__NR_gettid.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon nr,__NR_gettid,0x00ba,0x200011e,0xfff,0xfff,0xfff,0xfff +.syscon nr,__NR_gettid,0x00ba,0x0100001b,432,299,311,0xfff diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index 4d1e40108..ab51592b0 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -219,7 +219,7 @@ scall iopl 0xfffffffffffff0ac globl scall ioperm 0xfffffffffffff0ad globl scall init_module 0xfffffffffffff0af globl scall delete_module 0xfffffffffffff0b0 globl -scall sys_gettid 0xfffffffff211e0ba globl hidden +scall __sys_gettid 0x13712b1b0101b0ba globl hidden # thread_self_trap (or gettid? on xnu), _lwp_self on netbsd, thr_self on freebsd, getthrid on openbsd scall readahead 0xfffffffffffff0bb globl # consider fadvise() / madvise() scall setxattr 0x177ffffff20ec0bc globl scall fsetxattr 0x179ffffff20ed0be globl @@ -618,10 +618,10 @@ scall workq_open 0xfffffffff216ffff globl scall write_nocancel 0xfffffffff218dfff globl scall writev_nocancel 0xfffffffff219cfff globl #──────────────────────────FREEBSD─────────────────────────── +scall _umtx_op 0xffffff1c6fffffff globl scall abort2 0xffffff1cffffffff globl scall afs3_syscall 0xffffff179fffffff globl scall bindat 0xffffff21afffffff globl -scall break 0xffffff011fffffff globl scall cap_enter 0xffffff204fffffff globl scall cap_fcntls_get 0xffffff219fffffff globl scall cap_fcntls_limit 0xffffff218fffffff globl @@ -816,7 +816,6 @@ scall __acl_aclcheck_link 0xffffff1acfffffff globl scall __mac_syscall 0xfffffffff217dfff globl scall __acl_set_file 0xffffff15cfffffff globl scall __acl_delete_file 0xffffff15ffffffff globl -scall _umtx_op 0xffffff1c6fffffff globl scall __semwait_signal_nocancel 0xfffffffff21a7fff globl scall __old_semwait_signal_nocancel 0xfffffffff2173fff globl scall sctp_peeloff 0xffffff1d7fffffff globl diff --git a/test/libc/nexgen32e/pcmpstr_test.c b/test/libc/nexgen32e/pcmpstr_test.c new file mode 100644 index 000000000..5813fa27b --- /dev/null +++ b/test/libc/nexgen32e/pcmpstr_test.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/nexgen32e/nexgen32e.h" +#include "libc/testlib/testlib.h" + +// pcmpestrm + +/* TEST(pcmpstr, test) { */ +/* EXPECT_EQ(0, pcmpstr()); */ +/* EXPECT_STREQ("", pcmpstr()); */ +/* } */ diff --git a/test/libc/runtime/mmap_test.c b/test/libc/runtime/mmap_test.c index 15e5da374..e6e810bee 100644 --- a/test/libc/runtime/mmap_test.c +++ b/test/libc/runtime/mmap_test.c @@ -357,12 +357,7 @@ int count; void *ptrs[N]; void BenchUnmap(void) { - int i; - for (i = 0; i < count; ++i) { - if (ptrs[i]) { - ASSERT_EQ(0, munmap(ptrs[i], FRAMESIZE)); - } - } + ASSERT_EQ(0, munmap(ptrs[count++], FRAMESIZE)); } void BenchMmapPrivate(void) { @@ -375,16 +370,11 @@ void BenchMmapPrivate(void) { BENCH(mmap, bench) { EZBENCH2("mmap", donothing, BenchMmapPrivate()); - BenchUnmap(); + EZBENCH2("munmap", donothing, BenchUnmap()); } void BenchUnmapLinux(void) { - int i; - for (i = 0; i < count; ++i) { - if (ptrs[i]) { - ASSERT_EQ(0, LinuxMunmap(ptrs[i], FRAMESIZE)); - } - } + ASSERT_EQ(0, LinuxMunmap(ptrs[count++], FRAMESIZE)); } void BenchMmapPrivateLinux(void) { @@ -399,5 +389,5 @@ BENCH(mmap, benchLinux) { void *p; if (!IsLinux()) return; EZBENCH2("mmap (linux)", donothing, BenchMmapPrivateLinux()); - BenchUnmapLinux(); + EZBENCH2("munmap (linux)", donothing, BenchUnmapLinux()); } diff --git a/test/libc/runtime/munmap_test.c b/test/libc/runtime/munmap_test.c index 3cbbafa68..a1309431b 100644 --- a/test/libc/runtime/munmap_test.c +++ b/test/libc/runtime/munmap_test.c @@ -53,8 +53,8 @@ noasan bool MemoryExists(char *p) { sigaction(SIGSEGV, &sa, old + 0); sigaction(SIGBUS, &sa, old + 1); c = atomic_load(p); - sigaction(SIGSEGV, old + 0, 0); sigaction(SIGBUS, old + 1, 0); + sigaction(SIGSEGV, old + 0, 0); return !gotsignal; } diff --git a/tool/net/help.txt b/tool/net/help.txt index dd5430e40..254e2b4b3 100644 --- a/tool/net/help.txt +++ b/tool/net/help.txt @@ -236,12 +236,6 @@ USAGE $ file redbean.com redbean.com: ELF 64-bit LSB executable - redbean contains software licensed ISC, MIT, BSD-2, BSD-3, zlib - which makes it a permissively licensed gift to anyone who might - find it useful. The transitive closure of legalese can be found - inside the binary. redbean also respects your privacy and won't - phone home because your computer is its home. - ──────────────────────────────────────────────────────────────────────────────── SECURITY @@ -1088,7 +1082,7 @@ FUNCTIONS ProgramPrivateKey(pem:str) Same as the -K flag if called from .init.lua, e.g. ProgramPrivateKey(LoadAsset("/.sign.key")) for zip loading or - ProgramPrivateKey(Slurp("/etc/letsencrypt/fullchain.pem")) for + ProgramPrivateKey(Slurp("/etc/letsencrypt/privkey.pem")) for local file system only. ProgramRedirect(code:int,src:str,location:str) @@ -4148,6 +4142,19 @@ UNIX MODULE reflects the value chosen by the underlying operating system. +──────────────────────────────────────────────────────────────────────────────── + +LEGAL + + redbean contains software licensed ISC, MIT, BSD-2, BSD-3, zlib + which makes it a permissively licensed gift to anyone who might + find it useful. The transitive closure of legalese can be found + inside the binary structure, because notice licenses require we + distribute the license along with any software that uses it. By + putting them in the binary, compliance in automated and no need + for further action on the part of the user who is distributing. + + ──────────────────────────────────────────────────────────────────────────────── SEE ALSO