From 4e9662cbc78ee4ee30cf660b3590e82293f5d4cc Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 22 May 2022 04:51:02 -0700 Subject: [PATCH] Write tests for new APE loader and fix bugs - Add FreeBSD-specific mmap() flags - Reduce size of the APE loader from 8kb to 4kb - Work towards fixing the Makefile build on WSL - Automate testing of APE no-modify-self behaviors - Make the ape.S shell script code cleaner and tinier - Improve the APE sanity check to test behavior better - Fixed issue with ShowCrashReports() sigaltstack() on BSDs - Delete symbols for S_MODE magnums which wasted compile time If you checked out yesterday's APE commit, please run: rm -f /usr/bin/ape o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape" Because this change fixes certain aspects of the new ABI. We don't have automated migrations for APE loader versions yet. Thanks! You can also download prebuilt binaries here: - https://justine.lol/ape.elf (Linux/FreeBSD/NetBSD/OpenBSD) - https://justine.lol/ape.macho (Apple) Install the appropriate one as `/usr/bin/ape`. --- ape/ape.S | 145 +++++++-------- ape/ape.lds | 37 ++-- ape/ape.mk | 68 +++++-- ape/apeinstall.sh | 12 +- ape/loader-elf.S | 186 ++++++++++++++----- ape/loader-macho.S | 6 +- ape/loader-macho.lds | 1 - ape/loader.c | 194 ++++++++++++-------- ape/loader.h | 15 +- ape/loader.lds | 5 +- build/bootstrap/ape | Bin 4096 -> 0 bytes build/bootstrap/ape.elf | Bin 0 -> 4224 bytes build/bootstrap/apetest.com | Bin 0 -> 20480 bytes build/sanitycheck | 26 ++- build/sanitycheck2 | 16 -- libc/calls/getprogramexecutablename.greg.c | 20 +- libc/calls/reservefd.c | 2 +- libc/calls/write-nt.c | 23 ++- libc/intrin/kdos2errno.S | 2 +- libc/log/showcrashreports.c | 4 +- libc/runtime/getinterpreterexecutablename.c | 3 + libc/runtime/getsymboltable.c | 10 +- libc/runtime/mmap.c | 17 +- libc/sysv/consts.sh | 53 ++---- libc/sysv/consts/MAP_32BIT.S | 2 +- libc/sysv/consts/MAP_ANON.S | 2 +- libc/sysv/consts/MAP_DENYWRITE.S | 2 +- libc/sysv/consts/MAP_EXECUTABLE.S | 2 +- libc/sysv/consts/MAP_FILE.S | 2 +- libc/sysv/consts/MAP_FIXED_NOREPLACE.S | 2 +- libc/sysv/consts/MAP_HASSEMAPHORE.S | 2 + libc/sysv/consts/MAP_INHERIT.S | 2 + libc/sysv/consts/MAP_NOCORE.S | 2 +- libc/sysv/consts/MAP_NOSYNC.S | 2 + libc/sysv/consts/MAP_POPULATE.S | 2 +- libc/sysv/consts/MINSIGSTKSZ.S | 2 +- libc/sysv/consts/SIGSTKSZ.S | 2 +- libc/sysv/consts/ST_MANDLOCK.S | 2 +- libc/sysv/consts/ST_SYNCHRONOUS.S | 2 +- libc/sysv/consts/ST_WRITE.S | 2 +- libc/sysv/consts/S_IEXEC.S | 2 - libc/sysv/consts/S_IFBLK.S | 2 - libc/sysv/consts/S_IFCHR.S | 2 - libc/sysv/consts/S_IFDIR.S | 2 - libc/sysv/consts/S_IFIFO.S | 2 - libc/sysv/consts/S_IFLNK.S | 2 - libc/sysv/consts/S_IFMT.S | 2 - libc/sysv/consts/S_IFREG.S | 2 - libc/sysv/consts/S_IFSOCK.S | 2 - libc/sysv/consts/S_IREAD.S | 2 - libc/sysv/consts/S_IRGRP.S | 2 - libc/sysv/consts/S_IROTH.S | 2 - libc/sysv/consts/S_IRUSR.S | 2 - libc/sysv/consts/S_IRWXG.S | 2 - libc/sysv/consts/S_IRWXO.S | 2 - libc/sysv/consts/S_IRWXU.S | 2 - libc/sysv/consts/S_ISGID.S | 2 - libc/sysv/consts/S_ISUID.S | 2 - libc/sysv/consts/S_ISVTX.S | 2 - libc/sysv/consts/S_IWGRP.S | 2 - libc/sysv/consts/S_IWOTH.S | 2 - libc/sysv/consts/S_IWRITE.S | 2 - libc/sysv/consts/S_IWUSR.S | 2 - libc/sysv/consts/S_IXGRP.S | 2 - libc/sysv/consts/S_IXOTH.S | 2 - libc/sysv/consts/S_IXUSR.S | 2 - libc/sysv/consts/map.h | 48 ++--- libc/sysv/consts/ss.h | 9 +- test/libc/release/test.mk | 10 +- test/libc/runtime/ape_test.c | 107 +++++++++++ test/libc/runtime/test.mk | 12 +- test/tool/plinko/plinko_test.c | 28 +-- tool/build/lib/apetest.c | 23 +++ tool/build/lib/buildlib.mk | 35 +++- tool/net/redbean.c | 1 - 75 files changed, 759 insertions(+), 443 deletions(-) delete mode 100644 build/bootstrap/ape create mode 100755 build/bootstrap/ape.elf create mode 100755 build/bootstrap/apetest.com delete mode 100755 build/sanitycheck2 create mode 100644 libc/sysv/consts/MAP_HASSEMAPHORE.S create mode 100644 libc/sysv/consts/MAP_INHERIT.S create mode 100644 libc/sysv/consts/MAP_NOSYNC.S delete mode 100644 libc/sysv/consts/S_IEXEC.S delete mode 100644 libc/sysv/consts/S_IFBLK.S delete mode 100644 libc/sysv/consts/S_IFCHR.S delete mode 100644 libc/sysv/consts/S_IFDIR.S delete mode 100644 libc/sysv/consts/S_IFIFO.S delete mode 100644 libc/sysv/consts/S_IFLNK.S delete mode 100644 libc/sysv/consts/S_IFMT.S delete mode 100644 libc/sysv/consts/S_IFREG.S delete mode 100644 libc/sysv/consts/S_IFSOCK.S delete mode 100644 libc/sysv/consts/S_IREAD.S delete mode 100644 libc/sysv/consts/S_IRGRP.S delete mode 100644 libc/sysv/consts/S_IROTH.S delete mode 100644 libc/sysv/consts/S_IRUSR.S delete mode 100644 libc/sysv/consts/S_IRWXG.S delete mode 100644 libc/sysv/consts/S_IRWXO.S delete mode 100644 libc/sysv/consts/S_IRWXU.S delete mode 100644 libc/sysv/consts/S_ISGID.S delete mode 100644 libc/sysv/consts/S_ISUID.S delete mode 100644 libc/sysv/consts/S_ISVTX.S delete mode 100644 libc/sysv/consts/S_IWGRP.S delete mode 100644 libc/sysv/consts/S_IWOTH.S delete mode 100644 libc/sysv/consts/S_IWRITE.S delete mode 100644 libc/sysv/consts/S_IWUSR.S delete mode 100644 libc/sysv/consts/S_IXGRP.S delete mode 100644 libc/sysv/consts/S_IXOTH.S delete mode 100644 libc/sysv/consts/S_IXUSR.S create mode 100644 test/libc/runtime/ape_test.c create mode 100644 tool/build/lib/apetest.c diff --git a/ape/ape.S b/ape/ape.S index acddc38a0..c7f02a217 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -550,25 +550,25 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang // extract the loader into a temp folder, and use it to // load the APE without modifying it. .ascii "t=\"${TMPDIR:-/tmp}/ape\"\n" - .ascii "if [ ! -x \"$t\" ]; then\n" - .ascii "if [ ! -d /Applications ]; then\n" - .ascii "dd if=\"$o\" of=\"$t.$$\" skip=\"" - .shstub ape_loader_dd_skip,2 - .ascii "\" count=\"" - .shstub ape_loader_dd_count,2 - .ascii "\" bs=64\n" -#if SupportsXnu() && defined(APE_LOADER_MACHO) - .ascii "else\n" - .ascii "dd if=\"$o\" of=\"$t.$$\" skip=\"" - .shstub ape_loader_macho_dd_skip,2 - .ascii "\" count=\"" - .shstub ape_loader_macho_dd_count,2 - .ascii "\" bs=64\n" -#endif /* APE_LOADER_MACHO */ - .ascii "fi 2>/dev/null &&\n" - .ascii "chmod 755 \"$t.$$\" &&\n" - .ascii "mv \"$t.$$\" \"$t\"\n" - .ascii "fi\n" + .ascii "[ -x \"$t\" ] || {\n" + .ascii "dd if=\"$o\" of=\"$t.$$\" skip=\"" + .shstub ape_loader_dd_skip,2 + .ascii "\" count=\"" + .shstub ape_loader_dd_count,2 + .ascii "\" bs=64 2>/dev/null\n" +#if SupportsXnu() + .ascii "[ -d /Applications ] && " + .ascii "dd if=\"$t.$$\"" + .ascii " of=\"$t.$$\"" + .ascii " skip=6" + .ascii " count=10" + .ascii " bs=64" + .ascii " conv=notrunc" + .ascii " 2>/dev/null\n" +#endif /* SupportsXnu() */ + .ascii "chmod 755 \"$t.$$\"\n" + .ascii "mv -f \"$t.$$\" \"$t\"\n" + .ascii "}\n" .ascii "exec \"$t\" \"$o\" \"$@\"\n" #endif /* APE_LOADER */ #ifndef APE_NO_MODIFY_SELF @@ -589,15 +589,40 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang // then permission clashes can happen between system users, // since only root is able to set the sticky bit, which can // be addressed simply by overriding the TMPDIR environment - .ascii "o=\"${TMPDIR:-/tmp}/$0\"\n" - .ascii "if [ ! -e \"$o\" ]; then\n" - .ascii "d=\"$o\"\n" - .ascii "o=\"$o.$$\"\n" - .ascii "mkdir -p \"${o%/*}\" 2>/dev/null\n" - .ascii "cp -f \"$0\" \"$o\" || exit 120\n" + .ascii "t=\"${TMPDIR:-/tmp}/$0\"\n" + .ascii "[ -e \"$t\" ] || {\n" + .ascii "mkdir -p \"${t%/*}\" 2>/dev/null\n" + .ascii "cp -f \"$o\" \"$t.$$\" &&\n" + .ascii "mv -f \"$t.$$\" \"$t\" || exit 120\n" + .ascii "o=\"$t\"\n" #endif /* APE_NO_MODIFY_SELF */ + .ascii "exec 7<> \"$o\" || exit 121\n" + .ascii "printf '" + .ascii "\\177ELF" # 0x0: ⌂ELF + .ascii "\\2" # 4: long mode + .ascii "\\1" # 5: little endian + .ascii "\\1" # 6: elf v1.o + .ascii "\\011" # 7: FreeBSD + .ascii "\\0" # 8: os/abi ver. + .ascii "\\0\\0\\0" # 9: padding 3/7 + .ascii "\\0\\0\\0\\0" # padding 4/7 + .ascii "\\2\\0" # 10: εxεcµταblε + .ascii "\\076\\0" # 12: NexGen32e + .ascii "\\1\\0\\0\\0" # 14: elf v1.o + .shstub ape_elf_entry,8 # 18: e_entry + .shstub ape_elf_phoff,8 # 20: e_phoff + .shstub ape_elf_shoff,8 # 28: e_shoff + .ascii "\\0\\0\\0\\0" # 30: e_flags + .ascii "\\100\\0" # 34: e_ehsize + .ascii "\\070\\0" # 36: e_phentsize + .shstub ape_elf_phnum,2 # 38: e_phnum + .ascii "\\0\\0" # 3a: e_shentsize + .shstub ape_elf_shnum,2 # 3c: e_shnum + .shstub ape_elf_shstrndx,2 # 3e: e_shstrndx + .ascii "' >&7\n" + .ascii "exec 7<&-\n" #if SupportsXnu() - .ascii "if [ -d /Applications ]; then\n" + .ascii "[ -d /Applications ] && " .ascii "dd if=\"$o\"" .ascii " of=\"$o\"" .ascii " bs=8" @@ -606,54 +631,20 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .ascii "\" count=\"" .shstub ape_macho_dd_count,2 .ascii "\" conv=notrunc 2>/dev/null\n" - .ascii "el" #endif /* XNU */ - .ascii "if exec 7<> \"$o\"; then\n" - .ascii "printf '" - .ascii "\\177ELF" # 0x0: ⌂ELF - .ascii "\\2" # 4: long mode - .ascii "\\1" # 5: little endian - .ascii "\\1" # 6: elf v1.o - .ascii "\\011" # 7: FreeBSD - .ascii "\\0" # 8: os/abi ver. - .ascii "\\0\\0\\0" # 9: padding 3/7 - .ascii "\\0\\0\\0\\0" # padding 4/7 - .ascii "\\2\\0" # 10: εxεcµταblε - .ascii "\\076\\0" # 12: NexGen32e - .ascii "\\1\\0\\0\\0" # 14: elf v1.o - .shstub ape_elf_entry,8 # 18: e_entry - .shstub ape_elf_phoff,8 # 20: e_phoff - .shstub ape_elf_shoff,8 # 28: e_shoff - .ascii "\\0\\0\\0\\0" # 30: e_flags - .ascii "\\100\\0" # 34: e_ehsize - .ascii "\\070\\0" # 36: e_phentsize - .shstub ape_elf_phnum,2 # 38: e_phnum - .ascii "\\0\\0" # 3a: e_shentsize - .shstub ape_elf_shnum,2 # 3c: e_shnum - .shstub ape_elf_shstrndx,2 # 3e: e_shstrndx - .ascii "' >&7\n" - .ascii "exec 7<&-\n" - .ascii "else\n" - .ascii "exit 121\n" - .ascii "fi\n" #ifndef APE_NO_MODIFY_SELF - .ascii "exec \"$0\" \"$@\"\n" # optimistic execution + .ascii "exec \"$0\" \"$@\"\n" # try to preserve argv[0] #else - .ascii "mv -f \"$o\" \"$d\" 2>/dev/null\n" - .ascii "o=\"$d\"\n" - .ascii "fi\n" + .ascii "}\n" + .ascii "o=\"$t\"\n" .ascii "exec \"$o\" \"$@\"\n" #endif /* APE_NO_MODIFY_SELF */ .ascii "R=$?\n" - .ascii "\n" - .ascii "if [ $R -eq 126 ] && [ \"$(uname -m)\" != x86_64 ]; then\n" - .ascii "if Q=\"$(command -v qemu-x86_64)\"; then\n" + .ascii "if [ \"$(uname -m)\" != x86_64 ]; then\n" + .ascii "Q=\"$(command -v qemu-x86_64)\" &&\n" .ascii "exec \"$Q\" \"$o\" \"$@\"\n" - .ascii "else\n" - .ascii "echo error: need qemu-x86_64 >&2\n" - .ascii "fi\n" #ifndef APE_NO_MODIFY_SELF - .ascii "elif [ $R -eq 127 ]; then\n" # means argv[0] was wrong + .ascii "else\n" # means argv[0] was wrong .ascii " exec \"$o\" \"$@\"\n" # so do a path resolution #endif /* APE_NO_MODIFY_SELF */ .ascii "fi\n" @@ -661,14 +652,16 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .endobj apesh #ifdef APE_LOADER .section .ape.loader,"a",@progbits + .align 64 +ape_loader: .incbin APE_LOADER + .endobj ape_loader,globl + .align 64 +ape_loader_end: + nop + .endobj ape_loader_end,globl .previous #endif /* APE_LOADER */ -#if SupportsXnu() && defined(APE_LOADER_MACHO) - .section .ape.loader-macho,"a",@progbits - .incbin APE_LOADER_MACHO - .previous -#endif /* APE_LOADER_MACHO */ #endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */ #if SupportsSystemv() || SupportsMetal() @@ -1521,12 +1514,9 @@ kernel: movabs $ape_stack_vaddr,%rsp .byte 0x0f,0x1f,0207 # nop rdi binbase .long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512 #endif - .weak __hostos - ezlea __hostos,ax - test %rax,%rax - jz 1f - movb $METAL,(%rax) -1: push $0 + push $METAL # sets __hostos in crt.S + pop %rcx + push $0 mov %rsp,%rbp mov .Lenv0(%rip),%rax mov %rax,(%rbp) # envp[0][0] @@ -1542,7 +1532,6 @@ kernel: movabs $ape_stack_vaddr,%rsp push $1 # argc xor %ebp,%ebp xor %eax,%eax - xor %ecx,%ecx xor %edx,%edx xor %edi,%edi xor %esi,%esi diff --git a/ape/ape.lds b/ape/ape.lds index f37234a7b..e97b96058 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -243,10 +243,12 @@ SECTIONS { /* Code that needs to be addressable in Real Mode */ *(.text.real) KEEP(*(SORT_BY_NAME(.sort.text.real.*))) + /* Code we want earlier in the binary w/o modifications */ + KEEP(*(.ape.loader)) HIDDEN(_ereal = .); - . += 1; - /*END: realmode addressability guarantee */ +/*BEGIN: morphable code */ + . += 1; /* Normal Code */ *(.start) @@ -283,6 +285,7 @@ SECTIONS { /* Privileged code invulnerable to magic */ KEEP(*(.ape.pad.privileged)); . += . > 0 ? 1 : 0; +/*END: morphable code */ HIDDEN(__privileged_start = .); . += . > 0 ? 1 : 0; *(.privileged) @@ -390,21 +393,6 @@ SECTIONS { } :Ram /*END: file content that's loaded by o/s */ -/*BEGIN: payload (for now, only the APE loader) */ - .payload ALIGN(64) : { - /* Loader */ - HIDDEN(ape_loader = .); - KEEP(*(.ape.loader)) - . = ALIGN(64); - HIDDEN(ape_loader_end = .); -#if SupportsXnu() - HIDDEN(ape_loader_macho = .); - KEEP(*(.ape.loader-macho)) - . = ALIGN(64); - HIDDEN(ape_loader_macho_end = .); -#endif - } -/*END: payload */ /*BEGIN: bss memory void */ .zip . : { @@ -552,13 +540,14 @@ HIDDEN(ape_bss_filesz = 0); HIDDEN(ape_bss_memsz = SIZEOF(.bss)); HIDDEN(ape_bss_align = PAGESIZE); -SHSTUB2(ape_loader_dd_skip, RVA(ape_loader) / 64); -SHSTUB2(ape_loader_dd_count, (ape_loader_end - ape_loader) / 64); - -#if SupportsXnu() -SHSTUB2(ape_loader_macho_dd_skip, RVA(ape_loader_macho) / 64); -SHSTUB2(ape_loader_macho_dd_count, (ape_loader_macho_end - ape_loader_macho) / 64); -#endif +/* we roundup here because xnu wants the file load segments page-aligned */ +/* but we don't want to add the nop padding to the ape program, so we'll */ +/* let ape.S dd read past the end of the file into the wrapping binaries */ +SHSTUB2(ape_loader_dd_skip, DEFINED(ape_loader) ? RVA(ape_loader) / 64 : 0); +SHSTUB2(ape_loader_dd_count, + DEFINED(ape_loader_end) + ? ROUNDUP(ape_loader_end - ape_loader, PAGESIZE) / 64 + : 0); #if SupportsXnu() SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8); diff --git a/ape/ape.mk b/ape/ape.mk index 590075703..759296ec4 100644 --- a/ape/ape.mk +++ b/ape/ape.mk @@ -22,6 +22,10 @@ APE_NO_MODIFY_SELF = \ o/$(MODE)/ape/ape.lds \ o/$(MODE)/ape/ape-no-modify-self.o +APE_COPY_SELF = \ + o/$(MODE)/ape/ape.lds \ + o/$(MODE)/ape/ape-copy-self.o + APELINK = \ $(COMPILE) \ -ALINK.ape \ @@ -29,6 +33,22 @@ APELINK = \ $(LINKARGS) \ $(OUTPUT_OPTION) +APE_LOADER_FLAGS = \ + -DNDEBUG \ + -iquote. \ + -Wall \ + -Wextra \ + -fpie \ + -Os \ + -ffreestanding \ + -mgeneral-regs-only \ + -mno-red-zone \ + -fno-ident \ + -fno-gnu-unique \ + -c \ + $(OUTPUT_OPTION) \ + $< + APE_FILES := $(wildcard ape/*.*) APE_HDRS = $(filter %.h,$(APE_FILES)) APE_INCS = $(filter %.inc,$(APE_FILES)) @@ -50,31 +70,55 @@ o/ape/idata.inc: \ o/$(MODE)/ape/ape-no-modify-self.o: \ ape/ape.S \ - o/$(MODE)/ape/ape \ - o/$(MODE)/ape/ape.macho - @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_LOADER="\"o/$(MODE)/ape/ape\"" -DAPE_LOADER_MACHO="\"o/$(MODE)/ape/ape.macho\"" $< + o/$(MODE)/ape/ape.elf + @$(COMPILE) \ + -AOBJECTIFY.S \ + $(OBJECTIFY.S) \ + $(OUTPUT_OPTION) \ + -DAPE_NO_MODIFY_SELF \ + -DAPE_LOADER="\"o/$(MODE)/ape/ape.elf\"" $< + +o/$(MODE)/ape/ape-copy-self.o: \ + ape/ape.S + @$(COMPILE) \ + -AOBJECTIFY.S \ + $(OBJECTIFY.S) \ + $(OUTPUT_OPTION) \ + -DAPE_NO_MODIFY_SELF $< o/$(MODE)/ape/loader.o: ape/loader.c - @$(COMPILE) -AOBJECTIFY.c $(CC) -DNDEBUG -iquote. -Wall -Wextra -fpie -Os -g -ffreestanding -mno-red-zone -fno-ident -fno-gnu-unique -c $(OUTPUT_OPTION) $< - + @$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b01111001 -g $(APE_LOADER_FLAGS) o/$(MODE)/ape/loader-gcc.asm: ape/loader.c - @$(COMPILE) -AOBJECTIFY.c $(CC) -DNDEBUG -iquote. -Wall -Wextra -fpie -Os -g -ffreestanding -mno-red-zone -fno-ident -fno-gnu-unique -c -S $(OUTPUT_OPTION) $< + @$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b01111001 -S -g0 $(APE_LOADER_FLAGS) +o/$(MODE)/ape/loader-clang.asm: ape/loader.c + @$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=0b01111001 -S -g0 $(APE_LOADER_FLAGS) -o/$(MODE)/ape/ape: \ +o/$(MODE)/ape/loader-xnu.o: ape/loader.c + @$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b00001000 -g $(APE_LOADER_FLAGS) +o/$(MODE)/ape/loader-xnu-gcc.asm: ape/loader.c + @$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b00001000 -S -g0 $(APE_LOADER_FLAGS) +o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c + @$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=0b00001000 -S -g0 $(APE_LOADER_FLAGS) + +o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg +o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.macho.dbg + +o/$(MODE)/ape/ape.elf.dbg: \ o/$(MODE)/ape/loader.o \ o/$(MODE)/ape/loader-elf.o \ ape/loader.lds - @$(ELFLINK) -s -z max-page-size=0x10 + @$(ELFLINK) -z max-page-size=0x10 -o/$(MODE)/ape/ape.macho: \ - o/$(MODE)/ape/loader.o \ +o/$(MODE)/ape/ape.macho.dbg: \ + o/$(MODE)/ape/loader-xnu.o \ o/$(MODE)/ape/loader-macho.o \ ape/loader-macho.lds - @$(ELFLINK) -s -z max-page-size=0x10 + @$(ELFLINK) -z max-page-size=0x10 .PHONY: o/$(MODE)/ape o/$(MODE)/ape: $(APE) \ $(APE_CHECKS) \ - o/$(MODE)/ape/ape \ + o/$(MODE)/ape/ape.elf \ o/$(MODE)/ape/ape.macho \ + o/$(MODE)/ape/ape-copy-self.o \ o/$(MODE)/ape/ape-no-modify-self.o diff --git a/ape/apeinstall.sh b/ape/apeinstall.sh index d5723f130..6d2b7cd74 100755 --- a/ape/apeinstall.sh +++ b/ape/apeinstall.sh @@ -9,19 +9,19 @@ fi if [ -f o/depend ]; then # mkdeps.com build was successfully run so assume we can build echo >&2 - echo running: make -j8 o//ape/ape >&2 - make -j8 o//ape/ape || exit + echo running: make -j8 o//ape/ape.elf >&2 + make -j8 o//ape/ape.elf || exit echo done >&2 else # no evidence we can build, use prebuilt one mkdir -p o//ape || exit - cp -af build/bootstrap/ape o//ape/ape + cp -af build/bootstrap/ape.elf o//ape/ape.elf fi echo >&2 -echo installing o//ape/ape to /usr/bin/ape >&2 -echo sudo mv -f o//ape/ape /usr/bin/ape >&2 -sudo mv -f o//ape/ape /usr/bin/ape || exit +echo installing o//ape/ape.elf to /usr/bin/ape >&2 +echo sudo mv -f o//ape/ape.elf /usr/bin/ape >&2 +sudo mv -f o//ape/ape.elf /usr/bin/ape || exit echo done >&2 if [ -e /proc/sys/fs/binfmt_misc/APE ]; then diff --git a/ape/loader-elf.S b/ape/loader-elf.S index 9fafc4fd0..cbde38956 100644 --- a/ape/loader-elf.S +++ b/ape/loader-elf.S @@ -17,6 +17,9 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/elf/def.h" +#include "libc/sysv/consts/prot.h" +#include "libc/macho.internal.h" +#include "libc/dce.h" #include "libc/macros.internal.h" // APE Loader Executable Structure @@ -44,48 +47,6 @@ ehdr: .ascii "\177ELF" .word 0 # e_shstrndx .endobj ehdr,globl -// Ape Loader Entrpoint -// -// This is normally called by the operating system. However it may -// be called by the Actually Portable Executables themselves, when -// re-executing a program. Just do this: -// -// memcpy(0x200000, loader) -// xor %eax,%eax -// inc %eax -// jmp 0x200000 -// -// @see APE_LOADER_ENTRY -jg47h: .org 0x47 - .endobj jg47h -_start: mov %rsp,%rsi - jmp ApeLoader - .endfn _start,globl - -// System Call Entrpoint -// -// This function is used by the APE loader to make system calls. -// We also pass a reference to this function to the APE binary's -// _start() function. It's needed because on OpenBSD, msyscall() -// restricts which pages can issue system calls, and it can only -// be called once. Therefore if we want to be load and re-load a -// binary multiple times without calling the system execve(), we -// need to be able to handover the SYSCALL function. We hardcode -// this to a fixed address, but that shouldn't be used, since we -// would ideally want to move it to a random page in the future. -// -// @see APE_LOADER_SYSCALL -sc50h: .org 0x50 - .endobj sc50h -__syscall_loader: - clc - syscall - jc 1f - ret -1: neg %rax - ret - .endfn __syscall_loader,globl - .align 8 phdrs: .long PT_LOAD # p_type .long PF_R|PF_X # p_flags @@ -94,7 +55,7 @@ phdrs: .long PT_LOAD # p_type .quad ehdr # p_paddr .quad filesz # p_filesz .quad filesz # p_memsz - .quad PAGESIZE # p_align + .quad 64 # p_align .long PT_LOAD # p_type .long PF_R|PF_W # p_flags @@ -103,7 +64,7 @@ phdrs: .long PT_LOAD # p_type .quad bss # p_paddr .quad 0 # p_filesz .quad bsssize # p_memsz - .quad PAGESIZE # p_align + .quad 64 # p_align .long PT_GNU_STACK # p_type .long PF_R|PF_W # p_flags @@ -138,3 +99,140 @@ note: .long 2f-1f 3: .long 901000000 4: .endobj note notesize = . - note + + .align 64,0 # for ape.S dd + .org 0x180 # for ape.S dd + +// APE Loader XNU Header +// +// This header is dd'd backwards by the APE shell script when +// running on Mac OS X. +// +// @see ape/ape.S +macho: .long 0xFEEDFACE+1 + .long MAC_CPU_NEXGEN32E + .long MAC_CPU_NEXGEN32E_ALL + .long MAC_EXECUTE + .long 5 # number of load commands + .long 60f-10f # size of all load commands + .long MAC_NOUNDEFS # flags + .long 0 # reserved +10: .long MAC_LC_SEGMENT_64 + .long 20f-10b # unmaps first page dir + .ascin "__PAGEZERO",16 # consistent with linux + .quad 0,0x200000,0,0 # which forbids mem <2m + .long 0,0,0,0 +20: .long MAC_LC_SEGMENT_64 + .long 30f-20b + .ascin "__TEXT",16 + .quad ehdr # vaddr + .quad 4096 # memsz + .quad 0 # file offset + .quad filesz # file size + .long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot + .long PROT_EXEC|PROT_READ # initprot + .long 1 # segment section count + .long 0 # flags +210: .ascin "__text",16 # section name (.text) + .ascin "__TEXT",16 + .quad _start # vaddr + .quad textsz # memsz + .long textoff # offset + .long 6 # align 2**6 = 64 + .long 0 # reloc table offset + .long 0 # relocation count + .long MAC_S_ATTR_SOME_INSTRUCTIONS # section type & attributes + .long 0,0,0 # reserved +30: .long MAC_LC_SEGMENT_64 + .long 40f-30b + .ascin "__DATA",16 + .quad bss # vaddr + .quad bsssize # memsz + .quad 0 # offset + .quad 0 # file size + .long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot + .long PROT_READ|PROT_WRITE # initprot + .long 1 # segment section count + .long 0 # flags +310: .ascin "__bss",16 # section name (.bss) + .ascin "__DATA",16 + .quad bss # vaddr + .quad bsssize # memsz + .long 0 # offset + .long 12 # align 2**12 = 4096 + .long 0 # reloc table offset + .long 0 # relocation count + .long MAC_S_ZEROFILL # section type & attributes + .long 0,0,0 # reserved +40: .long MAC_LC_UUID + .long 50f-40b + .quad 0x3fb29ee4ac6c87aa # uuid1 + .quad 0xdd2c9bb866d9eef8 # uuid2 +50: .long MAC_LC_UNIXTHREAD + .long 60f-50b # cmdsize + .long MAC_THREAD_NEXGEN32E # flavaflav + .long (520f-510f)/4 # count +510: .quad 0 # rax + .quad 0 # rbx + .quad 0 # rcx + .quad XNU # rdx + .quad 0 # rdi + .quad 0 # rsi + .quad 0 # rbp + .quad 0 # rsp + .quad 0 # r8 + .quad 0 # r9 + .quad 0 # r10 + .quad 0 # r11 + .quad 0 # r12 + .quad 0 # r13 + .quad 0 # r14 + .quad 0 # r15 + .quad _start # rip + .quad 0 # rflags + .quad 0 # cs + .quad 0 # fs + .quad 0 # gs +520: +60: + .endobj macho + + .align 64,0 # for ape.S dd + .org 0x400 # for ape.S dd + +// Ape Loader Entrpoint +// +// This is normally called by the operating system. However it may +// be called by the Actually Portable Executables themselves, when +// re-executing a program. Just do this: +// +// memcpy(0x200000, loader) +// lea handoff(%rip),%rcx +// lea argblock(%rip),%rsp +// jmp 0x200400 +// +// @see APE_LOADER_ENTRY +// @see ape/loader.h +_start: mov %rsp,%rsi + jmp ApeLoader + .endfn _start,globl + +// System Call Entrpoint +// +// This function is used by the APE loader to make system calls. +// We also pass a reference to this function to the APE binary's +// _start() function. It's needed because on OpenBSD, msyscall() +// restricts which pages can issue system calls, and it can only +// be called once. Therefore if we want to be load and re-load a +// binary multiple times without calling the system execve(), we +// need to be able to handover the SYSCALL function. We hardcode +// this to a fixed address, but that shouldn't be used, since we +// would ideally want to move it to a random page in the future. +__syscall_loader: + clc + syscall + jc 1f + ret +1: neg %rax + ret + .endfn __syscall_loader,globl diff --git a/ape/loader-macho.S b/ape/loader-macho.S index 656a05b87..b027760a7 100644 --- a/ape/loader-macho.S +++ b/ape/loader-macho.S @@ -41,7 +41,7 @@ macho: .long 0xFEEDFACE+1 .long 30f-20b .ascin "__TEXT",16 .quad macho # vaddr - .quad filesz # memsz + .quad 4096 # memsz .quad 0 # file offset .quad filesz # file size .long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot @@ -53,7 +53,7 @@ macho: .long 0xFEEDFACE+1 .quad _start # vaddr .quad textsz # memsz .long textoff # offset - .long 3 # align 2**3 = 8 + .long 6 # align 2**3 = 64 .long 0 # reloc table offset .long 0 # relocation count .long MAC_S_ATTR_SOME_INSTRUCTIONS # section type & attributes @@ -112,7 +112,7 @@ macho: .long 0xFEEDFACE+1 60: .endobj macho,globl - .align 8 + .align 64 _start: mov %rsp,%rsi jmp ApeLoader .endfn _start,globl diff --git a/ape/loader-macho.lds b/ape/loader-macho.lds index c8f36b161..973c182a5 100644 --- a/ape/loader-macho.lds +++ b/ape/loader-macho.lds @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ ENTRY(_start) -OUTPUT_FORMAT(binary) SECTIONS { . = 0x200000; diff --git a/ape/loader.c b/ape/loader.c index 413641fd9..d38e4b838 100644 --- a/ape/loader.c +++ b/ape/loader.c @@ -22,7 +22,7 @@ #define TROUBLESHOOT_OS LINUX /** - * @fileoverview APE Loader for GNU/Systemd and FreeBSD/NetBSD/OpenBSD + * @fileoverview APE Loader for GNU/Systemd/XNU/FreeBSD/NetBSD/OpenBSD * * We recommend using the normal APE design, where binaries assimilate * themselves once by self-modifying the first 64 bytes. If that can't @@ -30,7 +30,7 @@ * * m=tiny * make -j8 MODE=$m o/$m/ape o/$m/examples/printargs.com - * o/$m/ape/ape o/$m/examples/printargs.com + * o/$m/ape/ape.elf o/$m/examples/printargs.com * * This is an embeddable Actually Portable Executable interpreter. The * `ape/ape.S` bootloader embeds this binary inside each binary that's @@ -45,8 +45,12 @@ * so your APE loader may be installed to your system as follows: * * m=tiny - * make -j8 MODE=$m o/$m/ape/ape - * sudo cp o/$m/ape/ape /usr/bin/ape + * make -j8 MODE=$m o/$m/ape/ape.elf + * sudo cp o/$m/ape/ape.elf /usr/bin/ape + * + * For Mac OS X systems you should install the `ape.macho` executable: + * + * sudo cp o/$m/ape/ape.macho /usr/bin/ape * * Your APE loader may be used as a shebang interpreter by doing this: * @@ -57,7 +61,7 @@ * However you won't need to do that, if your APE Loader is registered * as a binfmt_misc interpreter. You can do that as follows with root: * - * sudo cp -f o/$m/ape/ape /usr/bin + * sudo cp -f o/$m/ape/ape.elf /usr/bin * f=/proc/sys/fs/binfmt_misc/register * sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >$f" * @@ -78,13 +82,23 @@ */ #define LINUX 1 -#define METAL 2 -#define WINDOWS 4 #define XNU 8 #define OPENBSD 16 #define FREEBSD 32 #define NETBSD 64 +#define SupportsLinux() (SUPPORT_VECTOR & LINUX) +#define SupportsXnu() (SUPPORT_VECTOR & XNU) +#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD) +#define SupportsOpenbsd() (SUPPORT_VECTOR & OPENBSD) +#define SupportsNetbsd() (SUPPORT_VECTOR & NETBSD) + +#define IsLinux() (SupportsLinux() && os == LINUX) +#define IsXnu() (SupportsXnu() && os == XNU) +#define IsFreebsd() (SupportsFreebsd() && os == FREEBSD) +#define IsOpenbsd() (SupportsOpenbsd() && os == OPENBSD) +#define IsNetbsd() (SupportsNetbsd() && os == NETBSD) + #define O_RDONLY 0 #define PROT_READ 1 #define PROT_WRITE 2 @@ -92,7 +106,7 @@ #define MAP_SHARED 1 #define MAP_PRIVATE 2 #define MAP_FIXED 16 -#define MAP_ANONYMOUS (os == LINUX ? 32 : 4096) +#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096) #define AT_EXECFN_LINUX 31 #define AT_EXECFN_NETBSD 2014 #define ELFCLASS64 2 @@ -235,15 +249,15 @@ static char *Itoa(char p[21], long x) { #if TROUBLESHOOT const char *DescribeOs(int os) { - if (os == LINUX) { + if (IsLinux()) { return "GNU/SYSTEMD"; - } else if (os == XNU) { + } else if (IsXnu()) { return "XNU"; - } else if (os == FREEBSD) { + } else if (IsFreebsd()) { return "FREEBSD"; - } else if (os == OPENBSD) { + } else if (IsOpenbsd()) { return "OPENBSD"; - } else if (os == NETBSD) { + } else if (IsNetbsd()) { return "NETBSD"; } else { return "WUT"; @@ -251,40 +265,42 @@ const char *DescribeOs(int os) { } #endif -__attribute__((__noreturn__)) static void Exit(long rc, int os) { +__attribute__((__noreturn__)) static void Exit(int rc, int os) { asm volatile("call\t*%2" : /* no outputs */ - : "a"((os == LINUX ? 60 : 1) | (os == XNU ? 0x2000000 : 0)), - "D"(rc), "m"(syscall) + : "a"((IsLinux() ? 60 : 1) | (IsXnu() ? 0x2000000 : 0)), "D"(rc), + "rm"(syscall) : "memory"); __builtin_unreachable(); } -static void Close(long fd, int os) { - long ax, di; +static void Close(int fd, int os) { + int ax, di; asm volatile("call\t*%4" : "=a"(ax), "=D"(di) - : "0"((os == LINUX ? 3 : 6) | (os == XNU ? 0x2000000 : 0)), - "1"(fd), "m"(syscall) + : "0"((IsLinux() ? 3 : 6) | (IsXnu() ? 0x2000000 : 0)), "1"(fd), + "rm"(syscall) : "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "memory", "cc"); } -static long Read(long fd, void *data, unsigned long size, int os) { - long ax, di, si, dx; +static int Read(int fd, void *data, int size, int os) { + long si; + int ax, di, dx; asm volatile("call\t*%8" : "=a"(ax), "=D"(di), "=S"(si), "=d"(dx) - : "0"((os == LINUX ? 0 : 3) | (os == XNU ? 0x2000000 : 0)), - "1"(fd), "2"(data), "3"(size), "m"(syscall) + : "0"((IsLinux() ? 0 : 3) | (IsXnu() ? 0x2000000 : 0)), "1"(fd), + "2"(data), "3"(size), "rm"(syscall) : "rcx", "r8", "r9", "r10", "r11", "memory"); return ax; } -static void Write(long fd, const void *data, unsigned long size, int os) { - long ax, di, si, dx; +static void Write(int fd, const void *data, int size, int os) { + long si; + int ax, di, dx; asm volatile("call\t*%8" : "=a"(ax), "=D"(di), "=S"(si), "=d"(dx) - : "0"((os == LINUX ? 1 : 4) | (os == XNU ? 0x2000000 : 0)), - "1"(fd), "2"(data), "3"(size), "m"(syscall) + : "0"((IsLinux() ? 1 : 4) | (IsXnu() ? 0x2000000 : 0)), "1"(fd), + "2"(data), "3"(size), "rm"(syscall) : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); } @@ -292,58 +308,68 @@ static void Execve(const char *prog, char **argv, char **envp, int os) { long ax, di, si, dx; asm volatile("call\t*%8" : "=a"(ax), "=D"(di), "=S"(si), "=d"(dx) - : "0"((59) | (os == XNU ? 0x2000000 : 0)), "1"(prog), "2"(argv), - "3"(envp), "m"(syscall) + : "0"(59 | (IsXnu() ? 0x2000000 : 0)), "1"(prog), "2"(argv), + "3"(envp), "rm"(syscall) : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); } -static long Access(const char *path, int mode, int os) { - long ax, dx, di, si; +static int Access(const char *path, int mode, int os) { + int ax, si; + long dx, di; asm volatile("call\t*%7" : "=a"(ax), "=D"(di), "=S"(si), "=d"(dx) - : "0"((os == LINUX ? 21 : 33) | (os == XNU ? 0x2000000 : 0)), - "1"(path), "2"(mode), "m"(syscall) + : "0"((IsLinux() ? 21 : 33) | (IsXnu() ? 0x2000000 : 0)), + "1"(path), "2"(mode), "rm"(syscall) : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); return ax; } -static void Msyscall(long p, long n, int os) { - long ax, di, si; - if (os == OPENBSD) { +static int Msyscall(long p, long n, int os) { + int ax; + long di, si; + if (!IsOpenbsd()) { + return 0; + } else { asm volatile("call\t*%6" : "=a"(ax), "=D"(di), "=S"(si) - : "0"(37), "1"(p), "2"(n), "m"(syscall) + : "0"(37), "1"(p), "2"(n), "rm"(syscall) : "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc"); + return ax; } } -static long Open(const char *path, long flags, long mode, int os) { - long ax, di, si, dx; +static int Open(const char *path, int flags, int mode, int os) { + long di; + int ax, dx, si; asm volatile("call\t*%8" : "=a"(ax), "=D"(di), "=S"(si), "=d"(dx) - : "0"((os == LINUX ? 2 : 5) | (os == XNU ? 0x2000000 : 0)), - "1"(path), "2"(flags), "3"(mode), "m"(syscall) - : "rcx", "r8", "r9", "r10", "r11", "memory"); + : "0"((IsLinux() ? 2 : 5) | (IsXnu() ? 0x2000000 : 0)), + "1"(path), "2"(flags), "3"(mode), "rm"(syscall) + : "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); return ax; } -__attribute__((__noinline__)) long Mmap(long addr, long size, long prot, - long flags, long fd, long off, int os) { - long ax; - register long flags_ asm("r10") = flags; - register long fd_ asm("r8") = fd; +__attribute__((__noinline__)) static long Mmap(long addr, long size, int prot, + int flags, int fd, long off, + int os) { + long ax, di, si, dx; + register int flags_ asm("r10") = flags; + register int fd_ asm("r8") = fd; register long off_ asm("r9") = off; asm volatile("push\t%%r9\n\t" - "call\t*%8\n\t" + "push\t%%r9\n\t" + "call\t*%7\n\t" + "pop\t%%r9\n\t" "pop\t%%r9" - : "=a"(ax) - : "0"((os == LINUX ? 9 - : os == FREEBSD ? 477 - : 197) | - (os == XNU ? 0x2000000 : 0)), - "D"(addr), "S"(size), "d"(prot), "r"(flags_), "r"(fd_), - "r"(off_), "m"(syscall) - : "rcx", "r11", "memory"); + : "=a"(ax), "=D"(di), "=S"(si), "=d"(dx), "+r"(flags_), + "+r"(fd_), "+r"(off_) + : "rm"(syscall), + "0"((IsLinux() ? 9 + : IsFreebsd() ? 477 + : 197) | + (IsXnu() ? 0x2000000 : 0)), + "1"(addr), "2"(size), "3"(prot) + : "rcx", "r11", "memory", "cc"); return ax; } @@ -514,20 +540,33 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, Pexit(os, exe, 0, "ELF needs PT_LOAD phdr w/ PF_X"); } Close(fd, os); - Msyscall(code, codesize, os); + + // authorize only the loaded program to issue system calls. if this + // fails, then we pass a link to our syscall function to the program + // since it probably means a userspace program executed this loader + // and passed us a custom syscall function earlier. + if (Msyscall(code, codesize, os) != -1) { + syscall = 0; + } + #if TROUBLESHOOT Emit(TROUBLESHOOT_OS, "preparing to jump\n"); #endif - register long r8 asm("r8") = syscall; + + // we clear all the general registers we can to have some wiggle room + // to extend the behavior of this loader in the future. we don't need + // to clear the xmm registers since the ape loader should be compiled + // with the -mgeneral-regs-only flag. + register void *r8 asm("r8") = syscall; asm volatile("xor\t%%eax,%%eax\n\t" - "xor\t%%ebx,%%ebx\n\t" "xor\t%%r9d,%%r9d\n\t" "xor\t%%r10d,%%r10d\n\t" "xor\t%%r11d,%%r11d\n\t" - "xor\t%%r12d,%%r12d\n\t" - "xor\t%%r13d,%%r13d\n\t" - "xor\t%%r14d,%%r14d\n\t" - "xor\t%%r15d,%%r15d\n\t" + "xor\t%%ebx,%%ebx\n\t" // netbsd dosen't clear this + "xor\t%%r12d,%%r12d\n\t" // netbsd dosen't clear this + "xor\t%%r13d,%%r13d\n\t" // netbsd dosen't clear this + "xor\t%%r14d,%%r14d\n\t" // netbsd dosen't clear this + "xor\t%%r15d,%%r15d\n\t" // netbsd dosen't clear this "mov\t%%rdx,%%rsp\n\t" "xor\t%%edx,%%edx\n\t" "push\t%%rsi\n\t" @@ -535,7 +574,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, "xor\t%%ebp,%%ebp\n\t" "ret" : /* no outputs */ - : "D"(os == FREEBSD ? sp : 0), "S"(e->e_entry), "d"(sp), "c"(os), + : "D"(IsFreebsd() ? sp : 0), "S"(e->e_entry), "d"(sp), "c"(os), "r"(r8) : "memory"); __builtin_unreachable(); @@ -543,7 +582,8 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl, struct ApeLoader *handoff) { - long rc, *auxv; + int rc; + long *auxv; struct ElfEhdr *ehdr; int c, i, fd, os, argc; char *p, *exe, *prog, **argv, **envp, *page; @@ -553,13 +593,15 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl, } u; // detect freebsd - if (di) { + if (handoff) { + os = handoff->os; + } else if (SupportsFreebsd() && di) { os = FREEBSD; sp = (long *)di; - } else if (dl == XNU) { + } else if (SupportsXnu() && dl == XNU) { os = XNU; } else { - os = LINUX; + os = 0; } // extract arguments @@ -586,19 +628,18 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl, // no path searching is needed exe = handoff->prog; fd = handoff->fd; - os = handoff->os; exe = handoff->prog; page = handoff->page; ehdr = (struct ElfEhdr *)handoff->page; } else { // detect openbsd - if (!auxv[0]) { + if (SupportsOpenbsd() && !os && !auxv[0]) { os = OPENBSD; } // detect netbsd - if (os == LINUX) { + if (SupportsNetbsd() && !os) { for (; auxv[0]; auxv += 2) { if (auxv[0] == AT_EXECFN_NETBSD) { os = NETBSD; @@ -607,6 +648,11 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl, } } + // default operating system + if (!os) { + os = LINUX; + } + // we can load via shell, shebang, or binfmt_misc if (argc >= 3 && !StrCmp(argv[1], "-")) { // if the first argument is a hyphen then we give the user the @@ -654,11 +700,13 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl, } #endif - if (Read32(page) == Read32("\177ELF") || Read32(page) == 0xFEEDFACE + 1) { + if ((IsXnu() && Read32(page) == 0xFEEDFACE + 1) || + (!IsXnu() && Read32(page) == Read32("\177ELF"))) { Close(fd, os); Execve(exe, argv, envp, os); } + // TODO(jart): Parse Mach-O for old APE binary support on XNU. for (p = page; p < page + sizeof(u.p); ++p) { if (Read64(p) != Read64("printf '")) continue; for (i = 0, p += 8; p + 3 < page + sizeof(u.p) && (c = *p++) != '\'';) { diff --git a/ape/loader.h b/ape/loader.h index d36d7a567..7080f1370 100644 --- a/ape/loader.h +++ b/ape/loader.h @@ -1,14 +1,13 @@ #ifndef COSMOPOLITAN_APE_LOADER_H_ #define COSMOPOLITAN_APE_LOADER_H_ -#define APE_LOADER_BASE 0x200000 -#define APE_LOADER_SIZE 0x200000 -#define APE_LOADER_BSS (PAGESIZE * 2) -#define APE_LOADER_STACK 0x7f0000000000 -#define APE_LOADER_ENTRY (APE_LOADER_BASE + 0x47) -#define APE_LOADER_SYSCALL (APE_LOADER_BASE + 0x50) -#define APE_BLOCK_BASE 0x7e0000000000 -#define APE_BLOCK_SIZE 0x000200000000 +#define APE_LOADER_BASE 0x200000 +#define APE_LOADER_SIZE 0x200000 +#define APE_LOADER_ENTRY 0x200400 +#define APE_LOADER_BSS (PAGESIZE * 2) +#define APE_LOADER_STACK 0x7f0000000000 +#define APE_BLOCK_BASE 0x7e0000000000 +#define APE_BLOCK_SIZE 0x000200000000 struct ApeLoader { int fd; diff --git a/ape/loader.lds b/ape/loader.lds index e380bdb1b..b689cbae0 100644 --- a/ape/loader.lds +++ b/ape/loader.lds @@ -17,16 +17,16 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ ENTRY(_start) -OUTPUT_FORMAT(binary) SECTIONS { . = 0x200000; .text : { *(.text) *(.rodata .rodata.*) - . = ALIGN(4096); + . = ALIGN(64); } filesz = . - ehdr; + textsz = . - _start; .bss ALIGN(4096) : { bss = .; *(.bss) @@ -39,3 +39,4 @@ SECTIONS { } bsssize = SIZEOF(.bss); +textoff = _start - ehdr; diff --git a/build/bootstrap/ape b/build/bootstrap/ape deleted file mode 100644 index d8857f6f44bdfd26b55648507883c54887dfa155..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmeGe{cjWJ`OdK$CnTKtFdr?Hm&#Ge+9X_-0L~Kdfe&6!X9&dsI-sdzJCMz>Q~OMa zMw_5Zy1Y5ALe(bqhoMQGv_hp#u$48iH8_qMNIybIJBmPUH?_109t|IA2r#%k@5NaM z-TnhC``+j4eZHUP+$u_IO)Q(kWIiTlCBp)|jzI?HdEm z!)=vw7}Xcv4Q@<9!`y9oy_VCA1^ zBGwHoaWE^%}$0-V&~QPoUYld ztE-ZCbyl)iPj=4cu|Al-gf-bQ4P3B;K{5sou;9Q*HemXPCuokkE8)S3sgtcnxCa+A zpwQiAHi_*?nv-PuI(GKQ$}qWx3wv?lRm=`y=e0QEdS-KO?Z+nt<<|V>EG329Tu+`= zaGp(AvEG}$C>&wkB-v*u%l=N8q~oCET7v1@@D_ry^d>KH&SA%Kcohf-b_vbR2XXRc=Vk|ui%H$l93xGHS+DN&#Ju$WolQDjLhp=7P z(QgsqHX}SY`prFE=f{CF@+Cm+$;1XpEm#apNh^AS8oMZTnHPAqvIUU+xs?_2EWGcI zp2aZD7NOI<5aR1ge~QUxRKx3&8uEp>Wy18*Dy;t8 z#t%!Hr53hVSKeHqtIXzFaV?S4J|O4P(M`Kn3?^1%Wh6^d1M|RBgq6N|m}HH<3Hg(k z7~SuH%Og4e`hNG*ZqV(&d7QS;X;1*Mt+8TljZGpqJfwfL9(3Tq1fNvyvM1t{ovVSAJH~>AR49vttazIJlj(O?1p!5%*baX%H)KAL=9(~ZGTv_4m80Xs4a2JYn z8d@qdFZf&mcpsNVA)^~Dj73hfO+=S<+7tDb4%&|#f}?#ct%SE=lB>bfd^Ado(x zH*FG>FW5sS*(@mUn+~yZJ|=k%fX$ffg~@T=jIVN&?G6VnyocE{p1?=2X(Y!ykst6V zr}dEvXw+xv7{gd4F-f(|05d-UGZLY%mHJz{4*rb5lyU9Lpr^g6cLaO9=UtzrX;ZX;54l)2uR<#z|0;?=UE*J8{uCB7VuJ-Xnep{ujDlrplZX27P z;i@RJC5#t0tf^jW`i!fy=r42NUPm&KjWx?0sD?xex+#fRj>7@lysgp;V(3Ro%`#3jZXaj<8P1 zOSFnwK5a&l8odp9+gJ5I>>4_1K(7Hh*Zvv^js6K<4F0AN3dLg4SOsF>i|YLi;ZTs0 zBGD=)mno@hh*Xp$;<1u&G~f?^hXS1`ViIxx&QJxSS`ey!X2UwPO?YPAX8vjVEPcAT zxOhh{aOj816#bXXQbUHHlo>o4IMbdwHh44~Zb40hZ^h2E4<4-x4<18<$My^!3#5+y zhY*hXgP|DO%@;>=1JS0ISi{a;GAdnKT8e&}h|3L;5b}pZd;F1L%#UKxx=>7xBRLU? zgj#ZU$#PS?qNF4vSR9UqOTe$rmn(4LS16$k5fGEw;J$izbaAR|YkDBkD~hZ#sT3f0Oj5b)wEB>HN_t>T&t zwb38gMO~x}Z|!<<>pF4$4@<=iw;>pc$lF9u?HWngv}uPSC9O4(Wn~Y_xCNguB|_m+ zY13*$rfF9&7Dtf~)KQKi2%#Z@>KkHl88tz*j0hn!A%7S_D1n6RuM3A5p;|PA$h#wXas%Ah->s ysJR4HudUt61fq#>5E(gc0F9ZKQz%^jfRFXX+@f~6Gnj|a!yG*9gYV74fqw%EhS9A6 diff --git a/build/bootstrap/ape.elf b/build/bootstrap/ape.elf new file mode 100755 index 0000000000000000000000000000000000000000..b6da8fcb391abaffac38ac42011abfd7f9f9823a GIT binary patch literal 4224 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 literal 0 HcmV?d00001 diff --git a/build/bootstrap/apetest.com b/build/bootstrap/apetest.com new file mode 100755 index 0000000000000000000000000000000000000000..f19ee992d3da4de600ac219573db37a5549d73f4 GIT binary patch literal 20480 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 literal 0 HcmV?d00001 diff --git a/build/sanitycheck b/build/sanitycheck index 7a06eb647..3bd95062f 100755 --- a/build/sanitycheck +++ b/build/sanitycheck @@ -27,28 +27,38 @@ EOF exit 1 fi -build/sanitycheck2 -if [ $? -ne 123 ]; then +if [ ! -f /proc/sys/fs/binfmt_misc/status ]; then + exit 0 +fi + +STATUS="$(build/bootstrap/apetest.com)" +if [ x"$STATUS" != xsuccess ]; then cat <<'EOF' >&2 ERROR - Thompson Shell Backwards Compatibility Issue Detected + APE Execution error. DETAILS - Your system has likely been configured to use binfmt_misc and wine. - You need to run the command below which will install a /usr/bin/ape - program and then register it with binfmt_misc. See ape/loader.c for - source code and technical details. + Your system has probably been configured to use binfmt_misc. You need + to run the command below to install /usr/bin/ape and register it with + binfmt_misc. See ape/loader.c for source code, and technical details. WORKAROUND ape/apeinstall.sh +NOTES + + If it still doesn't work, possibly due to an overly aggressive WINE + or WSL registration, or possibly due to the ordering of definitions, + then one troubleshooting step is to just unregister everything using + sudo sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/status' and try again. + SEE ALSO - https://justine.storage.googleapis.com/ape.html + https://justine.lol/ape.html EOF kill $1 diff --git a/build/sanitycheck2 b/build/sanitycheck2 deleted file mode 100755 index 4e74e3964..000000000 --- a/build/sanitycheck2 +++ /dev/null @@ -1,16 +0,0 @@ -MZboop=123 -exit $MZboop - - - - - - - - - - - - - - diff --git a/libc/calls/getprogramexecutablename.greg.c b/libc/calls/getprogramexecutablename.greg.c index f3ecbab09..b6ab8a1e6 100644 --- a/libc/calls/getprogramexecutablename.greg.c +++ b/libc/calls/getprogramexecutablename.greg.c @@ -34,12 +34,22 @@ char program_executable_name[PATH_MAX]; +static inline char *StrCat(char buf[PATH_MAX], const char *a, const char *b) { + char *p, *e; + p = buf; + e = buf + PATH_MAX; + while (*a && p < e) *p++ = *a++; + while (*b && p < e) *p++ = *b++; + return buf; +} + static inline void GetProgramExecutableNameImpl(char *p, char *e) { char *q; ssize_t rc; size_t i, n; union { int cmd[4]; + char path[PATH_MAX]; char16_t path16[PATH_MAX]; } u; @@ -61,7 +71,11 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) { return; } - if (__argc && (q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) { + // if argv[0] exists then turn it into an absolute path. we also try + // adding a .com suffix since the ape auto-appends it when resolving + if (__argc && (((q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) || + ((q = StrCat(u.path, __argv[0], ".com")) && + !sys_faccessat(AT_FDCWD, q, F_OK, 0)))) { if (*q != '/') { if (q[0] == '.' && q[1] == '/') { q += 2; @@ -78,12 +92,12 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) { return; } + // if argv[0] doesn't exist, then fallback to interpreter name if ((rc = sys_readlinkat(AT_FDCWD, "/proc/self/exe", p, e - p - 1)) > 0 || (rc = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", p, e - p - 1)) > 0) { p[rc] = 0; return; } - if (IsFreebsd() || IsNetbsd()) { u.cmd[0] = CTL_KERN; u.cmd[1] = KERN_PROC; @@ -101,7 +115,7 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) { } /** - * Returns absolute path of executable. + * Returns absolute path of program. */ char *GetProgramExecutableName(void) { int e; diff --git a/libc/calls/reservefd.c b/libc/calls/reservefd.c index a8ad44180..81a0d45c9 100644 --- a/libc/calls/reservefd.c +++ b/libc/calls/reservefd.c @@ -58,7 +58,7 @@ int __ensurefds_unlocked(int fd) { if (!(p2 = weaken(malloc)(n2 * sizeof(*p1)))) return -1; __cxa_atexit(FreeOldFdsArray, p1, 0); memcpy(p2, p1, n1 * sizeof(*p1)); - bzero(p2 + n1, (p2 + n2) - (p2 + n1)); + bzero(p2 + n1, (n2 - n1) * sizeof(*p1)); g_fds.p = p2; g_fds.n = n2; return fd; diff --git a/libc/calls/write-nt.c b/libc/calls/write-nt.c index 4999f6ce8..5ddc51988 100644 --- a/libc/calls/write-nt.c +++ b/libc/calls/write-nt.c @@ -16,10 +16,15 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/weaken.h" #include "libc/calls/internal.h" #include "libc/calls/sig.internal.h" +#include "libc/calls/strace.internal.h" +#include "libc/errno.h" #include "libc/nt/errors.h" #include "libc/nt/runtime.h" +#include "libc/runtime/internal.h" +#include "libc/runtime/runtime.h" #include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" @@ -37,12 +42,18 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size, // return ebadf(); /* handled by consts.sh */ // case kNtErrorNotEnoughQuota: // return edquot(); /* handled by consts.sh */ - case kNtErrorBrokenPipe: // broken pipe - case kNtErrorNoData: // closing named pipe - __sig_raise(SIGPIPE, SI_KERNEL); // - return epipe(); // - case kNtErrorAccessDenied: // write doesn't return EACCESS - return ebadf(); // + case kNtErrorBrokenPipe: // broken pipe + case kNtErrorNoData: // closing named pipe + if (weaken(__sig_raise)) { + weaken(__sig_raise)(SIGPIPE, SI_KERNEL); + return epipe(); + } else { + STRACE("broken pipe"); + __restorewintty(); + _Exit(128 + EPIPE); + } + case kNtErrorAccessDenied: // write doesn't return EACCESS + return ebadf(); // default: return __winerr(); } diff --git a/libc/intrin/kdos2errno.S b/libc/intrin/kdos2errno.S index f09390e7f..3bab83afd 100644 --- a/libc/intrin/kdos2errno.S +++ b/libc/intrin/kdos2errno.S @@ -27,7 +27,7 @@ .long \systemv - kDos2Errno .endm - .section .rodata + .section .rodata,"a",@progbits .underrun kDos2Errno: // .e kNtErrorInvalidFunction,ENOSYS # in consts.sh diff --git a/libc/log/showcrashreports.c b/libc/log/showcrashreports.c index 29bdfeddf..7d317b07d 100644 --- a/libc/log/showcrashreports.c +++ b/libc/log/showcrashreports.c @@ -106,8 +106,10 @@ void ShowCrashReports(void) { bzero(&ss, sizeof(ss)); ss.ss_flags = 0; ss.ss_size = SIGSTKSZ; + // FreeBSD sigaltstack() will EFAULT if we use MAP_STACK here + // OpenBSD sigaltstack() auto-applies MAP_STACK to the memory if ((ss.ss_sp = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE, - MAP_STACK | MAP_ANONYMOUS, -1, 0))) { + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))) { if (!sigaltstack(&ss, &g_oldsigaltstack)) { __cxa_atexit(FreeSigAltStack, ss.ss_sp, 0); } else { diff --git a/libc/runtime/getinterpreterexecutablename.c b/libc/runtime/getinterpreterexecutablename.c index 2f3aa6c24..898731a1f 100644 --- a/libc/runtime/getinterpreterexecutablename.c +++ b/libc/runtime/getinterpreterexecutablename.c @@ -51,6 +51,9 @@ char *GetInterpreterExecutableName(char *p, size_t n) { if (n < 2) { errno = ENAMETOOLONG; } else if (IsWindows() || IsXnu()) { + // TODO(jart): Does XNU guarantee argv[0] is legit? + // Otherwise we should return NULL. + // What about OpenBSD? if (strlen(GetProgramExecutableName()) < n) { strcpy(p, GetProgramExecutableName()); return p; diff --git a/libc/runtime/getsymboltable.c b/libc/runtime/getsymboltable.c index cc7988072..45c8c4750 100644 --- a/libc/runtime/getsymboltable.c +++ b/libc/runtime/getsymboltable.c @@ -96,7 +96,13 @@ static struct SymbolTable *GetSymbolTableFromZip(struct Zipos *zipos) { * @note This code can't depend on dlmalloc() */ static struct SymbolTable *GetSymbolTableFromElf(void) { - return OpenSymbolTable(FindDebugBinary()); + int e; + const char *s; + if ((s = FindDebugBinary())) { + return OpenSymbolTable(s); + } else { + return 0; + } } /** @@ -117,7 +123,7 @@ static struct SymbolTable *GetSymbolTableFromElf(void) { * Function tracing is disabled throughout the duration of this call. * Backtraces and other core runtime functionality depend on this. * - * @return symbol table, or NULL w/ errno on first call + * @return symbol table, or NULL if not found */ struct SymbolTable *GetSymbolTable(void) { struct Zipos *z; diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index cb58ffb8c..32f0eade1 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -323,7 +323,7 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags, clashes = OverlapsImageSpace(p, size) || OverlapsExistingMapping(p, size); - if ((flags & MAP_FIXED_NOREPLACE) && clashes) { + if ((flags & MAP_FIXED_NOREPLACE) == MAP_FIXED_NOREPLACE && clashes) { STRACE("noreplace overlaps existing"); return VIP(eexist()); } @@ -464,14 +464,21 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags, * compile-time checks to ensure some char[8192] vars will not * create an undetectable overflow into another thread's stack * Your `flags` may optionally bitwise or any of the following: - * - `MAP_FIXED` in which case `addr` becomes more than a hint - * - `MAP_FIXED_NOREPLACE` to protect existing maps (Linux-only) * - `MAP_ANONYMOUS` in which case `fd == -1` should be the case + * - `MAP_FIXED` in which case `addr` becomes more than a hint + * - `MAP_FIXED_NOREPLACE` to protect existing mappings; this is + * always polyfilled by mmap() which tracks its own memory and + * removed before passing to the kernel, in order to support + * old versions; if you believe mappings exist which only the + * kernel knows, then this flag may be passed to sys_mmap() on + * Linux 4.17+ and FreeBSD (where it has multiple bits) * - `MAP_CONCEAL` is FreeBSD/NetBSD/OpenBSD-only * - `MAP_NORESERVE` is Linux/XNU/NetBSD-only - * - `MAP_LOCKED` is Linux-only - * - `MAP_POPULATE` is Linux-only + * - `MAP_POPULATE` is Linux/FreeBSD-only * - `MAP_NONBLOCK` is Linux-only + * - `MAP_NOSYNC` is FreeBSD-only + * - `MAP_INHERIT` is NetBSD-only + * - `MAP_LOCKED` is Linux-only * @param fd is an open()'d file descriptor, whose contents shall be * made available w/ automatic reading at the chosen address and * must be -1 if MAP_ANONYMOUS is specified diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 3be697aa8..cd2ffc2a6 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -224,22 +224,25 @@ syscon mmap MAP_PRIVATE 2 2 2 2 2 2 # forced consensus & faked nt syscon mmap MAP_STACK 6 6 6 6 6 6 # our definition syscon mmap MAP_TYPE 15 15 15 15 15 15 # mask for type of mapping syscon mmap MAP_FIXED 0x00000010 0x00000010 0x00000010 0x00000010 0x00000010 0x00000010 # unix consensus; openbsd appears to forbid; faked nt -syscon mmap MAP_FIXED_NOREPLACE 0x08000000 0x08000000 0x08000000 0x08000000 0x08000000 0x08000000 # handled and defined by cosmo runtime; 0x100000 on linux 4.7+ +syscon mmap MAP_FIXED_NOREPLACE 0x08000000 0x00004010 0x08000000 0x08000000 0x08000000 0x08000000 # handled and defined by cosmo runtime; 0x100000 on linux 4.7+; MAP_FIXED|MAP_EXCL on FreeBSD syscon mmap MAP_ANONYMOUS 0x00000020 0x00001000 0x00001000 0x00001000 0x00001000 0x00000020 # bsd consensus; faked nt syscon mmap MAP_GROWSDOWN 0x00000100 0 0 0 0 0 # use MAP_STACK; abstracted by MAP_STACK; may be passed to __sys_mmap() for low-level Linux fiddling -syscon mmap MAP_CONCEAL 0 0 0x00020000 0x00008000 0x00008000 0 # omit from core dumps; MAP_NOCORE on FreeBSD syscon mmap MAP_LOCKED 0x00002000 0 0 0 0 0 syscon mmap MAP_NORESERVE 0x00004000 0x00000040 0 0 0x00000040 0 # Linux calls it "reserve"; NT calls it "commit"? which is default? -syscon mmap MAP_POPULATE 0x00008000 0 0 0 0 0 # can avoid madvise(MADV_WILLNEED) on private file mapping +syscon mmap MAP_POPULATE 0x00008000 0 0x00040000 0 0 0 # MAP_PREFAULT_READ on FreeBSD; can avoid madvise(MADV_WILLNEED) on private file mapping syscon mmap MAP_NONBLOCK 0x00010000 0 0 0 0 0 syscon mmap MAP_HUGETLB 0x00040000 0 0 0 0 0x80000000 # kNtSecLargePages +syscon mmap MAP_INHERIT -1 -1 -1 -1 0x00000080 -1 # make it inherit across execve() +syscon mmap MAP_HASSEMAPHORE 0 0x00000200 0x00000200 0 0x00000200 0 # does it matter on x86? +syscon mmap MAP_NOSYNC 0 0 0x00000800 0 0 0 # flush to physical media only when necessary rather than gratuitously; be sure to use write() rather than ftruncate() with this! +syscon mmap MAP_CONCEAL 0 0 0x00020000 0x00008000 0x00008000 0 # omit from core dumps; MAP_NOCORE on FreeBSD syscon mmap MAP_HUGE_MASK 63 0 0 0 0 0 syscon mmap MAP_HUGE_SHIFT 26 0 0 0 0 0 -syscon compat MAP_NOCORE 0 0 0x0020000 0x8000 0x8000 0 # use MAP_CONCEAL -syscon compat MAP_ANON 0x20 0x1000 0x0001000 0x1000 0x1000 0x20 # bsd consensus; faked nt -syscon compat MAP_EXECUTABLE 0x1000 0 0 0 0 0 # ignored -syscon compat MAP_DENYWRITE 0x0800 0 0 0 0 0 -syscon compat MAP_32BIT 0x40 0 0x080000 0 0 0 # iffy +syscon compat MAP_NOCORE 0 0 0x00020000 0x00008000 0x00008000 0 # use MAP_CONCEAL +syscon compat MAP_ANON 0x00000020 0x00001000 0x00001000 0x00001000 0x00001000 0x00000020 # bsd consensus; faked nt +syscon compat MAP_EXECUTABLE 0x00001000 0 0 0 0 0 # ignored +syscon compat MAP_DENYWRITE 0x00000800 0 0 0 0 0 +syscon compat MAP_32BIT 0x00000040 0 0x00080000 0 0 0 # iffy # madvise() flags # @@ -337,36 +340,6 @@ syscon waitid WEXITED 4 4 0x10 0 32 0 syscon waitid WSTOPPED 2 8 2 0 2 0 syscon waitid WNOWAIT 0x01000000 0x20 8 0 0x10000 0 -# stat::st_mode constants -# -# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary -syscon stat S_IFREG 0100000 0100000 0100000 0100000 0100000 0100000 # regular file (unix consensus; faked nt) -syscon stat S_IFBLK 0060000 0060000 0060000 0060000 0060000 0060000 # block device (unix consensus; faked nt) -syscon stat S_IFCHR 0020000 0020000 0020000 0020000 0020000 0020000 # character device (unix consensus; faked nt) -syscon stat S_IFDIR 0040000 0040000 0040000 0040000 0040000 0040000 # directory (unix consensus; faked nt) -syscon stat S_IFIFO 0010000 0010000 0010000 0010000 0010000 0010000 # pipe (unix consensus; faked nt) -syscon stat S_IFLNK 0120000 0120000 0120000 0120000 0120000 0120000 # symbolic link (unix consensus; faked nt) -syscon stat S_IFSOCK 0140000 0140000 0140000 0140000 0140000 0140000 # socket (unix consensus; faked nt) -syscon stat S_IFMT 0170000 0170000 0170000 0170000 0170000 0170000 # FILE TYPE MASK (unix consensus; faked nt) -syscon stat S_ISVTX 0001000 0001000 0001000 0001000 0001000 0001000 # THE STICKY BIT (unix consensus; faked nt) -syscon stat S_ISGID 0002000 0002000 0002000 0002000 0002000 0002000 # the setgid bit (unix consensus; faked nt) -syscon stat S_ISUID 0004000 0004000 0004000 0004000 0004000 0004000 # the setuid bit (unix consensus; faked nt) -syscon stat S_IEXEC 0000100 0000100 0000100 0000100 0000100 0000100 # just use octal (unix consensus; faked nt) -syscon stat S_IWRITE 0000200 0000200 0000200 0000200 0000200 0000200 # just use octal (unix consensus; faked nt) -syscon stat S_IREAD 0000400 0000400 0000400 0000400 0000400 0000400 # just use octal (unix consensus; faked nt) -syscon stat S_IXUSR 0000100 0000100 0000100 0000100 0000100 0000100 # just use octal (unix consensus; faked nt) -syscon stat S_IWUSR 0000200 0000200 0000200 0000200 0000200 0000200 # just use octal (unix consensus; faked nt) -syscon stat S_IRUSR 0000400 0000400 0000400 0000400 0000400 0000400 # just use octal (unix consensus; faked nt) -syscon stat S_IRWXU 0000700 0000700 0000700 0000700 0000700 0000700 # just use octal (unix consensus; faked nt) -syscon stat S_IXGRP 0000010 0000010 0000010 0000010 0000010 0000010 # just use octal (unix consensus; faked nt) -syscon stat S_IWGRP 0000020 0000020 0000020 0000020 0000020 0000020 # just use octal (unix consensus; faked nt) -syscon stat S_IRGRP 0000040 0000040 0000040 0000040 0000040 0000040 # just use octal (unix consensus; faked nt) -syscon stat S_IRWXG 0000070 0000070 0000070 0000070 0000070 0000070 # just use octal (unix consensus; faked nt) -syscon stat S_IXOTH 0000001 0000001 0000001 0000001 0000001 0000001 # just use octal (unix consensus; faked nt) -syscon stat S_IWOTH 0000002 0000002 0000002 0000002 0000002 0000002 # just use octal (unix consensus; faked nt) -syscon stat S_IROTH 0000004 0000004 0000004 0000004 0000004 0000004 # just use octal (unix consensus; faked nt) -syscon stat S_IRWXO 0000007 0000007 0000007 0000007 0000007 0000007 # just use octal (unix consensus; faked nt) - # fcntl() # # group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary @@ -605,7 +578,8 @@ syscon sicode SYS_USER_DISPATCH 2 -1 -1 -1 -1 -1 # SIGSYS; syscall # sigaltstack() values # # group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary -syscon ss SIGSTKSZ 0x2000 0x020000 0x8800 0x7000 0x7000 0x2000 +syscon ss SIGSTKSZ 8192 131072 34816 28672 28672 8192 # overlayed with STACKSIZE; you need to #undef SIGSTKSZ to access this symbol +syscon ss MINSIGSTKSZ 2048 32768 2048 12288 8192 2048 # overlayed with 32768; you need to #undef MINSIGSTKSZ to access this symbol syscon ss SS_ONSTACK 1 1 1 1 1 1 # unix consensus syscon ss SS_DISABLE 2 4 4 4 4 2 # bsd consensus @@ -3131,7 +3105,6 @@ syscon misc CSTATUS 0 20 20 255 255 0 syscon misc DEAD_PROCESS 8 8 7 0 0 0 syscon misc FNM_NOSYS -1 -1 -1 2 2 0 syscon misc INIT_PROCESS 5 5 5 0 0 0 -syscon misc MINSIGSTKSZ 0x0800 0x8000 0x0800 0x3000 0x2000 0 syscon misc MQ_PRIO_MAX 0x8000 0 0x40 0 0 0 syscon misc MTERASE 13 0 12 9 9 0 syscon misc MTLOAD 30 0 19 0 0 0 diff --git a/libc/sysv/consts/MAP_32BIT.S b/libc/sysv/consts/MAP_32BIT.S index 69d1006da..992a099ca 100644 --- a/libc/sysv/consts/MAP_32BIT.S +++ b/libc/sysv/consts/MAP_32BIT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon compat,MAP_32BIT,0x40,0,0x080000,0,0,0 +.syscon compat,MAP_32BIT,0x00000040,0,0x00080000,0,0,0 diff --git a/libc/sysv/consts/MAP_ANON.S b/libc/sysv/consts/MAP_ANON.S index a1eb02bfe..a5bd6ea5b 100644 --- a/libc/sysv/consts/MAP_ANON.S +++ b/libc/sysv/consts/MAP_ANON.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon compat,MAP_ANON,0x20,0x1000,0x0001000,0x1000,0x1000,0x20 +.syscon compat,MAP_ANON,0x00000020,0x00001000,0x00001000,0x00001000,0x00001000,0x00000020 diff --git a/libc/sysv/consts/MAP_DENYWRITE.S b/libc/sysv/consts/MAP_DENYWRITE.S index 98efad2ec..3f495ded7 100644 --- a/libc/sysv/consts/MAP_DENYWRITE.S +++ b/libc/sysv/consts/MAP_DENYWRITE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon compat,MAP_DENYWRITE,0x0800,0,0,0,0,0 +.syscon compat,MAP_DENYWRITE,0x00000800,0,0,0,0,0 diff --git a/libc/sysv/consts/MAP_EXECUTABLE.S b/libc/sysv/consts/MAP_EXECUTABLE.S index e2efd0d26..078c5b380 100644 --- a/libc/sysv/consts/MAP_EXECUTABLE.S +++ b/libc/sysv/consts/MAP_EXECUTABLE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon compat,MAP_EXECUTABLE,0x1000,0,0,0,0,0 +.syscon compat,MAP_EXECUTABLE,0x00001000,0,0,0,0,0 diff --git a/libc/sysv/consts/MAP_FILE.S b/libc/sysv/consts/MAP_FILE.S index 13a1fe32c..55800b2c4 100644 --- a/libc/sysv/consts/MAP_FILE.S +++ b/libc/sysv/consts/MAP_FILE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon compat,MAP_FILE,0,0,0,0,0,0 +.syscon mmap,MAP_FILE,0,0,0,0,0,0 diff --git a/libc/sysv/consts/MAP_FIXED_NOREPLACE.S b/libc/sysv/consts/MAP_FIXED_NOREPLACE.S index 90b4f3369..0056e9e66 100644 --- a/libc/sysv/consts/MAP_FIXED_NOREPLACE.S +++ b/libc/sysv/consts/MAP_FIXED_NOREPLACE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon mmap,MAP_FIXED_NOREPLACE,0x08000000,0x08000000,0x08000000,0x08000000,0x08000000,0x08000000 +.syscon mmap,MAP_FIXED_NOREPLACE,0x08000000,0x00004010,0x08000000,0x08000000,0x08000000,0x08000000 diff --git a/libc/sysv/consts/MAP_HASSEMAPHORE.S b/libc/sysv/consts/MAP_HASSEMAPHORE.S new file mode 100644 index 000000000..807f606aa --- /dev/null +++ b/libc/sysv/consts/MAP_HASSEMAPHORE.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon mmap,MAP_HASSEMAPHORE,0,0x00000200,0x00000200,0,0x00000200,0 diff --git a/libc/sysv/consts/MAP_INHERIT.S b/libc/sysv/consts/MAP_INHERIT.S new file mode 100644 index 000000000..7216389f8 --- /dev/null +++ b/libc/sysv/consts/MAP_INHERIT.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon mmap,MAP_INHERIT,-1,-1,-1,-1,0x00000080,-1 diff --git a/libc/sysv/consts/MAP_NOCORE.S b/libc/sysv/consts/MAP_NOCORE.S index c0e6b263f..bb2e48762 100644 --- a/libc/sysv/consts/MAP_NOCORE.S +++ b/libc/sysv/consts/MAP_NOCORE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon compat,MAP_NOCORE,0,0,0x0020000,0x8000,0x8000,0 +.syscon compat,MAP_NOCORE,0,0,0x00020000,0x00008000,0x00008000,0 diff --git a/libc/sysv/consts/MAP_NOSYNC.S b/libc/sysv/consts/MAP_NOSYNC.S new file mode 100644 index 000000000..054342f35 --- /dev/null +++ b/libc/sysv/consts/MAP_NOSYNC.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon mmap,MAP_NOSYNC,0,0,0x00000800,0,0,0 diff --git a/libc/sysv/consts/MAP_POPULATE.S b/libc/sysv/consts/MAP_POPULATE.S index 36d7843ec..bca16d04f 100644 --- a/libc/sysv/consts/MAP_POPULATE.S +++ b/libc/sysv/consts/MAP_POPULATE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon mmap,MAP_POPULATE,0x00008000,0,0,0,0,0 +.syscon mmap,MAP_POPULATE,0x00008000,0,0x00040000,0,0,0 diff --git a/libc/sysv/consts/MINSIGSTKSZ.S b/libc/sysv/consts/MINSIGSTKSZ.S index a5c500930..23a7e9ec8 100644 --- a/libc/sysv/consts/MINSIGSTKSZ.S +++ b/libc/sysv/consts/MINSIGSTKSZ.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,MINSIGSTKSZ,0x0800,0x8000,0x0800,0x3000,0x2000,0 +.syscon ss,MINSIGSTKSZ,2048,32768,2048,12288,8192,2048 diff --git a/libc/sysv/consts/SIGSTKSZ.S b/libc/sysv/consts/SIGSTKSZ.S index 1a557a4b5..9f00d1765 100644 --- a/libc/sysv/consts/SIGSTKSZ.S +++ b/libc/sysv/consts/SIGSTKSZ.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon ss,SIGSTKSZ,0x2000,0x020000,0x8800,0x7000,0x7000,0x2000 +.syscon ss,SIGSTKSZ,8192,131072,34816,28672,28672,8192 diff --git a/libc/sysv/consts/ST_MANDLOCK.S b/libc/sysv/consts/ST_MANDLOCK.S index e23e806b8..dbfbec538 100644 --- a/libc/sysv/consts/ST_MANDLOCK.S +++ b/libc/sysv/consts/ST_MANDLOCK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon statvfs,ST_MANDLOCK,0x40,0,0,0,0,0 +.syscon statvfs,ST_MANDLOCK,0x0040,0,0,0,0,0 diff --git a/libc/sysv/consts/ST_SYNCHRONOUS.S b/libc/sysv/consts/ST_SYNCHRONOUS.S index 9e7308849..eaec0a049 100644 --- a/libc/sysv/consts/ST_SYNCHRONOUS.S +++ b/libc/sysv/consts/ST_SYNCHRONOUS.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon statvfs,ST_SYNCHRONOUS,0x10,0,0,0,2,0 +.syscon statvfs,ST_SYNCHRONOUS,16,0,0,0,2,0 diff --git a/libc/sysv/consts/ST_WRITE.S b/libc/sysv/consts/ST_WRITE.S index 1945a52f7..84a0035fd 100644 --- a/libc/sysv/consts/ST_WRITE.S +++ b/libc/sysv/consts/ST_WRITE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon statvfs,ST_WRITE,0x80,0,0,0,0,0 +.syscon statvfs,ST_WRITE,0x0080,0,0,0,0,0 diff --git a/libc/sysv/consts/S_IEXEC.S b/libc/sysv/consts/S_IEXEC.S deleted file mode 100644 index cec133e38..000000000 --- a/libc/sysv/consts/S_IEXEC.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IEXEC,0000100,0000100,0000100,0000100,0000100,0000100 diff --git a/libc/sysv/consts/S_IFBLK.S b/libc/sysv/consts/S_IFBLK.S deleted file mode 100644 index bb75920eb..000000000 --- a/libc/sysv/consts/S_IFBLK.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IFBLK,0060000,0060000,0060000,0060000,0060000,0060000 diff --git a/libc/sysv/consts/S_IFCHR.S b/libc/sysv/consts/S_IFCHR.S deleted file mode 100644 index c01847833..000000000 --- a/libc/sysv/consts/S_IFCHR.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IFCHR,0020000,0020000,0020000,0020000,0020000,0020000 diff --git a/libc/sysv/consts/S_IFDIR.S b/libc/sysv/consts/S_IFDIR.S deleted file mode 100644 index 58c96c0de..000000000 --- a/libc/sysv/consts/S_IFDIR.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IFDIR,0040000,0040000,0040000,0040000,0040000,0040000 diff --git a/libc/sysv/consts/S_IFIFO.S b/libc/sysv/consts/S_IFIFO.S deleted file mode 100644 index 634433d4f..000000000 --- a/libc/sysv/consts/S_IFIFO.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IFIFO,0010000,0010000,0010000,0010000,0010000,0010000 diff --git a/libc/sysv/consts/S_IFLNK.S b/libc/sysv/consts/S_IFLNK.S deleted file mode 100644 index 7f07c7498..000000000 --- a/libc/sysv/consts/S_IFLNK.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IFLNK,0120000,0120000,0120000,0120000,0120000,0120000 diff --git a/libc/sysv/consts/S_IFMT.S b/libc/sysv/consts/S_IFMT.S deleted file mode 100644 index af076b5ae..000000000 --- a/libc/sysv/consts/S_IFMT.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IFMT,0170000,0170000,0170000,0170000,0170000,0170000 diff --git a/libc/sysv/consts/S_IFREG.S b/libc/sysv/consts/S_IFREG.S deleted file mode 100644 index 8c859e78c..000000000 --- a/libc/sysv/consts/S_IFREG.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IFREG,0100000,0100000,0100000,0100000,0100000,0100000 diff --git a/libc/sysv/consts/S_IFSOCK.S b/libc/sysv/consts/S_IFSOCK.S deleted file mode 100644 index 3cc80067e..000000000 --- a/libc/sysv/consts/S_IFSOCK.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IFSOCK,0140000,0140000,0140000,0140000,0140000,0140000 diff --git a/libc/sysv/consts/S_IREAD.S b/libc/sysv/consts/S_IREAD.S deleted file mode 100644 index 5e0bee1c4..000000000 --- a/libc/sysv/consts/S_IREAD.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IREAD,0000400,0000400,0000400,0000400,0000400,0000400 diff --git a/libc/sysv/consts/S_IRGRP.S b/libc/sysv/consts/S_IRGRP.S deleted file mode 100644 index ad9f3a6f8..000000000 --- a/libc/sysv/consts/S_IRGRP.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRGRP,0000040,0000040,0000040,0000040,0000040,0000040 diff --git a/libc/sysv/consts/S_IROTH.S b/libc/sysv/consts/S_IROTH.S deleted file mode 100644 index 6179fbf38..000000000 --- a/libc/sysv/consts/S_IROTH.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IROTH,0000004,0000004,0000004,0000004,0000004,0000004 diff --git a/libc/sysv/consts/S_IRUSR.S b/libc/sysv/consts/S_IRUSR.S deleted file mode 100644 index 7720d0f60..000000000 --- a/libc/sysv/consts/S_IRUSR.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRUSR,0000400,0000400,0000400,0000400,0000400,0000400 diff --git a/libc/sysv/consts/S_IRWXG.S b/libc/sysv/consts/S_IRWXG.S deleted file mode 100644 index e35589566..000000000 --- a/libc/sysv/consts/S_IRWXG.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRWXG,0000070,0000070,0000070,0000070,0000070,0000070 diff --git a/libc/sysv/consts/S_IRWXO.S b/libc/sysv/consts/S_IRWXO.S deleted file mode 100644 index c9a4db418..000000000 --- a/libc/sysv/consts/S_IRWXO.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRWXO,0000007,0000007,0000007,0000007,0000007,0000007 diff --git a/libc/sysv/consts/S_IRWXU.S b/libc/sysv/consts/S_IRWXU.S deleted file mode 100644 index 3a291a499..000000000 --- a/libc/sysv/consts/S_IRWXU.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRWXU,0000700,0000700,0000700,0000700,0000700,0000700 diff --git a/libc/sysv/consts/S_ISGID.S b/libc/sysv/consts/S_ISGID.S deleted file mode 100644 index 108508726..000000000 --- a/libc/sysv/consts/S_ISGID.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_ISGID,0002000,0002000,0002000,0002000,0002000,0002000 diff --git a/libc/sysv/consts/S_ISUID.S b/libc/sysv/consts/S_ISUID.S deleted file mode 100644 index 170183946..000000000 --- a/libc/sysv/consts/S_ISUID.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_ISUID,0004000,0004000,0004000,0004000,0004000,0004000 diff --git a/libc/sysv/consts/S_ISVTX.S b/libc/sysv/consts/S_ISVTX.S deleted file mode 100644 index 33636aff5..000000000 --- a/libc/sysv/consts/S_ISVTX.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_ISVTX,0001000,0001000,0001000,0001000,0001000,0001000 diff --git a/libc/sysv/consts/S_IWGRP.S b/libc/sysv/consts/S_IWGRP.S deleted file mode 100644 index 27dd51e4c..000000000 --- a/libc/sysv/consts/S_IWGRP.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IWGRP,0000020,0000020,0000020,0000020,0000020,0000020 diff --git a/libc/sysv/consts/S_IWOTH.S b/libc/sysv/consts/S_IWOTH.S deleted file mode 100644 index 61e7b7ae8..000000000 --- a/libc/sysv/consts/S_IWOTH.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IWOTH,0000002,0000002,0000002,0000002,0000002,0000002 diff --git a/libc/sysv/consts/S_IWRITE.S b/libc/sysv/consts/S_IWRITE.S deleted file mode 100644 index df2360188..000000000 --- a/libc/sysv/consts/S_IWRITE.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IWRITE,0000200,0000200,0000200,0000200,0000200,0000200 diff --git a/libc/sysv/consts/S_IWUSR.S b/libc/sysv/consts/S_IWUSR.S deleted file mode 100644 index 7df8df706..000000000 --- a/libc/sysv/consts/S_IWUSR.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IWUSR,0000200,0000200,0000200,0000200,0000200,0000200 diff --git a/libc/sysv/consts/S_IXGRP.S b/libc/sysv/consts/S_IXGRP.S deleted file mode 100644 index f23c82907..000000000 --- a/libc/sysv/consts/S_IXGRP.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IXGRP,0000010,0000010,0000010,0000010,0000010,0000010 diff --git a/libc/sysv/consts/S_IXOTH.S b/libc/sysv/consts/S_IXOTH.S deleted file mode 100644 index ff3cc2474..000000000 --- a/libc/sysv/consts/S_IXOTH.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IXOTH,0000001,0000001,0000001,0000001,0000001,0000001 diff --git a/libc/sysv/consts/S_IXUSR.S b/libc/sysv/consts/S_IXUSR.S deleted file mode 100644 index fb7f231b5..000000000 --- a/libc/sysv/consts/S_IXUSR.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IXUSR,0000100,0000100,0000100,0000100,0000100,0000100 diff --git a/libc/sysv/consts/map.h b/libc/sysv/consts/map.h index 725ffac82..028aeaf9a 100644 --- a/libc/sysv/consts/map.h +++ b/libc/sysv/consts/map.h @@ -12,13 +12,17 @@ extern const long MAP_DENYWRITE; extern const long MAP_EXECUTABLE; extern const long MAP_FILE; extern const long MAP_FIXED; +extern const long MAP_FIXED_NOREPLACE; extern const long MAP_GROWSDOWN; +extern const long MAP_HASSEMAPHORE; extern const long MAP_HUGETLB; extern const long MAP_HUGE_MASK; extern const long MAP_HUGE_SHIFT; +extern const long MAP_INHERIT; extern const long MAP_LOCKED; extern const long MAP_NONBLOCK; extern const long MAP_NORESERVE; +extern const long MAP_NOSYNC; extern const long MAP_POPULATE; extern const long MAP_PRIVATE; extern const long MAP_SHARED; @@ -26,28 +30,30 @@ extern const long MAP_SHARED; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#define MAP_FILE 0 -#define MAP_SHARED 1 -#define MAP_PRIVATE 2 -#define MAP_STACK 6 -#define MAP_TYPE 15 -#define MAP_FIXED 16 -#define MAP_FIXED_NOREPLACE 0x8000000 +#define MAP_FILE 0 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_STACK 6 +#define MAP_TYPE 15 +#define MAP_FIXED 16 -#define MAP_32BIT SYMBOLIC(MAP_32BIT) -#define MAP_ANONYMOUS SYMBOLIC(MAP_ANONYMOUS) -#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL) -#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL) -#define MAP_DENYWRITE SYMBOLIC(MAP_DENYWRITE) -#define MAP_EXECUTABLE SYMBOLIC(MAP_EXECUTABLE) -#define MAP_GROWSDOWN SYMBOLIC(MAP_GROWSDOWN) -#define MAP_HUGETLB SYMBOLIC(MAP_HUGETLB) -#define MAP_HUGE_MASK SYMBOLIC(MAP_HUGE_MASK) -#define MAP_HUGE_SHIFT SYMBOLIC(MAP_HUGE_SHIFT) -#define MAP_LOCKED SYMBOLIC(MAP_LOCKED) -#define MAP_NONBLOCK SYMBOLIC(MAP_NONBLOCK) -#define MAP_NORESERVE SYMBOLIC(MAP_NORESERVE) -#define MAP_POPULATE SYMBOLIC(MAP_POPULATE) +#define MAP_32BIT SYMBOLIC(MAP_32BIT) +#define MAP_ANONYMOUS SYMBOLIC(MAP_ANONYMOUS) +#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL) +#define MAP_DENYWRITE SYMBOLIC(MAP_DENYWRITE) +#define MAP_EXECUTABLE SYMBOLIC(MAP_EXECUTABLE) +#define MAP_FIXED_NOREPLACE SYMBOLIC(MAP_FIXED_NOREPLACE) +#define MAP_GROWSDOWN SYMBOLIC(MAP_GROWSDOWN) +#define MAP_HASSEMAPHORE SYMBOLIC(MAP_HASSEMAPHORE) +#define MAP_HUGETLB SYMBOLIC(MAP_HUGETLB) +#define MAP_HUGE_MASK SYMBOLIC(MAP_HUGE_MASK) +#define MAP_HUGE_SHIFT SYMBOLIC(MAP_HUGE_SHIFT) +#define MAP_INHERIT SYMBOLIC(MAP_INHERIT) +#define MAP_LOCKED SYMBOLIC(MAP_LOCKED) +#define MAP_NONBLOCK SYMBOLIC(MAP_NONBLOCK) +#define MAP_NORESERVE SYMBOLIC(MAP_NORESERVE) +#define MAP_NOSYNC SYMBOLIC(MAP_NOSYNC) +#define MAP_POPULATE SYMBOLIC(MAP_POPULATE) #define MAP_ANON MAP_ANONYMOUS #define MAP_NOCORE MAP_CONCEAL diff --git a/libc/sysv/consts/ss.h b/libc/sysv/consts/ss.h index 1656da739..a2414c41a 100644 --- a/libc/sysv/consts/ss.h +++ b/libc/sysv/consts/ss.h @@ -3,13 +3,16 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ +extern const long SIGSTKSZ; +extern const long MINSIGSTKSZ; extern const long SS_DISABLE; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#define SIGSTKSZ STACKSIZE -#define SS_ONSTACK 1 -#define SS_DISABLE SS_DISABLE +#define SIGSTKSZ STACKSIZE +#define MINSIGSTKSZ 32768 +#define SS_ONSTACK 1 +#define SS_DISABLE SS_DISABLE #endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_SS_H_ */ diff --git a/test/libc/release/test.mk b/test/libc/release/test.mk index ec61a09a3..70982d4f3 100644 --- a/test/libc/release/test.mk +++ b/test/libc/release/test.mk @@ -9,7 +9,15 @@ o/$(MODE)/test/libc/release/cosmopolitan.zip: \ o/$(MODE)/ape/ape-no-modify-self.o \ o/$(MODE)/cosmopolitan.a \ o/$(MODE)/third_party/zip/zip.com - @$(COMPILE) -AZIP -T$@ o/$(MODE)/third_party/zip/zip.com -qj $@ o/cosmopolitan.h o/$(MODE)/ape/ape.lds o/$(MODE)/libc/crt/crt.o o/$(MODE)/ape/ape.o o/$(MODE)/ape/ape-no-modify-self.o o/$(MODE)/cosmopolitan.a + @$(COMPILE) -AZIP -T$@ \ + o/$(MODE)/third_party/zip/zip.com \ + -qj $@ \ + o/cosmopolitan.h \ + o/$(MODE)/ape/ape.lds \ + o/$(MODE)/libc/crt/crt.o \ + o/$(MODE)/ape/ape.o \ + o/$(MODE)/ape/ape-no-modify-self.o \ + o/$(MODE)/cosmopolitan.a o/$(MODE)/test/libc/release/smoke.com: \ o/$(MODE)/test/libc/release/smoke.com.dbg diff --git a/test/libc/runtime/ape_test.c b/test/libc/runtime/ape_test.c new file mode 100644 index 000000000..9f07cd69f --- /dev/null +++ b/test/libc/runtime/ape_test.c @@ -0,0 +1,107 @@ +/*-*- 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/calls/calls.h" +#include "libc/calls/sigbits.h" +#include "libc/calls/struct/sigaction.h" +#include "libc/errno.h" +#include "libc/mem/io.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/consts/sig.h" +#include "libc/testlib/testlib.h" + +STATIC_YOINK("zip_uri_support"); +STATIC_YOINK("apetest.com"); +STATIC_YOINK("apetest2.com"); + +char testlib_enable_tmp_setup_teardown_once; + +void Extract(const char *from, const char *to, int mode) { + ASSERT_SYS(0, 3, open(from, O_RDONLY)); + ASSERT_SYS(0, 4, creat(to, mode)); + ASSERT_NE(-1, _copyfd(3, 4, -1)); + EXPECT_SYS(0, 0, close(4)); + EXPECT_SYS(0, 0, close(3)); +} + +void SetUpOnce(void) { + ASSERT_SYS(0, 0, mkdir("bin", 0755)); + Extract("/zip/apetest.com", "bin/apetest.com", 0755); + Extract("/zip/apetest2.com", "bin/apetest2.com", 0755); + + // force the extraction of ape payload + // if system does not have binfmt_misc + ASSERT_SYS(0, 0, mkdir("tmp", 0755)); + setenv("TMPDIR", "tmp", true); +} + +void RunApeTest(const char *path) { + size_t n; + ssize_t rc, got; + char buf[512] = {0}; + sigset_t chldmask, savemask; + int i, pid, fdin, wstatus, pfds[2]; + struct sigaction ignore, saveint, savequit, savepipe; + ignore.sa_flags = 0; + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + sigaction(SIGINT, &ignore, &saveint); + sigaction(SIGQUIT, &ignore, &savequit); + sigaction(SIGPIPE, &ignore, &savepipe); + sigemptyset(&chldmask); + sigaddset(&chldmask, SIGCHLD); + sigprocmask(SIG_BLOCK, &chldmask, &savemask); + ASSERT_SYS(0, 0, pipe2(pfds, O_CLOEXEC)); + ASSERT_NE(-1, (pid = fork())); + if (!pid) { + __strace = 0; + __ftrace = 0; + close(1); + dup(pfds[1]); + sigaction(SIGINT, &saveint, 0); + sigaction(SIGQUIT, &savequit, 0); + sigaction(SIGPIPE, &savepipe, 0); + sigprocmask(SIG_SETMASK, &savemask, 0); + execv(path, (char *const[]){path, 0}); + _Exit(127); + } + close(pfds[1]); + EXPECT_SYS(0, 8, read(pfds[0], buf, sizeof(buf))); + EXPECT_STREQ("success\n", buf); + close(pfds[0]); + EXPECT_NE(-1, wait(&wstatus)); + EXPECT_TRUE(WIFEXITED(wstatus)); + EXPECT_EQ(0, WEXITSTATUS(wstatus)); + sigaction(SIGINT, &saveint, 0); + sigaction(SIGQUIT, &savequit, 0); + sigaction(SIGPIPE, &savepipe, 0); + sigprocmask(SIG_SETMASK, &savemask, 0); + EXPECT_SYS(0, 3, open(path, O_RDONLY)); + EXPECT_SYS(0, 6, read(3, buf, 6)); + EXPECT_SYS(0, 0, close(3)); + EXPECT_STREQN("MZqFpD", buf, 6); +} + +TEST(apeNoModifySelf, runsWithoutModifyingSelf) { + RunApeTest("bin/apetest.com"); +} + +TEST(apeCopySelf, runsWithoutModifyingSelf) { + RunApeTest("bin/apetest2.com"); +} diff --git a/test/libc/runtime/test.mk b/test/libc/runtime/test.mk index 2b1b75b95..c4881f68a 100644 --- a/test/libc/runtime/test.mk +++ b/test/libc/runtime/test.mk @@ -41,6 +41,8 @@ TEST_LIBC_RUNTIME_DIRECTDEPS = \ LIBC_TINYMATH \ LIBC_UNICODE \ LIBC_X \ + LIBC_ZIPOS \ + TOOL_BUILD_LIB \ THIRD_PARTY_XED TEST_LIBC_RUNTIME_DEPS := \ @@ -59,6 +61,15 @@ o/$(MODE)/test/libc/runtime/%.com.dbg: \ $(APE) @$(APELINK) +o/$(MODE)/test/libc/runtime/ape_test.com.dbg: \ + $(TEST_LIBC_RUNTIME_DEPS) \ + o/$(MODE)/test/libc/runtime/ape_test.o \ + o/$(MODE)/test/libc/runtime/runtime.pkg \ + $(LIBC_TESTMAIN) \ + $(CRT) \ + $(APE) + @$(APELINK) + $(TEST_LIBC_RUNTIME_OBJS): \ DEFAULT_CCFLAGS += \ -fno-builtin @@ -67,7 +78,6 @@ o/$(MODE)/test/libc/runtime/getenv_test.com.runs: \ o/$(MODE)/test/libc/runtime/getenv_test.com @HELLO=THERE build/runit $@ $< -o/$(MODE)/test/libc/runtime/fun_test.o \ o/$(MODE)/test/libc/runtime/itsatrap_test.o: \ OVERRIDE_CFLAGS += \ -fno-sanitize=all \ diff --git a/test/tool/plinko/plinko_test.c b/test/tool/plinko/plinko_test.c index f9f11a036..b4349fd1b 100644 --- a/test/tool/plinko/plinko_test.c +++ b/test/tool/plinko/plinko_test.c @@ -72,13 +72,13 @@ TEST(plinko, worksOrPrintsNiceError) { struct sigaction ignore, saveint, savequit, savepipe; ignore.sa_flags = 0; ignore.sa_handler = SIG_IGN; - EXPECT_EQ(0, sigemptyset(&ignore.sa_mask)); - EXPECT_EQ(0, sigaction(SIGINT, &ignore, &saveint)); - EXPECT_EQ(0, sigaction(SIGQUIT, &ignore, &savequit)); - EXPECT_EQ(0, sigaction(SIGPIPE, &ignore, &savepipe)); - EXPECT_EQ(0, sigemptyset(&chldmask)); - EXPECT_EQ(0, sigaddset(&chldmask, SIGCHLD)); - EXPECT_EQ(0, sigprocmask(SIG_BLOCK, &chldmask, &savemask)); + sigemptyset(&ignore.sa_mask); + sigaction(SIGINT, &ignore, &saveint); + sigaction(SIGQUIT, &ignore, &savequit); + sigaction(SIGPIPE, &ignore, &savepipe); + sigemptyset(&chldmask); + sigaddset(&chldmask, SIGCHLD); + sigprocmask(SIG_BLOCK, &chldmask, &savemask); ASSERT_NE(-1, pipe2(pfds[0], O_CLOEXEC)); ASSERT_NE(-1, pipe2(pfds[1], O_CLOEXEC)); ASSERT_NE(-1, (pid = fork())); @@ -90,14 +90,14 @@ TEST(plinko, worksOrPrintsNiceError) { close(2), dup(pfds[1][1]); sigaction(SIGINT, &saveint, 0); sigaction(SIGQUIT, &savequit, 0); - sigaction(SIGQUIT, &savepipe, 0); + sigaction(SIGPIPE, &savepipe, 0); sigprocmask(SIG_SETMASK, &savemask, 0); execve("bin/plinko.com", (char *const[]){"bin/plinko.com", 0}, (char *const[]){0}); _exit(127); } - EXPECT_NE(-1, close(pfds[0][0])); - EXPECT_NE(-1, close(pfds[1][1])); + close(pfds[0][0]); + close(pfds[1][1]); for (i = 0; i < ARRAYLEN(kSauces); ++i) { EXPECT_NE(-1, (fdin = open(kSauces[i], O_RDONLY))); rc = _copyfd(fdin, pfds[0][1], -1); @@ -118,10 +118,10 @@ TEST(plinko, worksOrPrintsNiceError) { } else { EXPECT_EQ(1, WEXITSTATUS(wstatus)); } - EXPECT_EQ(0, sigaction(SIGINT, &saveint, 0)); - EXPECT_EQ(0, sigaction(SIGQUIT, &savequit, 0)); - EXPECT_EQ(0, sigaction(SIGPIPE, &savepipe, 0)); - EXPECT_EQ(0, sigprocmask(SIG_SETMASK, &savemask, 0)); + sigaction(SIGINT, &saveint, 0); + sigaction(SIGQUIT, &savequit, 0); + sigaction(SIGPIPE, &savepipe, 0); + sigprocmask(SIG_SETMASK, &savemask, 0); if (g_testlib_failed) { kprintf("note: got the following in pipe: %s%n", buf); } diff --git a/tool/build/lib/apetest.c b/tool/build/lib/apetest.c new file mode 100644 index 000000000..99e91c535 --- /dev/null +++ b/tool/build/lib/apetest.c @@ -0,0 +1,23 @@ +/*-*- 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/calls/calls.h" + +int main(int argc, char *argv[]) { + write(1, "success\n", 8); +} diff --git a/tool/build/lib/buildlib.mk b/tool/build/lib/buildlib.mk index 383200cab..06b287a6d 100644 --- a/tool/build/lib/buildlib.mk +++ b/tool/build/lib/buildlib.mk @@ -9,7 +9,9 @@ TOOL_BUILD_LIB_A = o/$(MODE)/tool/build/lib/buildlib.a TOOL_BUILD_LIB_A_FILES := $(wildcard tool/build/lib/*) TOOL_BUILD_LIB_A_HDRS = $(filter %.h,$(TOOL_BUILD_LIB_A_FILES)) TOOL_BUILD_LIB_A_SRCS_S = $(filter %.S,$(TOOL_BUILD_LIB_A_FILES)) -TOOL_BUILD_LIB_A_SRCS_C = $(filter %.c,$(TOOL_BUILD_LIB_A_FILES)) + +TOOL_BUILD_LIB_A_SRCS_C = \ + $(filter-out tool/build/lib/apetest.c,$(filter %.c,$(TOOL_BUILD_LIB_A_FILES))) TOOL_BUILD_LIB_A_CHECKS = \ $(TOOL_BUILD_LIB_A_HDRS:%=o/$(MODE)/%.ok) \ @@ -19,9 +21,15 @@ TOOL_BUILD_LIB_A_SRCS = \ $(TOOL_BUILD_LIB_A_SRCS_S) \ $(TOOL_BUILD_LIB_A_SRCS_C) +TOOL_BUILD_LIB_COMS = \ + o/$(MODE)/tool/build/lib/apetest.com \ + o/$(MODE)/tool/build/lib/apetest2.com + TOOL_BUILD_LIB_A_OBJS = \ $(TOOL_BUILD_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \ - $(TOOL_BUILD_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o) + $(TOOL_BUILD_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o) \ + o/$(MODE)/tool/build/lib/apetest.com.zip.o \ + o/$(MODE)/tool/build/lib/apetest2.com.zip.o TOOL_BUILD_LIB_A_DIRECTDEPS = \ LIBC_ALG \ @@ -67,6 +75,25 @@ o/$(MODE)/tool/build/lib/ssefloat.o: \ TARGET_ARCH += \ -msse3 +o/$(MODE)/tool/build/lib/apetest.com.dbg: \ + $(TOOL_BUILD_LIB_A_DEPS) \ + o/$(MODE)/tool/build/lib/apetest.o \ + $(CRT) \ + $(APE_NO_MODIFY_SELF) + @$(APELINK) + +o/$(MODE)/tool/build/lib/apetest2.com.dbg: \ + $(TOOL_BUILD_LIB_A_DEPS) \ + o/$(MODE)/tool/build/lib/apetest.o \ + $(CRT) \ + $(APE_COPY_SELF) + @$(APELINK) + +o/$(MODE)/tool/build/lib/apetest.com.zip.o \ +o/$(MODE)/tool/build/lib/apetest2.com.zip.o: \ + ZIPOBJ_FLAGS += \ + -B + TOOL_BUILD_LIB_LIBS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x))) TOOL_BUILD_LIB_SRCS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)_SRCS)) TOOL_BUILD_LIB_HDRS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)_HDRS)) @@ -76,4 +103,6 @@ TOOL_BUILD_LIB_OBJS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)_OBJS)) TOOL_BUILD_LIB_TESTS = $(foreach x,$(TOOL_BUILD_LIB_ARTIFACTS),$($(x)_TESTS)) .PHONY: o/$(MODE)/tool/build/lib -o/$(MODE)/tool/build/lib: $(TOOL_BUILD_LIB_CHECKS) +o/$(MODE)/tool/build/lib: \ + $(TOOL_BUILD_LIB_COMS) \ + $(TOOL_BUILD_LIB_CHECKS) diff --git a/tool/net/redbean.c b/tool/net/redbean.c index ee5f1a3a0..5b60d7d1f 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -7305,7 +7305,6 @@ void RedBean(int argc, char *argv[]) { #else GetHostsTxt(); // for effect GetResolvConf(); // for effect - __print_maps(); if (daemonize || uniprocess || !linenoiseIsTerminal()) { EventLoop(HEARTBEAT); } else if (IsWindows()) {