From 578cb215914677fbbf4005c1985fcc44b1165ff0 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Fri, 13 May 2022 13:31:21 -0700 Subject: [PATCH] Add syscalls to Blinkenlights and fix bugs --- libc/log/startfatal.c | 4 +- libc/log/verr.c | 6 ++- libc/log/vflogf.c | 3 +- libc/nexgen32e/program_invocation_name.S | 7 ++- libc/runtime/mmap.c | 1 + libc/runtime/paginate.c | 3 +- libc/runtime/pc.internal.h | 21 ++++---- libc/runtime/program_invocation_short_name.S | 7 ++- libc/sock/syslog.c | 3 +- libc/stdio/tmpfile.c | 3 +- libc/str/{strsignal.c => strsignal.greg.c} | 35 +++++++++---- libc/testlib/showerror.c | 4 +- libc/testlib/testmain.c | 18 +++++-- test/libc/calls/ftruncate_test.c | 5 +- test/libc/calls/setrlimit_test.c | 2 +- test/libc/str/strsignal_test.c | 2 +- third_party/getopt/getopt.c | 6 ++- third_party/make/getprogname.c | 3 +- third_party/mbedtls/test/lib.c | 5 +- tool/build/lib/fds.c | 13 ++--- tool/build/lib/loader.c | 11 ++-- tool/build/lib/memory.c | 55 +++++++++++--------- tool/build/lib/memorymalloc.c | 45 ++++++++-------- tool/build/lib/syscall.c | 28 ++++++++-- tool/viz/printvideo.c | 5 +- 25 files changed, 187 insertions(+), 108 deletions(-) rename libc/str/{strsignal.c => strsignal.greg.c} (82%) diff --git a/libc/log/startfatal.c b/libc/log/startfatal.c index 599b1bd22..4c1432037 100644 --- a/libc/log/startfatal.c +++ b/libc/log/startfatal.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/safemacros.internal.h" #include "libc/intrin/kprintf.h" #include "libc/log/color.internal.h" #include "libc/log/internal.h" @@ -30,5 +31,6 @@ relegated void __start_fatal(const char *file, int line) { __restore_tty(); kprintf("%r%serror%s:%s:%d:%s%s: ", !__nocolor ? "\e[J\e[30;101m" : "", !__nocolor ? "\e[94;49m" : "", file, line, - program_invocation_short_name, !__nocolor ? "\e[0m" : ""); + firstnonnull(program_invocation_short_name, "unknown"), + !__nocolor ? "\e[0m" : ""); } diff --git a/libc/log/verr.c b/libc/log/verr.c index fc0911ff1..e0ad4a40f 100644 --- a/libc/log/verr.c +++ b/libc/log/verr.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/safemacros.internal.h" #include "libc/log/bsd.h" #include "libc/log/color.internal.h" #include "libc/log/internal.h" @@ -23,8 +24,9 @@ #include "libc/stdio/stdio.h" wontreturn void(verr)(int eval, const char *fmt, va_list va) { - fprintf(stderr, "%s: %s%s%s[%m]: ", program_invocation_name, RED2, "ERROR", - RESET); + fprintf(stderr, + "%s: %s%s%s[%m]: ", firstnonnull(program_invocation_name, "unknown"), + RED2, "ERROR", RESET); if (fmt) (vfprintf)(stderr, fmt, va); fprintf(stderr, "\n"); exit(eval); diff --git a/libc/log/vflogf.c b/libc/log/vflogf.c index ffedd9fac..95f6ec0f3 100644 --- a/libc/log/vflogf.c +++ b/libc/log/vflogf.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" +#include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/strace.internal.h" #include "libc/calls/struct/stat.h" @@ -96,7 +97,7 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f, vflogf_ts.tv_nsec = nsec; localtime_r(&secs, &tm); strcpy(iso8601(buf32, &tm), issamesecond ? "+" : "."); - prog = basename(program_invocation_name); + prog = basename(firstnonnull(program_invocation_name, "unknown")); bufmode = f->bufmode; if (bufmode == _IOLBF) f->bufmode = _IOFBF; if ((fprintf)(f, "%r%c%s%06ld:%s:%d:%.*s:%d] ", "FEWIVDNT"[level & 7], buf32, diff --git a/libc/nexgen32e/program_invocation_name.S b/libc/nexgen32e/program_invocation_name.S index f1910d4d9..8fc010092 100644 --- a/libc/nexgen32e/program_invocation_name.S +++ b/libc/nexgen32e/program_invocation_name.S @@ -18,8 +18,13 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" -// Supplies argv[0] the GNU way. .initbss 300,_init_program_invocation_name +// Supplies argv[0] the GNU way. +// +// If argv[0] isn't supplied, this value will be null. +// +// @see program_invocation_short_name +// @see GetProgramExecutableName() program_invocation_name: .quad 0 .endobj program_invocation_name,globl diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index 47bc1527d..d9e0337ab 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -344,6 +344,7 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags, return MAP_FAILED; } f |= MAP_STACK_openbsd; + needguard = true; } else if (IsLinux()) { // by default MAP_GROWSDOWN will auto-allocate 10mb of pages. it's // supposed to stop growing if an adjacent allocation exists, to diff --git a/libc/runtime/paginate.c b/libc/runtime/paginate.c index c37a00e0b..090d98b4f 100644 --- a/libc/runtime/paginate.c +++ b/libc/runtime/paginate.c @@ -36,7 +36,8 @@ void __paginate(int fd, const char *s) { ((args[0] = commandv("less", progpath, sizeof(progpath))) || (args[0] = commandv("more", progpath, sizeof(progpath))))) { snprintf(tmppath, sizeof(tmppath), "%s%s-%s-%d.txt", kTmpPath, - program_invocation_short_name, "paginate", getpid()); + firstnonnull(program_invocation_short_name, "unknown"), "paginate", + getpid()); if ((tfd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0644)) != -1) { write(tfd, s, strlen(s)); close(tfd); diff --git a/libc/runtime/pc.internal.h b/libc/runtime/pc.internal.h index 88cc32c3b..45ca8d919 100644 --- a/libc/runtime/pc.internal.h +++ b/libc/runtime/pc.internal.h @@ -155,15 +155,18 @@ ││ ││ │││ │ │ ││ ││││││││││ 6666555555555544444444443333333333222222222211111111110000000000 3210987654321098765432109876543210987654321098765432109876543210*/ -#define PAGE_V /* */ 0b000000001 -#define PAGE_RW /* */ 0b000000010 -#define PAGE_U /* */ 0b000000100 -#define PAGE_4KB /* */ 0b010000000 -#define PAGE_2MB /* */ 0b110000000 -#define PAGE_1GB /* */ 0b110000000 -#define PAGE_TA 0x00007ffffffff000 -#define PAGE_PA2 0x00007fffffe00000 -#define PAGE_XD 0x8000000000000000 +#define PAGE_V /* */ 0b000000000001 +#define PAGE_RW /* */ 0b000000000010 +#define PAGE_U /* */ 0b000000000100 +#define PAGE_4KB /* */ 0b000010000000 +#define PAGE_2MB /* */ 0b000110000000 +#define PAGE_1GB /* */ 0b000110000000 +#define PAGE_IGN1 /* */ 0b111000000000 +#define PAGE_RSRV /* blinkenlights reservation */ 0b001000000000 +#define PAGE_GROD /* blinkenlights MAP_GROWSDOWN */ 0b010000000000 +#define PAGE_TA 0x00007ffffffff000 +#define PAGE_PA2 0x00007fffffe00000 +#define PAGE_XD 0x8000000000000000 #if !(__ASSEMBLER__ + __LINKER__ + 0) diff --git a/libc/runtime/program_invocation_short_name.S b/libc/runtime/program_invocation_short_name.S index f6874d53f..cae430d67 100644 --- a/libc/runtime/program_invocation_short_name.S +++ b/libc/runtime/program_invocation_short_name.S @@ -18,8 +18,13 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" -// Supplies basename(argv[0]) The GNU Way. .initbss 400,_init_program_invocation_short_name +// Supplies basename(argv[0]) The GNU Way. +// +// If argv[0] isn't supplied, this value will be null. +// +// @see GetProgramExecutableName() +// @see program_invocation_name program_invocation_short_name: .quad 0 .endobj program_invocation_short_name,globl diff --git a/libc/sock/syslog.c b/libc/sock/syslog.c index 1b325ab2b..9c879aae1 100644 --- a/libc/sock/syslog.c +++ b/libc/sock/syslog.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/weirdtypes.h" #include "libc/dce.h" @@ -288,7 +289,7 @@ void openlog(const char *ident, int opt, int facility) { __initlog(); } if (!ident) { - ident = program_invocation_short_name; + ident = firstnonnull(program_invocation_short_name, "unknown"); } tprecode8to16(log_ident, ARRAYLEN(log_ident), ident); log_opt = opt; diff --git a/libc/stdio/tmpfile.c b/libc/stdio/tmpfile.c index 8ec1a985a..449d6d291 100644 --- a/libc/stdio/tmpfile.c +++ b/libc/stdio/tmpfile.c @@ -36,7 +36,8 @@ FILE *tmpfile(void) { tmp = firstnonnull(getenv("TMPDIR"), kTmpPath); sep = !isempty(tmp) && !endswith(tmp, "/") ? "/" : ""; if ((snprintf)(tpl, PATH_MAX, "%s%stmp.%s.XXXXXX", tmp, sep, - program_invocation_short_name) <= PATH_MAX) { + firstnonnull(program_invocation_short_name, "unknown")) <= + PATH_MAX) { if ((fd = mkostemps(tpl, 0, 0)) != -1) { return fdopen(fd, "w+"); } diff --git a/libc/str/strsignal.c b/libc/str/strsignal.greg.c similarity index 82% rename from libc/str/strsignal.c rename to libc/str/strsignal.greg.c index ea6b0868f..a349ac47c 100644 --- a/libc/str/strsignal.c +++ b/libc/str/strsignal.greg.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" #include "libc/fmt/magnumstrs.internal.h" +#include "libc/log/libfatal.internal.h" #include "libc/macros.internal.h" #include "libc/str/str.h" @@ -26,7 +27,7 @@ static char g_strsignal[12]; /** * Returns string describing signal code. * - * This returns SIGUNKNOWN for 0 which is the empty value. Textual names + * This returns SIGZERO for 0 which is the empty value. Textual names * should be available for signals 1 through 32. Signals in the range 33 * and 128 are returned as a `SIG%03d` string. Everything else is SIGWUT * @@ -34,24 +35,36 @@ static char g_strsignal[12]; * @return pointer to static memory that mutates on subsequent calls * @see sigaction() */ -char *strsignal(int sig) { +noasan noinstrument char *strsignal(int sig) { + char *p; const char *s; - strcpy(g_strsignal, "SIG"); + p = g_strsignal; + p[0] = 'S'; + p[1] = 'I'; + p[2] = 'G'; + p[3] = 0; if (sig) { if ((s = GetMagnumStr(kSignalNames, sig))) { - strcpy(g_strsignal + 3, s); - return g_strsignal; + __stpcpy(p + 3, s); + return p; } } if (!sig) { - strcpy(g_strsignal + 3, "UNKNOWN"); + p[3] = 'Z'; + p[4] = 'E'; + p[5] = 'R'; + p[6] = 'O'; + p[7] = 0; } else if (1 <= sig && sig <= 128) { - g_strsignal[3] = '0' + sig / 100; - g_strsignal[4] = '0' + sig / 10 % 10; - g_strsignal[5] = '0' + sig % 10; - g_strsignal[6] = 0; + p[3] = '0' + sig / 100; + p[4] = '0' + sig / 10 % 10; + p[5] = '0' + sig % 10; + p[6] = 0; } else { - strcpy(g_strsignal + 3, "WUT"); + p[3] = 'W'; + p[4] = 'U'; + p[5] = 'T'; + p[6] = 0; } return g_strsignal; } diff --git a/libc/testlib/showerror.c b/libc/testlib/showerror.c index 6427501d1..d244e0ee4 100644 --- a/libc/testlib/showerror.c +++ b/libc/testlib/showerror.c @@ -88,8 +88,8 @@ testonly void testlib_showerror_(int line, const char *wantcode, } kprintf("\t%s%s%s\n" "\t%s%s @ %s%s\n", - SUBTLE, strerror(e), RESET, SUBTLE, program_invocation_name, hostname, - RESET); + SUBTLE, strerror(e), RESET, SUBTLE, + firstnonnull(program_invocation_name, "unknown"), 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 05fbb3cd9..2893e06cf 100644 --- a/libc/testlib/testmain.c +++ b/libc/testlib/testmain.c @@ -35,6 +35,7 @@ #include "libc/log/log.h" #include "libc/macros.internal.h" #include "libc/mem/mem.h" +#include "libc/nexgen32e/vendor.internal.h" #include "libc/nexgen32e/x86feature.h" #include "libc/runtime/internal.h" #include "libc/runtime/memtrack.internal.h" @@ -71,7 +72,7 @@ static bool runbenchmarks_; void PrintUsage(int rc, FILE *f) { fputs("Usage: ", f); - fputs(program_invocation_name, f); + fputs(firstnonnull(program_invocation_name, "unknown"), f); fputs(USAGE, f); exit(rc); } @@ -102,17 +103,26 @@ static void EmptySignalMask(void) { } static void FixIrregularFds(void) { - int i; + int i, fd; struct pollfd pfds[64]; for (i = 0; i < 3; ++i) { - if (fcntl(0, F_GETFL) == -1) { - CHECK_EQ(0, open("/dev/null", O_RDWR)); + if (fcntl(i, F_GETFL) == -1) { + errno = 0; + fd = open("/dev/null", O_RDWR); + CHECK_NE(-1, fd); + if (fd != i) { + close(fd); + } } } for (i = 0; i < ARRAYLEN(pfds); ++i) { pfds[i].fd = i + 3; pfds[i].events = POLLIN; } + if (IsGenuineCosmo()) { + // TODO(jart): Fix Blinkenlights poll() / close() + return; + } if (poll(pfds, ARRAYLEN(pfds), 0) != -1) { for (i = 0; i < ARRAYLEN(pfds); ++i) { if (pfds[i].revents & POLLNVAL) continue; diff --git a/test/libc/calls/ftruncate_test.c b/test/libc/calls/ftruncate_test.c index 6281845d5..1d075abec 100644 --- a/test/libc/calls/ftruncate_test.c +++ b/test/libc/calls/ftruncate_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" #include "libc/dce.h" @@ -33,7 +34,9 @@ const char *path; TEST(ftruncate, test) { mkdir("o", 0755); mkdir("o/tmp", 0755); - path = gc(xasprintf("o/tmp/%s.%d", program_invocation_short_name, getpid())); + path = gc(xasprintf("o/tmp/%s.%d", + firstnonnull(program_invocation_short_name, "unknown"), + getpid())); ASSERT_NE(-1, (fd = creat(path, 0755))); ASSERT_EQ(5, write(fd, "hello", 5)); errno = 31337; diff --git a/test/libc/calls/setrlimit_test.c b/test/libc/calls/setrlimit_test.c index 1fcf0e440..c0f0aafb6 100644 --- a/test/libc/calls/setrlimit_test.c +++ b/test/libc/calls/setrlimit_test.c @@ -98,7 +98,7 @@ TEST(setrlimit, testFileSizeLimit) { ASSERT_EQ(0, setrlimit(RLIMIT_FSIZE, &rlim)); snprintf(tmpname, sizeof(tmpname), "%s/%s.%d", firstnonnull(getenv("TMPDIR"), "/tmp"), - program_invocation_short_name, getpid()); + firstnonnull(program_invocation_short_name, "unknown"), getpid()); ASSERT_NE(-1, (fd = open(tmpname, O_RDWR | O_CREAT | O_TRUNC))); rngset(junkdata, 512, rand64, -1); for (i = 0; i < 5 * 1024 * 1024 / 512; ++i) { diff --git a/test/libc/str/strsignal_test.c b/test/libc/str/strsignal_test.c index 39fc43897..12c90a0c9 100644 --- a/test/libc/str/strsignal_test.c +++ b/test/libc/str/strsignal_test.c @@ -20,7 +20,7 @@ #include "libc/testlib/testlib.h" TEST(strsignal, test) { - EXPECT_STREQ("SIGUNKNOWN", strsignal(0)); + EXPECT_STREQ("SIGZERO", strsignal(0)); EXPECT_STREQ("SIGINT", strsignal(SIGINT)); EXPECT_STREQ("SIGQUIT", strsignal(SIGQUIT)); EXPECT_STREQ("SIGALRM", strsignal(SIGALRM)); diff --git a/third_party/getopt/getopt.c b/third_party/getopt/getopt.c index a1151abfa..86e65d96d 100644 --- a/third_party/getopt/getopt.c +++ b/third_party/getopt/getopt.c @@ -79,8 +79,10 @@ hidden char *getopt_place; char kGetoptEmsg[1] hidden; static void getopt_print_badch(const char *s) { - fputs(program_invocation_name, stderr); - fputs(": ", stderr); + if (program_invocation_name) { + fputs(program_invocation_name, stderr); + fputs(": ", stderr); + } fputs(s, stderr); fputs(" -- ", stderr); fputc(optopt, stderr); diff --git a/third_party/make/getprogname.c b/third_party/make/getprogname.c index cd183fa6f..861330f07 100644 --- a/third_party/make/getprogname.c +++ b/third_party/make/getprogname.c @@ -17,12 +17,13 @@ /* clang-format off */ #include "third_party/make/config.h" #include "third_party/make/getprogname.h" +#include "libc/bits/safemacros.internal.h" #include "third_party/make/dirname.h" char const * getprogname (void) { - return program_invocation_short_name; + return firstnonnull(program_invocation_short_name, "unknown"); } /* diff --git a/third_party/mbedtls/test/lib.c b/third_party/mbedtls/test/lib.c index 2d6532367..95decc083 100644 --- a/third_party/mbedtls/test/lib.c +++ b/third_party/mbedtls/test/lib.c @@ -16,6 +16,7 @@ */ #include "libc/assert.h" #include "libc/bits/bits.h" +#include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/dce.h" #include "libc/fmt/conv.h" @@ -1011,8 +1012,8 @@ int execute_tests(int argc, const char **argv, const char *default_filename) { file = fopen(test_filename, "r"); if (file == NULL) { WRITE("%s (%s) failed to open test file: %s %m\n", - program_invocation_short_name, GetProgramExecutableName(), - test_filename); + firstnonnull(program_invocation_short_name, "unknown"), + GetProgramExecutableName(), test_filename); if (outcome_file != NULL) fclose(outcome_file); return 1; } diff --git a/tool/build/lib/fds.c b/tool/build/lib/fds.c index 9e1159f1a..d30fe1a2f 100644 --- a/tool/build/lib/fds.c +++ b/tool/build/lib/fds.c @@ -25,26 +25,21 @@ int MachineFdAdd(struct MachineFds *mf) { int fd; struct MachineFdClosed *closed; if ((closed = mf->closed)) { - DCHECK_LT(closed->fd, mf->i); fd = closed->fd; mf->closed = closed->next; free(closed); } else { - DCHECK_LE(mf->i, mf->n); - if (mf->i == mf->n) { - if (!__grow(&mf->p, &mf->n, sizeof(struct MachineFd), 0)) { - return -1; - } + fd = mf->i; + if (mf->i++ == mf->n) { + mf->n = mf->i + (mf->i >> 1); + mf->p = realloc(mf->p, mf->n * sizeof(*mf->p)); } - fd = mf->i++; } return fd; } void MachineFdRemove(struct MachineFds *mf, int fd) { struct MachineFdClosed *closed; - DCHECK_GE(fd, 0); - DCHECK_LT(fd, mf->i); mf->p[fd].cb = NULL; if ((closed = malloc(sizeof(struct MachineFdClosed)))) { closed->fd = fd; diff --git a/tool/build/lib/loader.c b/tool/build/lib/loader.c index 78e622030..ac204c7c5 100644 --- a/tool/build/lib/loader.c +++ b/tool/build/lib/loader.c @@ -25,6 +25,7 @@ #include "libc/log/log.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/vendor.internal.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/sysv/consts/fileno.h" @@ -65,9 +66,12 @@ static void LoadElfLoadSegment(struct Machine *m, void *code, size_t codesize, CHECK_GE(vend - vstart, fstart - fend); CHECK_LE(phdr->p_filesz, phdr->p_memsz); CHECK_EQ(felf + phdr->p_offset - fstart, phdr->p_vaddr - vstart); - CHECK_NE(-1, ReserveVirtual(m, vstart, fend - fstart, 0x0207)); + CHECK_NE(-1, ReserveVirtual(m, vstart, fend - fstart, + PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV)); VirtualRecv(m, vstart, (void *)fstart, fend - fstart); - if (bsssize) CHECK_NE(-1, ReserveVirtual(m, vbss, bsssize, 0x0207)); + if (bsssize) + CHECK_NE(-1, ReserveVirtual(m, vbss, bsssize, + PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV)); if (phdr->p_memsz - phdr->p_filesz > bsssize) { VirtualSet(m, phdr->p_vaddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz - bsssize); @@ -158,7 +162,8 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars, sp = 0x800000000000; Write64(m->sp, sp); m->cr3 = AllocateLinearPage(m); - CHECK_NE(-1, ReserveVirtual(m, sp - STACKSIZE, STACKSIZE, 0x0207)); + CHECK_NE(-1, ReserveVirtual(m, sp - STACKSIZE, STACKSIZE, + PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV)); LoadArgv(m, prog, args, vars); if (memcmp(elf->map, "\177ELF", 4) == 0) { elf->ehdr = (void *)elf->map; diff --git a/tool/build/lib/memory.c b/tool/build/lib/memory.c index f1c645519..8be0edee4 100644 --- a/tool/build/lib/memory.c +++ b/tool/build/lib/memory.c @@ -46,13 +46,18 @@ void SetWriteAddr(struct Machine *m, int64_t addr, uint32_t size) { } } -uint64_t HandlePageFault(struct Machine *m, uint64_t entry, uint64_t table, - unsigned index) { +uint64_t HandlePageFault(struct Machine *m, int64_t virt, uint64_t entry, + uint64_t table, unsigned index) { long page; if ((page = AllocateLinearPage(m)) != -1) { --m->memstat.reserved; + if (entry & PAGE_GROD) { + ReserveVirtual(m, virt - 4096, 4096, + PAGE_GROD | PAGE_RSRV | + (entry & (PAGE_XD | PAGE_U | PAGE_RW | PAGE_V))); + } return (*(uint64_t *)(m->real.p + table + index * 8) = - page | entry & ~0x7ffffffffe00); + page | entry & ~(PAGE_TA | PAGE_IGN1)); } else { return 0; } @@ -61,7 +66,7 @@ uint64_t HandlePageFault(struct Machine *m, uint64_t entry, uint64_t table, uint64_t FindPage(struct Machine *m, int64_t virt) { uint64_t table, entry; unsigned level, index, i; - virt &= -0x1000; + virt &= -4096; for (i = 0; i < ARRAYLEN(m->tlb); ++i) { if (m->tlb[i].virt == virt && (m->tlb[i].entry & 1)) { return m->tlb[i].entry; @@ -76,8 +81,8 @@ uint64_t FindPage(struct Machine *m, int64_t virt) { entry = *(uint64_t *)(m->real.p + table + index * 8); if (!(entry & 1)) return 0; } while ((level -= 9) >= 12); - if ((entry & 0x0e00) && - (entry = HandlePageFault(m, entry, table, index)) == -1) { + if ((entry & PAGE_RSRV) && + (entry = HandlePageFault(m, virt, entry, table, index)) == -1) { return 0; } m->tlbindex = (m->tlbindex + 1) & (ARRAYLEN(m->tlb) - 1); @@ -113,21 +118,21 @@ void *ResolveAddress(struct Machine *m, int64_t v) { void VirtualSet(struct Machine *m, int64_t v, char c, uint64_t n) { char *p; uint64_t k; - k = 0x1000 - (v & 0xfff); + k = 4096 - (v & 0xfff); while (n) { k = MIN(k, n); p = ResolveAddress(m, v); memset(p, c, k); n -= k; v += k; - k = 0x1000; + k = 4096; } } void VirtualCopy(struct Machine *m, int64_t v, char *r, uint64_t n, bool d) { char *p; uint64_t k; - k = 0x1000 - (v & 0xfff); + k = 4096 - (v & 0xfff); while (n) { k = MIN(k, n); p = ResolveAddress(m, v); @@ -139,7 +144,7 @@ void VirtualCopy(struct Machine *m, int64_t v, char *r, uint64_t n, bool d) { n -= k; r += k; v += k; - k = 0x1000; + k = 4096; } } @@ -165,7 +170,7 @@ void VirtualRecvWrite(struct Machine *m, int64_t addr, void *src, uint64_t n) { void *ReserveAddress(struct Machine *m, int64_t v, size_t n) { void *r; DCHECK_LE(n, sizeof(m->stash)); - if ((v & 0xfff) + n <= 0x1000) return ResolveAddress(m, v); + if ((v & 0xfff) + n <= 4096) return ResolveAddress(m, v); m->stashaddr = v; m->stashsize = n; r = m->stash; @@ -177,11 +182,11 @@ void *AccessRam(struct Machine *m, int64_t v, size_t n, void *p[2], uint8_t *tmp, bool copy) { unsigned k; uint8_t *a, *b; - DCHECK_LE(n, 0x1000); - if ((v & 0xfff) + n <= 0x1000) return ResolveAddress(m, v); - k = 0x1000; + DCHECK_LE(n, 4096); + if ((v & 0xfff) + n <= 4096) return ResolveAddress(m, v); + k = 4096; k -= v & 0xfff; - DCHECK_LE(k, 0x1000); + DCHECK_LE(k, 4096); a = ResolveAddress(m, v); b = ResolveAddress(m, v + k); if (copy) { @@ -220,9 +225,9 @@ void *BeginLoadStore(struct Machine *m, int64_t v, size_t n, void *p[2], void EndStore(struct Machine *m, int64_t v, size_t n, void *p[2], uint8_t *b) { uint8_t *a; unsigned k; - DCHECK_LE(n, 0x1000); - if ((v & 0xfff) + n <= 0x1000) return; - k = 0x1000; + DCHECK_LE(n, 4096); + if ((v & 0xfff) + n <= 4096) return; + k = 4096; k -= v & 0xfff; DCHECK_GT(k, n); DCHECK_NOTNULL(p[0]); @@ -239,7 +244,7 @@ void EndStoreNp(struct Machine *m, int64_t v, size_t n, void *p[2], void *LoadStr(struct Machine *m, int64_t addr) { size_t have; char *copy, *page, *p; - have = 0x1000 - (addr & 0xfff); + have = 4096 - (addr & 0xfff); if (!addr) return NULL; if (!(page = FindReal(m, addr))) return NULL; if ((p = memchr(page, '\0', have))) { @@ -247,16 +252,16 @@ void *LoadStr(struct Machine *m, int64_t addr) { return page; } CHECK_LT(m->freelist.i, ARRAYLEN(m->freelist.p)); - if (!(copy = malloc(have + 0x1000))) return NULL; + if (!(copy = malloc(have + 4096))) return NULL; memcpy(copy, page, have); for (;;) { if (!(page = FindReal(m, addr + have))) break; - if ((p = memccpy(copy + have, page, '\0', 0x1000))) { + if ((p = memccpy(copy + have, page, '\0', 4096))) { SetReadAddr(m, addr, have + (p - (copy + have)) + 1); return (m->freelist.p[m->freelist.i++] = copy); } - have += 0x1000; - if (!(p = realloc(copy, have + 0x1000))) break; + have += 4096; + if (!(p = realloc(copy, have + 4096))) break; copy = p; } free(copy); @@ -266,7 +271,7 @@ void *LoadStr(struct Machine *m, int64_t addr) { void *LoadBuf(struct Machine *m, int64_t addr, size_t size) { size_t have, need; char *buf, *copy, *page; - have = 0x1000 - (addr & 0xfff); + have = 4096 - (addr & 0xfff); if (!addr) return NULL; if (!(buf = FindReal(m, addr))) return NULL; if (size > have) { @@ -274,7 +279,7 @@ void *LoadBuf(struct Machine *m, int64_t addr, size_t size) { if (!(copy = malloc(size))) return NULL; buf = memcpy(copy, buf, have); do { - need = MIN(0x1000, size - have); + need = MIN(4096, size - have); if ((page = FindReal(m, addr + have))) { memcpy(copy + have, page, need); have += need; diff --git a/tool/build/lib/memorymalloc.c b/tool/build/lib/memorymalloc.c index 1fa78a010..4b80216b9 100644 --- a/tool/build/lib/memorymalloc.c +++ b/tool/build/lib/memorymalloc.c @@ -21,6 +21,7 @@ #include "libc/log/check.h" #include "libc/log/log.h" #include "libc/mem/mem.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "libc/sysv/errfuns.h" @@ -66,7 +67,7 @@ void ResetMem(struct Machine *m) { long AllocateLinearPage(struct Machine *m) { long page; if ((page = AllocateLinearPageRaw(m)) != -1) { - bzero(m->real.p + page, 0x1000); + bzero(m->real.p + page, 4096); } return page; } @@ -77,12 +78,12 @@ long AllocateLinearPageRaw(struct Machine *m) { struct MachineRealFree *rf; if ((rf = m->realfree)) { DCHECK(rf->n); - DCHECK_EQ(0, rf->i & 0xfff); - DCHECK_EQ(0, rf->n & 0xfff); + DCHECK_EQ(0, rf->i & 4095); + DCHECK_EQ(0, rf->n & 4095); DCHECK_LE(rf->i + rf->n, m->real.i); i = rf->i; - rf->i += 0x1000; - if (!(rf->n -= 0x1000)) { + rf->i += 4096; + if (!(rf->n -= 4096)) { m->realfree = rf->next; free(rf); } @@ -96,9 +97,9 @@ long AllocateLinearPageRaw(struct Machine *m) { if (n) { n += n >> 1; } else { - n = 0x10000; + n = 65536; } - n = ROUNDUP(n, 0x1000); + n = ROUNDUP(n, 4096); if ((p = realloc(p, n))) { m->real.p = p; m->real.n = n; @@ -108,10 +109,10 @@ long AllocateLinearPageRaw(struct Machine *m) { return -1; } } - DCHECK_EQ(0, i & 0xfff); - DCHECK_EQ(0, n & 0xfff); - DCHECK_LE(i + 0x1000, n); - m->real.i += 0x1000; + DCHECK_EQ(0, i & 4095); + DCHECK_EQ(0, n & 4095); + DCHECK_LE(i + 4096, n); + m->real.i += 4096; ++m->memstat.allocated; } ++m->memstat.committed; @@ -130,7 +131,7 @@ static void MachineWrite64(struct Machine *m, unsigned long i, uint64_t x) { int ReserveReal(struct Machine *m, size_t n) { uint8_t *p; - DCHECK_EQ(0, n & 0xfff); + DCHECK_EQ(0, n & 4095); if (m->real.n < n) { if ((p = realloc(m->real.p, n))) { m->real.p = p; @@ -148,9 +149,9 @@ int ReserveVirtual(struct Machine *m, int64_t virt, size_t size, uint64_t key) { int64_t ti, mi, pt, end, level; for (end = virt + size;;) { for (pt = m->cr3, level = 39; level >= 12; level -= 9) { - pt = pt & 0x7ffffffff000; + pt = pt & PAGE_TA; ti = (virt >> level) & 511; - mi = (pt & 0x7ffffffff000) + ti * 8; + mi = (pt & PAGE_TA) + ti * 8; pt = MachineRead64(m, mi); if (level > 12) { if (!(pt & 1)) { @@ -165,7 +166,7 @@ int ReserveVirtual(struct Machine *m, int64_t virt, size_t size, uint64_t key) { MachineWrite64(m, mi, key); ++m->memstat.reserved; } - if ((virt += 0x1000) >= end) return 0; + if ((virt += 4096) >= end) return 0; if (++ti == 512) break; pt = MachineRead64(m, (mi += 8)); } @@ -179,13 +180,13 @@ int64_t FindVirtual(struct Machine *m, int64_t virt, size_t size) { do { if (virt >= 0x800000000000) return enomem(); for (pt = m->cr3, i = 39; i >= 12; i -= 9) { - pt = MachineRead64(m, (pt & 0x7ffffffff000) + ((virt >> i) & 511) * 8); + pt = MachineRead64(m, (pt & PAGE_TA) + ((virt >> i) & 511) * 8); if (!(pt & 1)) break; } if (i >= 12) { got += 1ull << i; } else { - virt += 0x1000; + virt += 4096; got = 0; } } while (got < size); @@ -195,10 +196,10 @@ int64_t FindVirtual(struct Machine *m, int64_t virt, size_t size) { static void AppendRealFree(struct Machine *m, uint64_t real) { struct MachineRealFree *rf; if (m->realfree && real == m->realfree->i + m->realfree->n) { - m->realfree->n += 0x1000; + m->realfree->n += 4096; } else if ((rf = malloc(sizeof(struct MachineRealFree)))) { rf->i = real; - rf->n = 0x1000; + rf->n = 4096; rf->next = m->realfree; m->realfree = rf; } @@ -208,17 +209,17 @@ int FreeVirtual(struct Machine *m, int64_t base, size_t size) { uint64_t i, mi, pt, end, virt; for (virt = base, end = virt + size; virt < end; virt += 1ull << i) { for (pt = m->cr3, i = 39;; i -= 9) { - mi = (pt & 0x7ffffffff000) + ((virt >> i) & 511) * 8; + mi = (pt & PAGE_TA) + ((virt >> i) & 511) * 8; pt = MachineRead64(m, mi); if (!(pt & 1)) { break; } else if (i == 12) { ++m->memstat.freed; - if (pt & 0x0e00) { + if (pt & PAGE_RSRV) { --m->memstat.reserved; } else { --m->memstat.committed; - AppendRealFree(m, pt & 0x7ffffffff000); + AppendRealFree(m, pt & PAGE_TA); } MachineWrite64(m, mi, 0); break; diff --git a/tool/build/lib/syscall.c b/tool/build/lib/syscall.c index f8e4976c6..3960cfd31 100644 --- a/tool/build/lib/syscall.c +++ b/tool/build/lib/syscall.c @@ -37,6 +37,7 @@ #include "libc/mem/mem.h" #include "libc/nexgen32e/vendor.internal.h" #include "libc/runtime/gc.internal.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" #include "libc/sock/select.h" #include "libc/sock/sock.h" @@ -221,6 +222,7 @@ static int XlatMapFlags(int x) { if (x & 2) res |= MAP_PRIVATE; if (x & 16) res |= MAP_FIXED; if (x & 32) res |= MAP_ANONYMOUS; + if (x & 256) res |= MAP_GROWSDOWN; return res; } @@ -522,7 +524,8 @@ static int OpMadvise(struct Machine *m, int64_t addr, size_t length, static int64_t OpBrk(struct Machine *m, int64_t addr) { addr = ROUNDUP(addr, PAGESIZE); if (addr > m->brk) { - if (ReserveVirtual(m, m->brk, addr - m->brk, 0x0207) != -1) { + if (ReserveVirtual(m, m->brk, addr - m->brk, + PAGE_V | PAGE_RW | PAGE_U | PAGE_RSRV) != -1) { m->brk = addr; } } else if (addr < m->brk) { @@ -545,9 +548,10 @@ static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot, VERBOSEF("MMAP%s %012lx %,ld %#x %#x %d %#lx", GetSimulated(), virt, size, prot, flags, fd, offset); if (prot & PROT_READ) { - key = 0x0205; - if (prot & PROT_WRITE) key |= 2; - if (!(prot & PROT_EXEC)) key |= 0x8000000000000000; + key = PAGE_RSRV | PAGE_U | PAGE_V; + if (prot & PROT_WRITE) key |= PAGE_RW; + if (!(prot & PROT_EXEC)) key |= PAGE_XD; + if (flags & 256 /* MAP_GROWSDOWN */) key |= PAGE_GROD; flags = XlatMapFlags(flags); if (fd != -1 && (fd = XlatFd(m, fd)) == -1) return -1; if (!(flags & MAP_FIXED)) { @@ -1127,6 +1131,21 @@ static int OpGetrlimit(struct Machine *m, int resource, int64_t rlimitaddr) { return enosys(); } +static ssize_t OpReadlinkat(struct Machine *m, int dirfd, int64_t pathaddr, + int64_t bufaddr, size_t size) { + char *buf; + ssize_t rc; + const char *path; + if ((dirfd = XlatAfd(m, dirfd)) == -1) return -1; + path = LoadStr(m, pathaddr); + if (!(buf = malloc(size))) return enomem(); + if ((rc = readlinkat(dirfd, path, buf, size)) != -1) { + VirtualRecvWrite(m, bufaddr, buf, rc); + } + free(buf); + return rc; +} + static int64_t OpGetcwd(struct Machine *m, int64_t bufaddr, size_t size) { size_t n; char *buf; @@ -1437,6 +1456,7 @@ void OpSyscall(struct Machine *m, uint32_t rde) { SYSCALL(0x106, OpFstatat(m, di, si, dx, r0)); SYSCALL(0x107, OpUnlinkat(m, di, si, dx)); SYSCALL(0x108, OpRenameat(m, di, si, dx, r0)); + SYSCALL(0x10B, OpReadlinkat(m, di, si, dx, r0)); SYSCALL(0x10D, OpFaccessat(m, di, si, dx, r0)); SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9))); SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0))); diff --git a/tool/viz/printvideo.c b/tool/viz/printvideo.c index 23e21478e..4f332b2dd 100644 --- a/tool/viz/printvideo.c +++ b/tool/viz/printvideo.c @@ -521,7 +521,8 @@ static bool OpenSpeaker(void) { if (sox_) tryspeakerfns_[i++] = TrySox; } snprintf(fifopath_, sizeof(fifopath_), "%s%s.%d.%d.wav", kTmpPath, - program_invocation_short_name, getpid(), count); + firstnonnull(program_invocation_short_name, "unknown"), getpid(), + count); for (i = 0; i < ARRAYLEN(tryspeakerfns_); ++i) { if (tryspeakerfns_[i]) { if (++speakerfails_ <= 2 && tryspeakerfns_[i]()) { @@ -1363,7 +1364,7 @@ static void PrintUsage(int rc, FILE *f) { static void GetOpts(int argc, char *argv[]) { int opt; snprintf(logpath_, sizeof(logpath_), "%s%s.log", kTmpPath, - program_invocation_short_name); + firstnonnull(program_invocation_short_name, "unknown")); while ((opt = getopt(argc, argv, "?34AGSTVYabdfhnpstxyzvL:")) != -1) { switch (opt) { case 'y':