From 6843150e0c6322f50cda0ce59cca0b2e7397a3a7 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Tue, 25 Jul 2023 05:43:04 -0700 Subject: [PATCH] Mint APE Loader v1.4 This change also incorporates more bug fixes and improvements to a wide variety of small things. For example this fixes #860 so Windows console doesn't get corrupted after exit. An system stack memory map issue with aarch64 has been fixed. We no longer use O_NONBLOCK on AF_UNIX sockets. Crash reports on Arm64 will now demangle C++ symbols, even when c++filt isn't available. Most importantly the Apple M1 version of APE Loader is brought up to date by this change. A prebuilt unsigned binary for it is being included in build/bootstrap/. One more thing: retrieving the term dimensions under --strace was causing the stack to become corrupted and now that's been solved too. PSS: We're now including an ELF PT_NOTE for APE in the binaries we build, that has the APE Loader version. --- ape/ape-m1.c | 446 ++++++++++++------ ape/ape.S | 21 +- ape/ape.lds | 6 + ape/apeuninstall.sh | 1 + ape/loader.c | 116 +++-- ape/start.S | 10 + build/bootstrap/ape.elf | Bin 9460 -> 9474 bytes build/bootstrap/ape.macho | Bin 9460 -> 9474 bytes build/bootstrap/ape.silicon | Bin 0 -> 35159 bytes examples/showdown.c | 26 - libc/calls/execve-sysv.c | 4 +- libc/calls/sigaction.c | 2 - libc/calls/struct/winsize.internal.h | 2 +- libc/elf/findelfsectionbyname.c | 12 +- libc/intrin/restorewintty.c | 8 +- libc/log/oncrash_arm64.c | 23 +- libc/nt/struct/imageoptionalheader.internal.h | 24 + libc/runtime/cosmo2.c | 12 +- libc/runtime/winmain.greg.c | 2 +- libc/sock/goodsocket.c | 9 +- libc/sysv/consts/rlimit.h | 1 - net/https/generatehardrandom.c | 7 +- net/turfwar/turfwar.c | 2 +- test/libc/runtime/mmap_test.c | 12 + tool/net/redbean.c | 4 +- 25 files changed, 524 insertions(+), 226 deletions(-) create mode 100755 build/bootstrap/ape.silicon delete mode 100644 examples/showdown.c diff --git a/ape/ape-m1.c b/ape/ape-m1.c index bf615566c..39a657efc 100644 --- a/ape/ape-m1.c +++ b/ape/ape-m1.c @@ -31,6 +31,7 @@ #include #include +#define pagesz 16384 #define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24) #define SYSLIB_VERSION 1 @@ -57,14 +58,14 @@ struct Syslib { dispatch_time_t (*dispatch_walltime)(const struct timespec *, int64_t); }; -#define TROUBLESHOOT 0 - #define ELFCLASS32 1 #define ELFDATA2LSB 1 #define EM_AARCH64 183 #define ET_EXEC 2 +#define ET_DYN 3 #define PT_LOAD 1 #define PT_DYNAMIC 2 +#define PT_INTERP 3 #define EI_CLASS 4 #define EI_DATA 5 #define PF_X 1 @@ -96,15 +97,14 @@ struct Syslib { #define _COMM_PAGE_APRR_WRITE_ENABLE (_COMM_PAGE_START_ADDRESS + 0x110) #define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118) -#define Min(X, Y) ((Y) > (X) ? (X) : (Y)) -#define Roundup(X, K) (((X) + (K)-1) & -(K)) -#define Rounddown(X, K) ((X) & -(K)) +#define MIN(X, Y) ((Y) > (X) ? (X) : (Y)) +#define MAX(X, Y) ((Y) < (X) ? (X) : (Y)) -#define Read32(S) \ +#define READ32(S) \ ((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \ (unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000) -#define Read64(S) \ +#define READ64(S) \ ((unsigned long)(255 & (S)[7]) << 070 | \ (unsigned long)(255 & (S)[6]) << 060 | \ (unsigned long)(255 & (S)[5]) << 050 | \ @@ -144,12 +144,12 @@ struct ElfPhdr { union ElfEhdrBuf { struct ElfEhdr ehdr; - char buf[0x1000]; + char buf[8192]; }; union ElfPhdrBuf { struct ElfPhdr phdr; - char buf[0x1000]; + char buf[4096]; }; struct PathSearcher { @@ -190,29 +190,19 @@ static int StrCmp(const char *l, const char *r) { return (l[i] & 255) - (r[i] & 255); } -static void *MemSet(void *a, int c, unsigned long n) { - char *d = a; - unsigned long i; - for (i = 0; i < n; ++i) { - d[i] = c; +static void Bzero(void *a, unsigned long n) { + long z; + char *p, *e; + p = (char *)a; + e = p + n; + z = 0; + while (p + sizeof(z) <= e) { + __builtin_memcpy(p, &z, sizeof(z)); + p += sizeof(z); } - return d; -} - -static void *MemMove(void *a, const void *b, unsigned long n) { - char *d = a; - unsigned long i; - const char *s = b; - if (d > s) { - for (i = n; i--;) { - d[i] = s[i]; - } - } else { - for (i = 0; i < n; ++i) { - d[i] = s[i]; - } + while (p < e) { + *p++ = 0; } - return d; } static const char *MemChr(const char *s, unsigned char c, unsigned long n) { @@ -224,6 +214,36 @@ static const char *MemChr(const char *s, unsigned char c, unsigned long n) { return 0; } +static void *MemMove(void *a, const void *b, unsigned long n) { + long w; + char *d; + const char *s; + unsigned long i; + d = (char *)a; + s = (const char *)b; + if (d > s) { + while (n >= sizeof(w)) { + n -= sizeof(w); + __builtin_memcpy(&w, s + n, sizeof(n)); + __builtin_memcpy(d + n, &w, sizeof(n)); + } + while (n--) { + d[n] = s[n]; + } + } else { + i = 0; + while (i + sizeof(w) <= n) { + __builtin_memcpy(&w, s + i, sizeof(i)); + __builtin_memcpy(d + i, &w, sizeof(i)); + i += sizeof(w); + } + for (; i < n; ++i) { + d[i] = s[i]; + } + } + return d; +} + static char *GetEnv(char **p, const char *s) { unsigned long i, j; if (p) { @@ -272,19 +292,29 @@ static void Emit(const char *s) { write(2, s, StrLen(s)); } -static void Perror(const char *c, int failed, const char *s) { - char ibuf[21]; - Emit("ape error: "); - Emit(c); - Emit(": "); - Emit(s); - if (failed) { -#include - Emit(" failed errno="); - Itoa(ibuf, errno); - Emit(ibuf); +static long Print(int fd, const char *s, ...) { + int c; + unsigned n; + char b[512]; + __builtin_va_list va; + __builtin_va_start(va, s); + for (n = 0; s; s = __builtin_va_arg(va, const char *)) { + while ((c = *s++)) { + if (n < sizeof(b)) { + b[n++] = c; + } + } } - Emit("\n"); + __builtin_va_end(va); + return write(fd, b, n); +} + +static void Perror(const char *thing, long rc, const char *reason) { + char ibuf[21]; + ibuf[0] = 0; + if (rc) Itoa(ibuf, -rc); + Print(2, "ape error: ", thing, ": ", reason, rc ? " failed w/ errno " : "", + ibuf, "\n", 0l); } __attribute__((__noreturn__)) static void Pexit(const char *c, int failed, @@ -416,72 +446,138 @@ static void pthread_jit_write_protect_np_workaround(int enabled) { pthread_jit_write_protect_np(enabled); return; } - Pexit("ape-m1", 0, "failed to set jit write protection"); + Pexit("ape", 0, "failed to set jit write protection"); } __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd, long *sp, struct ElfEhdr *e, struct ElfPhdr *p, struct Syslib *lib) { - int prot, flags; - long code, codesize; - unsigned long a, b, i; + long rc; + int prot; + int flags; + int found_entry; + unsigned long dynbase; + unsigned long virtmin, virtmax; + unsigned long a, b, c, d, i, j; - code = 0; - codesize = 0; - for (i = e->e_phnum; i--;) { - if (p[i].p_type == PT_DYNAMIC) { - Pexit(exe, 0, "not a static executable"); - } + /* validate elf */ + found_entry = 0; + virtmin = virtmax = 0; + for (i = 0; i < e->e_phnum; ++i) { if (p[i].p_type != PT_LOAD) { continue; } - if (!p[i].p_memsz) { - continue; - } - if (p[i].p_vaddr & 0x3fff) { - Pexit(exe, 0, "APE phdr addr must be 16384-aligned"); - } - if (p[i].p_offset & 0x3fff) { - Pexit(exe, 0, "APE phdr offset must be 16384-aligned"); + if (p[i].p_filesz > p[i].p_memsz) { + Pexit(exe, 0, "ELF p_filesz exceeds p_memsz"); } if ((p[i].p_flags & (PF_W | PF_X)) == (PF_W | PF_X)) { Pexit(exe, 0, "Apple Silicon doesn't allow RWX memory"); } - prot = 0; - flags = MAP_FIXED | MAP_PRIVATE; - if (p[i].p_flags & PF_R) { - prot |= PROT_READ; + if ((p[i].p_vaddr & (pagesz - 1)) != (p[i].p_offset & (pagesz - 1))) { + Pexit(exe, 0, "ELF p_vaddr incongruent w/ p_offset modulo 16384"); } - if (p[i].p_flags & PF_W) { - prot |= PROT_WRITE; + if (p[i].p_vaddr + p[i].p_memsz < p[i].p_vaddr || + p[i].p_vaddr + p[i].p_memsz + (pagesz - 1) < p[i].p_vaddr) { + Pexit(exe, 0, "ELF p_vaddr + p_memsz overflow"); + } + if (p[i].p_offset + p[i].p_filesz < p[i].p_offset || + p[i].p_offset + p[i].p_filesz + (pagesz - 1) < p[i].p_offset) { + Pexit(exe, 0, "ELF p_offset + p_filesz overflow"); + } + a = p[i].p_vaddr & -pagesz; + b = (p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz; + for (j = i + 1; j < e->e_phnum; ++j) { + if (p[j].p_type != PT_LOAD) continue; + c = p[j].p_vaddr & -pagesz; + d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz; + if (MAX(a, c) < MIN(b, d)) { + Pexit(exe, 0, "ELF segments overlap each others virtual memory"); + } } if (p[i].p_flags & PF_X) { - prot |= PROT_EXEC; - code = p[i].p_vaddr; - codesize = p[i].p_filesz; - } - if (p[i].p_filesz) { - if (mmap((char *)p[i].p_vaddr, p[i].p_filesz, prot, flags, fd, - p[i].p_offset) == MAP_FAILED) { - Pexit(exe, -1, "image mmap()"); - } - if ((a = Min(-p[i].p_filesz & 0x3fff, p[i].p_memsz - p[i].p_filesz))) { - MemSet((void *)(p[i].p_vaddr + p[i].p_filesz), 0, a); + if (p[i].p_vaddr <= e->e_entry && + e->e_entry < p[i].p_vaddr + p[i].p_memsz) { + found_entry = 1; } } - if ((b = Roundup(p[i].p_memsz, 0x4000)) > - (a = Roundup(p[i].p_filesz, 0x4000))) { - if (mmap((char *)p[i].p_vaddr + a, b - a, prot, flags | MAP_ANONYMOUS, -1, - 0) == MAP_FAILED) { - Pexit(exe, -1, "bss mmap()"); - } + if (p[i].p_vaddr < virtmin) { + virtmin = p[i].p_vaddr; + } + if (p[i].p_vaddr + p[i].p_memsz > virtmax) { + virtmax = p[i].p_vaddr + p[i].p_memsz; } } - if (!code) { - Pexit(exe, 0, "ELF needs PT_LOAD phdr w/ PF_X"); + if (!found_entry) { + Pexit(exe, 0, "ELF entrypoint not found in PT_LOAD with PF_X"); } + /* choose loading address for dynamic elf executables + that maintains relative distances between segments */ + if (e->e_type == ET_DYN) { + rc = (long)mmap(0, virtmax - virtmin, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (rc < 0) Pexit(exe, rc, "pie mmap"); + dynbase = rc; + if (dynbase & (pagesz - 1)) { + Pexit(exe, 0, "OS mmap incongruent w/ AT_PAGESZ"); + } + if (dynbase + virtmin < dynbase) { + Pexit(exe, 0, "ELF dynamic base overflow"); + } + } else { + dynbase = 0; + } + + /* load elf */ + for (i = 0; i < e->e_phnum; ++i) { + if (p[i].p_type != PT_LOAD) continue; + if (!p[i].p_memsz) continue; + + /* configure mapping */ + prot = 0; + flags = MAP_FIXED | MAP_PRIVATE; + if (p[i].p_flags & PF_R) prot |= PROT_READ; + if (p[i].p_flags & PF_W) prot |= PROT_WRITE; + if (p[i].p_flags & PF_X) prot |= PROT_EXEC; + + /* load from file */ + if (p[i].p_filesz) { + void *addr; + int prot1, prot2; + unsigned long size; + prot1 = prot; + prot2 = prot; + a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */ + b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */ + c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */ + if (b > c) b = c; + if (c > b && (~prot1 & PROT_WRITE)) { + prot1 = PROT_READ | PROT_WRITE; + } + addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz)); + size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz; + rc = (long)mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz); + if (rc < 0) Pexit(exe, rc, "prog mmap"); + if (c > b) Bzero((void *)(dynbase + a), b - a); + if (prot2 != prot1) { + rc = mprotect(addr, size, prot2); + if (rc < 0) Pexit(exe, rc, "prog mprotect"); + } + } + + /* allocate extra bss */ + a = p[i].p_vaddr + p[i].p_filesz; + a = (a + (pagesz - 1)) & -pagesz; + b = p[i].p_vaddr + p[i].p_memsz; + if (b > a) { + flags |= MAP_ANONYMOUS; + rc = (long)mmap((void *)(dynbase + a), b - a, prot, flags, -1, 0); + if (rc < 0) Pexit(exe, rc, "bss mmap"); + } + } + + /* finish up */ close(fd); register long *x0 asm("x0") = sp; @@ -523,39 +619,116 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd, __builtin_unreachable(); } -static void TryElf(struct ApeLoader *M, const char *exe, int fd, long *sp, - long *bp, char *execfn) { +static const char *TryElf(struct ApeLoader *M, const char *exe, int fd, + long *sp, long *bp, char *execfn) { + long i, rc; unsigned size; - if (Read32(M->ehdr.buf) == Read32("\177ELF") && // - M->ehdr.ehdr.e_type == ET_EXEC && // - M->ehdr.ehdr.e_machine == EM_AARCH64 && // - M->ehdr.ehdr.e_ident[EI_CLASS] != ELFCLASS32 && // - M->ehdr.ehdr.e_phentsize >= sizeof(M->phdr.phdr) && // - (size = (unsigned)M->ehdr.ehdr.e_phnum * M->ehdr.ehdr.e_phentsize) <= - sizeof(M->phdr.buf) && - pread(fd, M->phdr.buf, size, M->ehdr.ehdr.e_phoff) == size) { - long auxv[][2] = { - {AT_PHDR, (long)&M->phdr.phdr}, // - {AT_PHENT, M->ehdr.ehdr.e_phentsize}, // - {AT_PHNUM, M->ehdr.ehdr.e_phnum}, // - {AT_ENTRY, M->ehdr.ehdr.e_entry}, // - {AT_PAGESZ, 0x4000}, // - {AT_UID, getuid()}, // - {AT_EUID, geteuid()}, // - {AT_GID, getgid()}, // - {AT_EGID, getegid()}, // - {AT_HWCAP, 0xffb3ffffu}, // - {AT_HWCAP2, 0x181}, // - {AT_SECURE, issetugid()}, // - {AT_RANDOM, (long)M->rando}, // - {AT_EXECFN, (long)execfn}, // - {0, 0}, // - }; - _Static_assert(sizeof(auxv) == AUXV_BYTES, - "Please update the AUXV_BYTES constant"); - MemMove(bp, auxv, sizeof(auxv)); - Spawn(exe, fd, sp, &M->ehdr.ehdr, &M->phdr.phdr, &M->lib); + struct ElfEhdr *e; + struct ElfPhdr *p; + + /* validate elf header */ + e = &M->ehdr.ehdr; + if (READ32(M->ehdr.buf) != READ32("\177ELF")) { + return "didn't embed ELF magic"; } + if (e->e_ident[EI_CLASS] == ELFCLASS32) { + return "32-bit ELF isn't supported"; + } + if (e->e_type != ET_EXEC && e->e_type != ET_DYN) { + return "ELF not ET_EXEC or ET_DYN"; + } + if (e->e_machine != EM_AARCH64) { + return "couldn't find ELF header with ARM64 machine type"; + } + if (e->e_phentsize != sizeof(struct ElfPhdr)) { + Pexit(exe, 0, "e_phentsize is wrong"); + } + size = e->e_phnum; + if ((size *= sizeof(struct ElfPhdr)) > sizeof(M->phdr.buf)) { + Pexit(exe, 0, "too many ELF program headers"); + } + + /* read program headers */ + rc = pread(fd, M->phdr.buf, size, M->ehdr.ehdr.e_phoff); + if (rc < 0) return "failed to read ELF program headers"; + if (rc != size) return "truncated read of ELF program headers"; + + /* bail on recoverable program header errors */ + p = &M->phdr.phdr; + for (i = 0; i < e->e_phnum; ++i) { + if (p[i].p_type == PT_INTERP) { + return "ELF has PT_INTERP which isn't supported"; + } + if (p[i].p_type == PT_DYNAMIC) { + return "ELF has PT_DYNAMIC which isn't supported"; + } + } + + /* remove empty program headers */ + for (i = 0; i < e->e_phnum;) { + if (p[i].p_type == PT_LOAD && !p[i].p_memsz) { + if (i + 1 < e->e_phnum) { + MemMove(p + i, p + i + 1, + (e->e_phnum - (i + 1)) * sizeof(struct ElfPhdr)); + } + --e->e_phnum; + } else { + ++i; + } + } + + /* + * merge adjacent loads that are contiguous with equal protection, + * which prevents our program header overlap check from needlessly + * failing later on; it also shaves away a microsecond of latency, + * since every program header requires invoking at least 1 syscall + */ + for (i = 0; i + 1 < e->e_phnum;) { + if (p[i].p_type == PT_LOAD && p[i + 1].p_type == PT_LOAD && + ((p[i].p_flags & (PF_R | PF_W | PF_X)) == + (p[i + 1].p_flags & (PF_R | PF_W | PF_X))) && + ((p[i].p_offset + p[i].p_filesz + (pagesz - 1)) & -pagesz) - + (p[i + 1].p_offset & -pagesz) <= + pagesz && + ((p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz) - + (p[i + 1].p_vaddr & -pagesz) <= + pagesz) { + p[i].p_memsz = (p[i + 1].p_vaddr + p[i + 1].p_memsz) - p[i].p_vaddr; + p[i].p_filesz = (p[i + 1].p_offset + p[i + 1].p_filesz) - p[i].p_offset; + if (i + 2 < e->e_phnum) { + MemMove(p + i + 1, p + i + 2, + (e->e_phnum - (i + 2)) * sizeof(struct ElfPhdr)); + } + --e->e_phnum; + } else { + ++i; + } + } + + /* simulate linux auxiliary values */ + long auxv[][2] = { + {AT_PHDR, (long)&M->phdr.phdr}, // + {AT_PHENT, M->ehdr.ehdr.e_phentsize}, // + {AT_PHNUM, M->ehdr.ehdr.e_phnum}, // + {AT_ENTRY, M->ehdr.ehdr.e_entry}, // + {AT_PAGESZ, pagesz}, // + {AT_UID, getuid()}, // + {AT_EUID, geteuid()}, // + {AT_GID, getgid()}, // + {AT_EGID, getegid()}, // + {AT_HWCAP, 0xffb3ffffu}, // + {AT_HWCAP2, 0x181}, // + {AT_SECURE, issetugid()}, // + {AT_RANDOM, (long)M->rando}, // + {AT_EXECFN, (long)execfn}, // + {0, 0}, // + }; + _Static_assert(sizeof(auxv) == AUXV_BYTES, + "Please update the AUXV_BYTES constant"); + MemMove(bp, auxv, sizeof(auxv)); + + /* we're now ready to load */ + Spawn(exe, fd, sp, e, p, &M->lib); } __attribute__((__noinline__)) static long sysret(long rc) { @@ -590,7 +763,7 @@ int main(int argc, char **argv, char **envp) { int c, i, n, fd, rc; struct ApeLoader *M; unsigned char rando[24]; - char *p, *tp, *exe, *prog, *execfn; + char *p, *pe, *tp, *exe, *prog, *execfn; // generate some hard random data if (getentropy(rando, sizeof(rando))) { @@ -673,9 +846,9 @@ int main(int argc, char **argv, char **envp) { argc = sp[3] = sp[0] - 3; argv = (char **)((sp += 3) + 1); } else if (argc < 2) { - Emit("usage: ape-m1 PROG [ARGV1,ARGV2,...]\n" - " ape-m1 - PROG [ARGV0,ARGV1,...]\n" - "actually portable executable loader (apple arm)\n" + Emit("usage: ape PROG [ARGV1,ARGV2,...]\n" + " ape - PROG [ARGV0,ARGV1,...]\n" + "actually portable executable loader silicon 1.4\n" "copyright 2023 justine alexandra roberts tunney\n" "https://justine.lol/ape.html\n"); _exit(1); @@ -692,9 +865,10 @@ int main(int argc, char **argv, char **envp) { Pexit(exe, -1, "open"); } else if ((rc = read(fd, M->ehdr.buf, sizeof(M->ehdr.buf))) < 0) { Pexit(exe, -1, "read"); - } else if (rc != sizeof(M->ehdr.buf)) { + } else if ((unsigned long)rc < sizeof(M->ehdr.ehdr)) { Pexit(exe, 0, "too small"); } + pe = M->ehdr.buf + rc; // resolve argv[0] to reflect path search if (argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) { @@ -713,30 +887,22 @@ int main(int argc, char **argv, char **envp) { // relocate the guest's random numbers MemMove(M->rando, rando, sizeof(M->rando)); - MemSet(rando, 0, sizeof(rando)); - -#if TROUBLESHOOT - for (i = 0; i < argc; ++i) { - Emit("argv = "); - Emit(argv[i]); - Emit("\n"); - } -#endif + Bzero(rando, sizeof(rando)); // ape intended behavior // 1. if file is an elf executable, it'll be used as-is // 2. if ape, will scan shell script for elf printf statements // 3. shell script may have multiple lines producing elf headers - // 4. all elf printf lines must exist in the first 4096 bytes of file + // 4. all elf printf lines must exist in the first 8192 bytes of file // 5. elf program headers may appear anywhere in the binary - if (Read64(M->ehdr.buf) == Read64("MZqFpD='") || - Read64(M->ehdr.buf) == Read64("jartsr='")) { - for (p = M->ehdr.buf; p < M->ehdr.buf + sizeof(M->ehdr.buf); ++p) { - if (Read64(p) != Read64("printf '")) { + if (READ64(M->ehdr.buf) == READ64("MZqFpD='") || + READ64(M->ehdr.buf) == READ64("jartsr='") || + READ64(M->ehdr.buf) == READ64("APEDBG='")) { + for (p = M->ehdr.buf; p < pe; ++p) { + if (READ64(p) != READ64("printf '")) { continue; } - for (i = 0, p += 8; - p + 3 < M->ehdr.buf + sizeof(M->ehdr.buf) && (c = *p++) != '\'';) { + for (i = 0, p += 8; p + 3 < pe && (c = *p++) != '\'';) { if (c == '\\') { if ('0' <= *p && *p <= '7') { c = *p++ - '0'; @@ -751,12 +917,14 @@ int main(int argc, char **argv, char **envp) { } } M->ehdr.buf[i++] = c; + if (i >= sizeof(M->ehdr.buf)) { + break; + } } if (i >= sizeof(M->ehdr.ehdr)) { TryElf(M, exe, fd, sp, bp, execfn); } } } - TryElf(M, exe, fd, sp, bp, execfn); - Pexit(exe, 0, "Not an acceptable APE/ELF executable for AARCH64"); + Pexit(exe, 0, TryElf(M, exe, fd, sp, bp, execfn)); } diff --git a/ape/ape.S b/ape/ape.S index 573bceb6c..41ef92d89 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -610,7 +610,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang // extract the loader into a temp folder, and use it to // load the APE without modifying it. .ascii "[ x\"$1\" != x--assimilate ] && {\n" - .ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.3\"\n" + .ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.4\"\n" .ascii "[ -x \"$t\" ] || {\n" .ascii "mkdir -p \"${t%/*}\" &&\n" .ascii "dd if=\"$o\" of=\"$t.$$\" skip=" @@ -810,6 +810,19 @@ ape_loader_end: .previous #endif /* SupportsSystemv() || SupportsMetal() */ + .section .note.ape.ident,"a",@progbits + .balign 4 +ape.ident: + .long 2f-1f + .long 4f-3f + .long 1 +1: .asciz "APE" +2: .balign 4 +3: .long 104000000 +4: .size ape.ident,.-ape.ident + .type ape.ident,@object + .previous + #if SupportsOpenbsd() .section .note.openbsd.ident,"a",@progbits .balign 4 @@ -1054,8 +1067,8 @@ ape_pe: .ascin "PE",4 .long RVA(ape_pe_entry) // EntryPoint .long 0 // BaseOfCode .quad ape_pe_base // ImageBase - .long 4096 // SectionAlignment - .long 4096 // FileAlignment + .long ape_pe_sectionalignment // SectionAlignment + .long ape_pe_filealignment // FileAlignment .short v_ntversion // MajorOperatingSystemVersion .short 0 // MinorOperatingSystemVersion .short 0 // MajorImageVersion @@ -1064,7 +1077,7 @@ ape_pe: .ascin "PE",4 .short 0 // MinorSubsystemVersion .long 0 // Win32VersionValue .long RVA(_end) // SizeOfImage - .long RVA(_ehead) // SizeOfHeaders + .long ape_pe_sizeofheaders // SizeOfHeaders .long 0 // Checksum .short v_ntsubsystem // Subsystem: 0=Neutral,2=GUI,3=Console .stub v_ntdllchar,short // DllCharacteristics diff --git a/ape/ape.lds b/ape/ape.lds index 0e8e2d91e..34fdfb73b 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -532,6 +532,11 @@ SECTIONS { } } +ape_pe_filealignment = 512; +ape_pe_sectionalignment = 4096; +ape_pe_sizeofheaders = SIZEOF(.head); +ape_pe_sizeofimage = ROUNDUP(_end - __executable_start, ape_pe_sectionalignment); + PFSTUB8(ape_elf_entry, _start); PFSTUB8(ape_elf_phoff, RVA(ape_phdrs)); PFSTUB8(ape_elf_shoff, 0); @@ -720,6 +725,7 @@ CHURN(WinMain); #define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain)) PFSTUB4(ape_pe_offset, ape_pe - ape_mz); ape_pe_optsz = ape_pe_sections - (ape_pe + 24); +ASSERT(ape_pe_optsz % 8 == 0, "SizeOfOptionalHeader must be multiple of 8"); ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40; ape_pe_base = IMAGE_BASE_VIRTUAL; ape_idataz = LINK_WINDOWS ? RVA(ape_idata_iat) : 0; diff --git a/ape/apeuninstall.sh b/ape/apeuninstall.sh index 49889aac6..69a18d568 100755 --- a/ape/apeuninstall.sh +++ b/ape/apeuninstall.sh @@ -36,6 +36,7 @@ rm -f o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape" for x in .ape \ .ape-1.1 \ .ape-1.3 \ + .ape-1.4 \ .ape-blink-0.9.2 \ .ape-blink-1.0.0; do rm -f \ diff --git a/ape/loader.c b/ape/loader.c index 1d8297f4f..a02d675b3 100644 --- a/ape/loader.c +++ b/ape/loader.c @@ -510,8 +510,7 @@ static char SearchPath(struct PathSearcher *ps, const char *suffix) { } static char FindCommand(struct PathSearcher *ps, const char *suffix) { - if (MemChr(ps->name, '/', ps->namelen) || - MemChr(ps->name, '\\', ps->namelen)) { + if (MemChr(ps->name, '/', ps->namelen)) { ps->path[0] = 0; return AccessCommand(ps, suffix, 0); } @@ -556,18 +555,9 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, Pexit(os, exe, 0, "AT_PAGESZ isn't two power"); } for (i = 0; i < e->e_phnum; ++i) { - if (p[i].p_type == PT_INTERP) { - Pexit(os, exe, 0, "ELF has PT_INTERP which isn't supported"); - } - if (p[i].p_type == PT_DYNAMIC) { - Pexit(os, exe, 0, "ELF has PT_DYNAMIC which isn't supported"); - } if (p[i].p_type != PT_LOAD) { continue; } - if (!p[i].p_memsz) { - continue; - } if (p[i].p_filesz > p[i].p_memsz) { Pexit(os, exe, 0, "ELF p_filesz exceeds p_memsz"); } @@ -578,9 +568,9 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, p[i].p_vaddr + p[i].p_memsz + (pagesz - 1) < p[i].p_vaddr) { Pexit(os, exe, 0, "ELF p_vaddr + p_memsz overflow"); } - if (p[i].p_vaddr + p[i].p_filesz < p[i].p_vaddr || - p[i].p_vaddr + p[i].p_filesz + (pagesz - 1) < p[i].p_vaddr) { - Pexit(os, exe, 0, "ELF p_vaddr + p_filesz overflow"); + if (p[i].p_offset + p[i].p_filesz < p[i].p_offset || + p[i].p_offset + p[i].p_filesz + (pagesz - 1) < p[i].p_offset) { + Pexit(os, exe, 0, "ELF p_offset + p_filesz overflow"); } a = p[i].p_vaddr & -pagesz; b = (p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz; @@ -637,7 +627,6 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, /* load elf */ for (i = 0; i < e->e_phnum; ++i) { if (p[i].p_type != PT_LOAD) continue; - if (!p[i].p_memsz) continue; /* configure mapping */ prot = 0; @@ -692,53 +681,122 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, static const char *TryElf(struct ApeLoader *M, const char *exe, int fd, long *sp, long *auxv, unsigned long pagesz, int os) { - long rc; + long i, rc; unsigned size; + struct ElfEhdr *e; + struct ElfPhdr *p; + + /* validate page size */ + if (!pagesz) pagesz = 4096; + if (pagesz & (pagesz - 1)) { + Pexit(os, exe, 0, "AT_PAGESZ isn't two power"); + } + + /* validate elf header */ + e = &M->ehdr.ehdr; if (READ32(M->ehdr.buf) != READ32("\177ELF")) { return "didn't embed ELF magic"; } - if (M->ehdr.ehdr.e_ident[EI_CLASS] == ELFCLASS32) { + if (e->e_ident[EI_CLASS] == ELFCLASS32) { return "32-bit ELF isn't supported"; } - if (M->ehdr.ehdr.e_type != ET_EXEC && M->ehdr.ehdr.e_type != ET_DYN) { + if (e->e_type != ET_EXEC && e->e_type != ET_DYN) { return "ELF not ET_EXEC or ET_DYN"; } - if (M->ehdr.ehdr.e_machine != EM_NEXGEN32E) { + if (e->e_machine != EM_NEXGEN32E) { return "couldn't find ELF header with x86-64 machine type"; } - if (M->ehdr.ehdr.e_phentsize < sizeof(M->phdr.phdr)) { - return "e_phentsize is too small"; + if (e->e_phentsize != sizeof(struct ElfPhdr)) { + Pexit(os, exe, 0, "e_phentsize is wrong"); } - size = M->ehdr.ehdr.e_phnum; - if ((size *= M->ehdr.ehdr.e_phentsize) > sizeof(M->phdr.buf)) { - return "too many ELF program headers"; + size = e->e_phnum; + if ((size *= sizeof(struct ElfPhdr)) > sizeof(M->phdr.buf)) { + Pexit(os, exe, 0, "too many ELF program headers"); } - rc = Pread(fd, M->phdr.buf, size, M->ehdr.ehdr.e_phoff, os); + + /* read program headers */ + rc = Pread(fd, M->phdr.buf, size, e->e_phoff, os); if (rc < 0) return "failed to read ELF program headers"; if (rc != size) return "truncated read of ELF program headers"; + + /* bail on recoverable program header errors */ + p = &M->phdr.phdr; + for (i = 0; i < e->e_phnum; ++i) { + if (p[i].p_type == PT_INTERP) { + return "ELF has PT_INTERP which isn't supported"; + } + if (p[i].p_type == PT_DYNAMIC) { + return "ELF has PT_DYNAMIC which isn't supported"; + } + } + + /* remove empty program headers */ + for (i = 0; i < e->e_phnum;) { + if (p[i].p_type == PT_LOAD && !p[i].p_memsz) { + if (i + 1 < e->e_phnum) { + MemMove(p + i, p + i + 1, + (e->e_phnum - (i + 1)) * sizeof(struct ElfPhdr)); + } + --e->e_phnum; + } else { + ++i; + } + } + + /* + * merge adjacent loads that are contiguous with equal protection, + * which prevents our program header overlap check from needlessly + * failing later on; it also shaves away a microsecond of latency, + * since every program header requires invoking at least 1 syscall + */ + for (i = 0; i + 1 < e->e_phnum;) { + if (p[i].p_type == PT_LOAD && p[i + 1].p_type == PT_LOAD && + ((p[i].p_flags & (PF_R | PF_W | PF_X)) == + (p[i + 1].p_flags & (PF_R | PF_W | PF_X))) && + ((p[i].p_offset + p[i].p_filesz + (pagesz - 1)) & -pagesz) - + (p[i + 1].p_offset & -pagesz) <= + pagesz && + ((p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz) - + (p[i + 1].p_vaddr & -pagesz) <= + pagesz) { + p[i].p_memsz = (p[i + 1].p_vaddr + p[i + 1].p_memsz) - p[i].p_vaddr; + p[i].p_filesz = (p[i + 1].p_offset + p[i + 1].p_filesz) - p[i].p_offset; + if (i + 2 < e->e_phnum) { + MemMove(p + i + 1, p + i + 2, + (e->e_phnum - (i + 2)) * sizeof(struct ElfPhdr)); + } + --e->e_phnum; + } else { + ++i; + } + } + + /* fixup operating system provided auxiliary values */ for (; *auxv; auxv += 2) { switch (*auxv) { case AT_PHDR: auxv[1] = (unsigned long)&M->phdr; break; case AT_PHENT: - auxv[1] = M->ehdr.ehdr.e_phentsize; + auxv[1] = e->e_phentsize; break; case AT_PHNUM: - auxv[1] = M->ehdr.ehdr.e_phnum; + auxv[1] = e->e_phnum; break; default: break; } } - Spawn(os, exe, fd, sp, pagesz, &M->ehdr.ehdr, &M->phdr.phdr); + + /* we're now ready to load */ + Spawn(os, exe, fd, sp, pagesz, e, p); } static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) { Print(os, fd, "NAME\n" "\n" - " actually portable executable loader v1.3\n" + " actually portable executable loader version 1.4\n" " copyright 2023 justine alexandra roberts tunney\n" " https://justine.lol/ape.html\n" "\n" diff --git a/ape/start.S b/ape/start.S index 0c2e5ee80..32b61543f 100644 --- a/ape/start.S +++ b/ape/start.S @@ -49,3 +49,13 @@ netbsd.ident: 3: .long 901000000 4: .size netbsd.ident,.-netbsd.ident .type netbsd.ident,@object + .balign 4 +ape.ident: + .long 2f-1f + .long 4f-3f + .long 1 +1: .asciz "APE" +2: .balign 4 +3: .long 104000000 +4: .size ape.ident,.-ape.ident + .type ape.ident,@object diff --git a/build/bootstrap/ape.elf b/build/bootstrap/ape.elf index 147a981891df3abbd9d8fe853e2904d941974ee2..5c1720dcdb1dcb7eec521434a6ce0a598b02d9b7 100755 GIT binary patch delta 2837 zcmXw54Nw%<9pBwM6b-O<5E2seu?J@cf?6+r?G2c)awl(LuM)*#4fs(DjY7oAAsR_e zT`tY*W;?NK+vzlEXPSvgn&~uCJM|-pIWTAWXRz~LDB$fb^CiuyqUZA zfB*M;|M!2t|Hr%ks{1Nm&f~wo|GtWufn3h{1akLpnKx5No0^oaH>CRRwUpUTd*5^WPfg3vZqjzhxpV<9syepbb%*++An zaFrZLkYLyI`K0NLY#hj8c>RV;?A#Hd8STV+P)Y;&%=;nvi3 zBlK*94h}zTgLl2dpXZJiI%8V&QD=0uxi#95PV^oRF`h#z0Yl<;+d#^Ls4ONl7D-QC zB6M|n>H;yMxSaXC%}^fVn_%O7G5$N8#YmJ@dX3P*aNu7o-O4}-2ZqCeFTsUYQsb#3W5DPY^ThJd&IQdx^NbR}Cgw*~y=>y`xC!h}p!e^o&;0?3Y_t zD*6!_e)4TksKy=wNu#HUuZLh&BH}Xqs;)g7*i9TqeElRiO2mp@66|rz9%N>J3$v=- zqsH`voO)w?pPN~X`dQv0>?}%fu8bJvd8ixQB-nQZbaEka`9(E&N)wlTqS_~j-YpMz zBJ<(wURVvszZ5&mU^#FFW$kgb{YcSm{#ZUX9uZKv8vTbD>OP7ocZ@4TlUpUmLZ_5k z7R8f_-fsu&8C}W2N!wQHV6q-2m3l&ZXtz_;!#ACiRzOYS;8={GgT^^xCOe`MKd^s{ zHHq(<0xq%Uh{W{aZoNMn(;7uQ-iNVHJX|i5U@U|b)34%gieBnR)|_J^Sa8$suFHac ziC5^rn?lsB=%<7?d1rL1SeKYfohyJ=SxPvS8K!47qZ#>Omd!Bq<}Q|13+_Sq zhnd|VQYF@YS2#E*cD@Kjs>TU_rK!#32%jXN-F!Bk1g~$;AbspDK>^)Jr3gKxp(he^ z7mpT5^h=X!aPk9ZS*-Xc;m@#)`4f6+Z<)=d#+Z+FXj5y{O#|#^67yG1mcvUp74u8+ z1nqV_dmXRqaQY1-CS#Nl2Q2z1h$Akv1l1JCuu8j!-?@(Du@P-m|4<%wA!%X1IuxU~lY3dh>9(gWpShN| zWww)#TR6sEHJ$_Kh~&EI9JgjIFy-7@p^UZnz6Qb~ zE+tPjSMnPDPo>$B#wC9-Vfiy>3!UFuRhfkav&FwJsYSnFfk~KW1s7w4gDE zoBCHmM>IMZNF-l(P#>`E$=#6kNg-l*qNT)KR1a*jYRvkBI7gV1W1YrOlw;i#Rbj5z zTJ8zYC}(cbuaf7i1D@ho0bEgNH-g@Vp#KVM2s(QLG&5Jjj2MSF#F-fHj)F)HY2v+R z+ntH17x4K2IDb8ci?9P%sDL6lI?4cTpJ86g<`<{tAES-2bC;mebtc64Iy`v3;E z)>Qylp=mIA!)vv83xq+hb-??GFmKd)&%2Nug_A6I<|{ObxEw9Py_u;&Y=jCK6&MJN zGflsvVb{q89(-h0dKq?zjwIi@X35zbyuXGq<}_41y+PAlC{RtOsX_21UxOJCxQOdPm@U>5C rX>4q5h#nI1OZb@$+gmrcY?T7@79J`qc$J^Qz^%`0Y;LwL`1Ae`PbDTF delta 2496 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 diff --git a/build/bootstrap/ape.silicon b/build/bootstrap/ape.silicon new file mode 100755 index 0000000000000000000000000000000000000000..d918ddea4ec4ff909fb963fa6785d2dd53303dd9 GIT binary patch literal 35159 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 literal 0 HcmV?d00001 diff --git a/examples/showdown.c b/examples/showdown.c deleted file mode 100644 index a56f18a50..000000000 --- a/examples/showdown.c +++ /dev/null @@ -1,26 +0,0 @@ -#if 0 -/*─────────────────────────────────────────────────────────────────╗ -│ To the extent possible under law, Justine Tunney has waived │ -│ all copyright and related or neighboring rights to this file, │ -│ as it is written in the following disclaimers: │ -│ • http://unlicense.org/ │ -│ • http://creativecommons.org/publicdomain/zero/1.0/ │ -╚─────────────────────────────────────────────────────────────────*/ -#endif -#include "libc/calls/calls.h" -#include "libc/calls/struct/iovec.h" -#include "libc/errno.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" - -int main(int argc, char *argv[]) { - char buf[65536]; - memset(buf, '\n', sizeof(buf)); - for (;;) { - ssize_t rc = writev(1, &(struct iovec){buf, sizeof(buf)}, 1); - if (rc != sizeof(buf)) { - printf("got %ld (%s)\n", rc, strerror(errno)); - return 1; - } - } -} diff --git a/libc/calls/execve-sysv.c b/libc/calls/execve-sysv.c index 186f66d4c..e989f9109 100644 --- a/libc/calls/execve-sysv.c +++ b/libc/calls/execve-sysv.c @@ -85,8 +85,8 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) { (CanExecute((ape = "/usr/bin/ape")) || CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"), firstnonnull(getenv("HOME"), ".")), - ".ape-1.3", buf))) || - CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."), ".ape-1.3", + ".ape-1.4", buf))) || + CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."), ".ape-1.4", buf))))) { shargs[0] = ape; shargs[1] = "-"; diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index 35920dc58..84ff0e99f 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -48,8 +48,6 @@ #include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" -#undef sigaction - #ifdef SYSDEBUG STATIC_YOINK("strsignal"); // for kprintf() #endif diff --git a/libc/calls/struct/winsize.internal.h b/libc/calls/struct/winsize.internal.h index 2558b874c..423db93c9 100644 --- a/libc/calls/struct/winsize.internal.h +++ b/libc/calls/struct/winsize.internal.h @@ -8,7 +8,7 @@ COSMOPOLITAN_C_START_ int tcgetwinsize_nt(struct Fd *, struct winsize *); const char *DescribeWinsize(char[64], int, struct winsize *); -#define DescribeWinsize(rc, ws) DescribeWinsize(alloca(12), rc, ws) +#define DescribeWinsize(rc, ws) DescribeWinsize(alloca(64), rc, ws) COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/elf/findelfsectionbyname.c b/libc/elf/findelfsectionbyname.c index c70516afc..5d5a6878a 100644 --- a/libc/elf/findelfsectionbyname.c +++ b/libc/elf/findelfsectionbyname.c @@ -33,11 +33,13 @@ Elf64_Shdr *FindElfSectionByName(Elf64_Ehdr *elf, size_t mapsize, long i; Elf64_Shdr *shdr; const char *secname; - for (i = 0; i < elf->e_shnum; ++i) { - if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) && - (secname = GetElfString(elf, mapsize, shdrstrtab, shdr->sh_name)) && - !strcmp(name, secname)) { - return shdr; + if (shdrstrtab) { + for (i = 0; i < elf->e_shnum; ++i) { + if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) && + (secname = GetElfString(elf, mapsize, shdrstrtab, shdr->sh_name)) && + !strcmp(name, secname)) { + return shdr; + } } } return 0; diff --git a/libc/intrin/restorewintty.c b/libc/intrin/restorewintty.c index 08f924968..e77070891 100644 --- a/libc/intrin/restorewintty.c +++ b/libc/intrin/restorewintty.c @@ -20,6 +20,7 @@ #include "libc/nt/console.h" #include "libc/nt/process.h" #include "libc/nt/runtime.h" +#include "libc/nt/thunk/msabi.h" #include "libc/runtime/internal.h" __msabi extern typeof(GetCurrentProcessId) *const __imp_GetCurrentProcessId; @@ -28,17 +29,18 @@ __msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle; extern uint32_t __pid_exec; -const unsigned char kConsoleHandles[3] = { +const signed char kConsoleHandles[3] = { kNtStdInputHandle, kNtStdOutputHandle, kNtStdErrorHandle, }; // Puts cmd.exe gui back the way it was. -privileged dontinstrument void _restorewintty(void) { +void _restorewintty(void) { + int i; if (!IsWindows()) return; if (__imp_GetCurrentProcessId() != __pid_exec) return; - for (int i = 0; i < 3; ++i) { + for (i = 0; i < 3; ++i) { __imp_SetConsoleMode(__imp_GetStdHandle(kConsoleHandles[i]), __ntconsolemode[i]); } diff --git a/libc/log/oncrash_arm64.c b/libc/log/oncrash_arm64.c index 8d9b9ede8..8a6249416 100644 --- a/libc/log/oncrash_arm64.c +++ b/libc/log/oncrash_arm64.c @@ -32,10 +32,12 @@ #include "libc/log/internal.h" #include "libc/log/log.h" #include "libc/macros.internal.h" +#include "libc/mem/mem.h" #include "libc/nexgen32e/stackframe.h" #include "libc/runtime/runtime.h" #include "libc/runtime/stack.h" #include "libc/runtime/symbols.internal.h" +#include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/sysv/consts/sig.h" #include "libc/thread/thread.h" @@ -162,6 +164,17 @@ static bool AppendFileLine(struct Buffer *b, const char *addr2line, } } +static char *GetSymbolName(struct SymbolTable *st, int symbol, char **mem, + size_t *memsz) { + char *s, *t; + if ((s = __get_symbol_name(st, symbol)) && // + s[0] == '_' && s[1] == 'Z' && // + (t = __cxa_demangle(s, *mem, memsz, 0))) { + *mem = s = t; + } + return s; +} + relegated void __oncrash_arm64(int sig, struct siginfo *si, void *arg) { char buf[10000]; ucontext_t *ctx = arg; @@ -200,6 +213,8 @@ relegated void __oncrash_arm64(int sig, struct siginfo *si, void *arg) { if (ctx) { long pc; char line[256]; + char *mem = 0; + size_t memsz = 0; int addend, symbol; const char *debugbin; const char *addr2line; @@ -253,8 +268,7 @@ relegated void __oncrash_arm64(int sig, struct siginfo *si, void *arg) { if (pc && st && (symbol = __get_symbol(st, pc))) { addend = pc - st->addr_base; addend -= st->symbols[symbol].x; - Append(b, " "); - Append(b, "%s", __get_symbol_name(st, symbol)); + Append(b, " %s", GetSymbolName(st, symbol, &mem, &memsz)); if (addend) Append(b, "%+d", addend); } Append(b, "\n"); @@ -274,7 +288,7 @@ relegated void __oncrash_arm64(int sig, struct siginfo *si, void *arg) { addend -= st->symbols[symbol].x; Append(b, " "); if (!AppendFileLine(b, addr2line, debugbin, pc)) { - Append(b, "%s", __get_symbol_name(st, symbol)); + Append(b, "%s", GetSymbolName(st, symbol, &mem, &memsz)); if (addend) Append(b, "%+d", addend); } } @@ -313,11 +327,12 @@ relegated void __oncrash_arm64(int sig, struct siginfo *si, void *arg) { } Append(b, " %016lx fp %lx lr ", fp, pc); if (!AppendFileLine(b, addr2line, debugbin, pc) && st) { - Append(b, "%s", __get_symbol_name(st, symbol)); + Append(b, "%s", GetSymbolName(st, symbol, &mem, &memsz)); if (addend) Append(b, "%+d", addend); } Append(b, "\n"); } + free(mem); } } else { Append(b, "got %G while crashing! pc %lx lr %lx\n", sig, diff --git a/libc/nt/struct/imageoptionalheader.internal.h b/libc/nt/struct/imageoptionalheader.internal.h index db526f04e..29cf9a14f 100644 --- a/libc/nt/struct/imageoptionalheader.internal.h +++ b/libc/nt/struct/imageoptionalheader.internal.h @@ -4,8 +4,20 @@ #include "libc/nt/struct/imagedatadirectory.internal.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) +/** + * Portable Executable Optional Header. + * + * @see NtImageNtHeaders which encloses this + * @see NtImageFileHeader which precedes this + * @see NtImageSectionHeader which follows this + */ struct NtImageOptionalHeader { + + /* + * Must be kNtPe64bit. + */ uint16_t Magic; + uint8_t MajorLinkerVersion; uint8_t MinorLinkerVersion; uint32_t SizeOfCode; @@ -55,8 +67,20 @@ struct NtImageOptionalHeader { uint16_t MajorSubsystemVersion; uint16_t MinorSubsystemVersion; uint32_t Win32VersionValue; + + /* + * The size (in bytes) of the image, including all headers, as the + * image is loaded in memory. It must be a multiple of + * SectionAlignment. + */ uint32_t SizeOfImage; + + /* + * The combined size of an MS-DOS stub, PE header, and section headers + * rounded up to a multiple of FileAlignment. + */ uint32_t SizeOfHeaders; + uint32_t CheckSum; uint16_t Subsystem; uint16_t DllCharacteristics; diff --git a/libc/runtime/cosmo2.c b/libc/runtime/cosmo2.c index e6585faa5..5df560666 100644 --- a/libc/runtime/cosmo2.c +++ b/libc/runtime/cosmo2.c @@ -21,6 +21,7 @@ #include "libc/dce.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" +#include "libc/limits.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/rdtsc.h" #include "libc/runtime/internal.h" @@ -32,6 +33,7 @@ #include "libc/sysv/consts/sig.h" #include "libc/thread/thread.h" #include "libc/thread/tls.h" +#include "third_party/lua/lunix.h" #ifndef __x86_64__ /** @@ -128,11 +130,13 @@ textstartup void cosmo(long *sp, struct Syslib *m1) { _mmi.p = _mmi.s; __mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE; - // record provided stack to memory manager + // record system provided stack to memory manager + uintptr_t s = (uintptr_t)sp; + uintptr_t z = GetStackSize() << 1; _mmi.i = 1; - _mmi.p->x = (uintptr_t)GetStackAddr() >> 16; - _mmi.p->y = (uintptr_t)(GetStackAddr() + (GetStackSize() - FRAMESIZE)) >> 16; - _mmi.p->size = GetStackSize(); + _mmi.p->x = (s & -z) >> 16; + _mmi.p->y = MIN(((s & -z) + (z - 1)) >> 16, INT_MAX); + _mmi.p->size = z; _mmi.p->prot = PROT_READ | PROT_WRITE; __virtualmax = -1; diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index c77b519e0..e55ccb736 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -66,7 +66,7 @@ __msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect; */ extern int64_t __wincrashearly; -extern const char kConsoleHandles[3]; +extern const signed char kConsoleHandles[3]; extern void cosmo(int, char **, char **, long (*)[2]) wontreturn; static const short kConsoleModes[3] = { diff --git a/libc/sock/goodsocket.c b/libc/sock/goodsocket.c index 6ead34788..6a17f358d 100644 --- a/libc/sock/goodsocket.c +++ b/libc/sock/goodsocket.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/struct/timeval.h" +#include "libc/errno.h" #include "libc/sock/goodsocket.internal.h" #include "libc/sock/sock.h" #include "libc/sysv/consts/so.h" @@ -33,18 +34,23 @@ static bool Tune(int fd, int a, int b, int x) { */ int GoodSocket(int family, int type, int protocol, bool isserver, const struct timeval *timeout) { - int fd; + int e, fd; if ((fd = socket(family, type, protocol)) != -1) { + e = errno; if (isserver) { Tune(fd, SOL_TCP, TCP_FASTOPEN, 100); Tune(fd, SOL_SOCKET, SO_REUSEADDR, 1); } else { Tune(fd, SOL_TCP, TCP_FASTOPEN_CONNECT, 1); } + errno = e; if (!Tune(fd, SOL_TCP, TCP_QUICKACK, 1)) { + e = errno; Tune(fd, SOL_TCP, TCP_NODELAY, 1); + errno = e; } if (timeout) { + e = errno; if (timeout->tv_sec < 0) { Tune(fd, SOL_SOCKET, SO_KEEPALIVE, 1); Tune(fd, SOL_TCP, TCP_KEEPIDLE, -timeout->tv_sec); @@ -53,6 +59,7 @@ int GoodSocket(int family, int type, int protocol, bool isserver, setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, timeout, sizeof(*timeout)); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, timeout, sizeof(*timeout)); } + errno = e; } } return fd; diff --git a/libc/sysv/consts/rlimit.h b/libc/sysv/consts/rlimit.h index d2703ce44..f5db40b22 100644 --- a/libc/sysv/consts/rlimit.h +++ b/libc/sysv/consts/rlimit.h @@ -45,7 +45,6 @@ extern const unsigned RLIMIT_VMEM; #define RLIMIT_SWAP RLIMIT_SWAP #define RLIMIT_VMEM RLIMIT_VMEM - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_RLIMIT_H_ */ diff --git a/net/https/generatehardrandom.c b/net/https/generatehardrandom.c index e3e5682dd..0f2c2fcb6 100644 --- a/net/https/generatehardrandom.c +++ b/net/https/generatehardrandom.c @@ -16,10 +16,15 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/stdio/rand.h" #include "net/https/https.h" int GenerateHardRandom(void *ctx, unsigned char *p, size_t n) { - rngset(p, n, rdseed, 0); + size_t i; + ssize_t rc; + for (i = 0; i < n; i += (size_t)rc) { + _npassert((rc = getrandom(p + i, n - i, 0)) != -1); + } return 0; } diff --git a/net/turfwar/turfwar.c b/net/turfwar/turfwar.c index 9a4f7ce67..cff1d133d 100644 --- a/net/turfwar/turfwar.c +++ b/net/turfwar/turfwar.c @@ -1929,7 +1929,7 @@ int main(int argc, char *argv[]) { CHECK_EQ(0, chdir("/opt/turfwar")); putenv("TMPDIR=/opt/turfwar/tmp"); - if ((g_blackhole.fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0)) == -1) { + if ((g_blackhole.fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) { kprintf("error: socket(AF_UNIX) failed: %s\n", strerror(errno)); _Exit(3); } diff --git a/test/libc/runtime/mmap_test.c b/test/libc/runtime/mmap_test.c index 4d1b986a9..5160e84fb 100644 --- a/test/libc/runtime/mmap_test.c +++ b/test/libc/runtime/mmap_test.c @@ -33,6 +33,7 @@ #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/stack.h" +#include "libc/runtime/sysconf.h" #include "libc/stdio/rand.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" @@ -91,6 +92,17 @@ TEST(mmap, noreplaceExistingMap) { EXPECT_SYS(0, 0, munmap(p, FRAMESIZE)); } +TEST(mmap, smallerThanPage_mapsRemainder) { + long pagesz = sysconf(_SC_PAGESIZE); + char *map = mmap(0, 1, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + ASSERT_NE(MAP_FAILED, map); + EXPECT_TRUE(testlib_memoryexists(map)); + EXPECT_TRUE(testlib_memoryexists(map + (pagesz - 1))); + EXPECT_SYS(0, 0, munmap(map, 1)); + EXPECT_FALSE(testlib_memoryexists(map)); + EXPECT_FALSE(testlib_memoryexists(map + (pagesz - 1))); +} + TEST(mmap, testMapFile) { int fd; char *p; diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 989699de2..19da60bb9 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -143,7 +143,7 @@ STATIC_STACK_SIZE(0x80000); STATIC_YOINK("zipos"); -#ifndef TINY +#ifdef USE_BLINK STATIC_YOINK("blink_linux_aarch64"); // for raspberry pi STATIC_YOINK("blink_xnu_aarch64"); // is apple silicon #endif @@ -4928,7 +4928,7 @@ static int LuaProgramTokenBucket(lua_State *L) { blackhole.addr.sun_family = AF_UNIX; strlcpy(blackhole.addr.sun_path, "/var/run/blackhole.sock", sizeof(blackhole.addr.sun_path)); - if ((blackhole.fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0)) == -1) { + if ((blackhole.fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) { WARNF("(token) socket(AF_UNIX) failed: %m"); ban = -1; } else if (sendto(blackhole.fd, &testip, 4, 0,