diff --git a/Makefile b/Makefile index 5f00462dd..232062226 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,10 @@ o/$(MODE): \ o/$(MODE)/examples \ o/$(MODE)/third_party +ifneq ($(USE_SYSTEM_TOOLCHAIN),) .STRICT = 1 +endif + .PLEDGE = stdio rpath wpath cpath fattr proc .UNVEIL = \ libc/integral \ diff --git a/ape/aarch64.lds b/ape/aarch64.lds index b05c66840..d40978ea2 100644 --- a/ape/aarch64.lds +++ b/ape/aarch64.lds @@ -263,6 +263,7 @@ SECTIONS { .note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) } /DISCARD/ : { + *(__patchable_function_entries) *(.GCC.command.line) *(.note.GNU-stack) *(.gnu_debuglink) diff --git a/ape/ape.lds b/ape/ape.lds index 7e8a045d1..bf382ba45 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -498,6 +498,7 @@ SECTIONS { .GCC.command.line 0 : { *(.GCC.command.line) } /DISCARD/ : { + *(__patchable_function_entries) *(__mcount_loc) *(.discard) *(.yoink) diff --git a/ape/ape.mk b/ape/ape.mk index 4c83aa5a4..d81eb409e 100644 --- a/ape/ape.mk +++ b/ape/ape.mk @@ -191,13 +191,13 @@ o/$(MODE)/ape/ape.elf.dbg: \ o/$(MODE)/ape/loader.o \ o/$(MODE)/ape/loader-elf.o \ ape/loader.lds - @$(ELFLINK) -z max-page-size=0x10 + @$(ELFLINK) -z common-page-size=0x10 -z max-page-size=0x10 o/$(MODE)/ape/ape.macho.dbg: \ o/$(MODE)/ape/loader-xnu.o \ o/$(MODE)/ape/loader-macho.o \ ape/loader-macho.lds - @$(ELFLINK) -z max-page-size=0x10 + @$(ELFLINK) -z common-page-size=0x10 -z max-page-size=0x10 .PHONY: o/$(MODE)/ape o/$(MODE)/ape: $(APE_CHECKS) \ diff --git a/build/bootstrap/fixupobj.com b/build/bootstrap/fixupobj.com index aaafb3a72..b6c2f7fc6 100755 Binary files a/build/bootstrap/fixupobj.com and b/build/bootstrap/fixupobj.com differ diff --git a/build/bootstrap/package.com b/build/bootstrap/package.com index 7589d3e96..781d228ef 100755 Binary files a/build/bootstrap/package.com and b/build/bootstrap/package.com differ diff --git a/build/config.mk b/build/config.mk index c344533ad..427f25195 100644 --- a/build/config.mk +++ b/build/config.mk @@ -17,13 +17,31 @@ CONFIG_CCFLAGS += $(BACKTRACES) -O2 CONFIG_CPPFLAGS += -DSYSDEBUG TARGET_ARCH ?= -msse3 endif - ifeq ($(MODE), aarch64) ENABLE_FTRACE = 1 CONFIG_CCFLAGS += -O2 $(BACKTRACES) CONFIG_CPPFLAGS += -DSYSDEBUG endif +# Zero Optimization Mode +# +# - Goes 2x slower +# - Supports --strace +# - Unsupports --ftrace +# - Better GDB debugging +# +ifeq ($(MODE), zero) +OVERRIDE_CFLAGS += -O0 +OVERRIDE_CXXFLAGS += -O0 +OVERRIDE_CCFLAGS = -fno-omit-frame-pointer +CONFIG_CPPFLAGS += -DSYSDEBUG +endif +ifeq ($(MODE), aarch64-zero) +OVERRIDE_CFLAGS += -O0 +OVERRIDE_CXXFLAGS += -O0 +CONFIG_CPPFLAGS += -DSYSDEBUG +endif + # Fast Build Mode # # - `make MODE=fastbuild` @@ -74,7 +92,7 @@ endif ifeq ($(MODE), optlinux) CONFIG_CPPFLAGS += -DNDEBUG -msse2avx -Wa,-msse2avx -DSUPPORT_VECTOR=1 CONFIG_CCFLAGS += -O3 -fmerge-all-constants -DEFAULT_COPTS += -mred-zone +CONFIG_COPTS += -mred-zone TARGET_ARCH ?= -march=native endif @@ -121,24 +139,23 @@ endif # - `make MODE=dbg` # - Backtraces # - Enables asan -# - Enables ubsan (TODO) +# - Enables ubsan # - Stack canaries -# - No optimization (TODO) +# - No optimization # - Enormous binaries # ifeq ($(MODE), dbg) ENABLE_FTRACE = 1 CONFIG_CPPFLAGS += -DMODE_DBG -CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O -fno-inline +CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline CONFIG_COPTS += -fsanitize=address -fsanitize=undefined TARGET_ARCH ?= -msse3 OVERRIDE_CCFLAGS += -fno-pie endif - ifeq ($(MODE), aarch64-dbg) ENABLE_FTRACE = 1 CONFIG_CPPFLAGS += -DMODE_DBG -CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O -fno-inline +CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline CONFIG_COPTS += -fsanitize=undefined endif @@ -197,7 +214,6 @@ PYFLAGS += \ -O2 \ -B endif - ifeq ($(MODE), aarch64-tiny) # TODO(jart): -mcmodel=tiny CONFIG_CPPFLAGS += \ @@ -244,8 +260,6 @@ CONFIG_CPPFLAGS += \ -DTRUSTWORTHY \ -DSUPPORT_VECTOR=1 \ -DDWARFLESS -DEFAULT_COPTS += \ - -mred-zone CONFIG_OFLAGS += \ -g0 CONFIG_LDFLAGS += \ @@ -281,8 +295,6 @@ CONFIG_CPPFLAGS += \ -DTRUSTWORTHY \ -DSUPPORT_VECTOR=113 \ -DDWARFLESS -DEFAULT_COPTS += \ - -mred-zone CONFIG_OFLAGS += \ -g0 CONFIG_LDFLAGS += \ @@ -317,8 +329,6 @@ CONFIG_CPPFLAGS += \ -DTRUSTWORTHY \ -DSUPPORT_VECTOR=121 \ -DDWARFLESS -DEFAULT_COPTS += \ - -mred-zone CONFIG_CCFLAGS += \ -Os \ -fno-align-functions \ diff --git a/build/definitions.mk b/build/definitions.mk index d0fa2c3eb..8993b014d 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -33,14 +33,25 @@ # # VARIABLES # -# CCFLAGS gcc frontend flags (.i, .c, .cc, .f, .S, .lds, etc.) +# Our configuration variables, ordered by increasing preference: +# +# CCFLAGS frontend flags (.i, .c, .cc, .f, .S, .lds, etc.) +# OFLAGS objectify flags (precludes -S and -E) # CPPFLAGS preprocessor flags (.h, .c, .cc, .S, .inc, .lds, etc.) +# TARGET_ARCH microarchitecture flags (e.g. -march=native) +# COPTS c/c++ flags (.c, .cc) # CFLAGS c flags (.c only) # CXXFLAGS c++ flags (.cc only) -# COPTS c/c++ flags (.c, .cc) # LDFLAGS linker flags (don't use -Wl, frontend prefix) # ASFLAGS assembler flags (don't use -Wa, frontend prefix) -# TARGET_ARCH microarchitecture flags (e.g. -march=native) +# +# For each FOO above, there exists (by increasing preference) +# +# DEFAULT_FOO see build/definitions.mk +# CONFIG_FOO see build/config.mk +# FOO set ~/.cosmo.mk and target-specific +# OVERRIDE_FOO set ~/.cosmo.mk and target-specific (use rarely) +# LC_ALL = C SOURCE_DATE_EPOCH = 0 @@ -88,19 +99,19 @@ ARCH = x86_64 HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win10 endif -PORTCOSMO_CCFLAGS = -fportcosmo -include build/portcosmo.h - +ifeq ($(PREFIX),) +ifeq ($(USE_SYSTEM_TOOLCHAIN),) ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-*)","") PREFIX = o/third_party/gcc/bin/x86_64-pc-linux-gnu- -DEFAULT_CPPFLAGS += $(PORTCOSMO_CCFLAGS) else IGNORE := $(shell build/bootstrap/unbundle.com) PREFIX = o/third_party/gcc/bin/x86_64-linux-musl- -DEFAULT_CPPFLAGS += $(PORTCOSMO_CCFLAGS) endif ifeq ($(ARCH), aarch64) PREFIX = o/third_party/gcc/bin/aarch64-linux-musl- endif +endif +endif AS = $(PREFIX)as CC = $(PREFIX)gcc @@ -112,7 +123,7 @@ GCC = $(PREFIX)gcc STRIP = $(PREFIX)strip OBJCOPY = $(PREFIX)objcopy OBJDUMP = $(PREFIX)objdump -ADDR2LINE = $(PWD)/$(PREFIX)addr2line +ADDR2LINE = $(join $(PWD),$(PREFIX))addr2line export ADDR2LINE export LC_ALL @@ -122,15 +133,11 @@ export SOURCE_DATE_EPOCH export TMPDIR ifeq ($(LANDLOCKMAKE_VERSION),) -TMPSAFE = $(TMPDIR)/$(subst /,_,$@).tmp +TMPSAFE = $(join $(TMPDIR),$(subst /,_,$@)).tmp else TMPSAFE = $(TMPDIR)/ endif -ifneq ($(ARCH), aarch64) -MNO_FENTRY = -mno-fentry -endif - ifeq ($(ARCH), aarch64) IMAGE_BASE_VIRTUAL ?= 0x010000000000 else @@ -150,7 +157,6 @@ SANITIZER = \ -fsanitize=address NO_MAGIC = \ - $(MNO_FENTRY) \ -fno-stack-protector \ -fwrapv \ -fno-sanitize=all @@ -170,19 +176,22 @@ DEFAULT_CCFLAGS += \ -fdebug-prefix-map='$(PWD)'= \ -frecord-gcc-switches -DEFAULT_OFLAGS = \ +DEFAULT_OFLAGS ?= \ -g \ -gdwarf-4 \ -gdescribe-dies -DEFAULT_COPTS = \ +DEFAULT_COPTS ?= \ -fno-math-errno \ -fno-ident \ -fno-common \ -fno-gnu-unique \ -fstrict-aliasing \ -fstrict-overflow \ - -fno-semantic-interposition + -fno-semantic-interposition \ + -fno-dwarf2-cfi-asm \ + -fno-unwind-tables \ + -fno-asynchronous-unwind-tables ifeq ($(ARCH), x86_64) DEFAULT_COPTS += \ @@ -334,19 +343,19 @@ LD.libs = \ $(CONFIG_LIBS) \ $(LIBS) -COMPILE.c.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(c.flags) -COMPILE.cxx.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(cxx.flags) +COMPILE.c.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(c.flags) +COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(cxx.flags) COMPILE.f.flags = $(cc.flags) $(copt.flags) $(f.flags) -COMPILE.F.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(f.flags) +COMPILE.F.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(f.flags) COMPILE.i.flags = $(cc.flags) $(copt.flags) $(c.flags) COMPILE.ii.flags = $(cc.flags) $(copt.flags) $(cxx.flags) LINK.flags = $(DEFAULT_LDFLAGS) $(CONFIG_LDFLAGS) $(LDFLAGS) -OBJECTIFY.c.flags = $(OBJECTIFY.S.flags) $(copt.flags) $(c.flags) -OBJECTIFY.cxx.flags = $(OBJECTIFY.S.flags) $(copt.flags) $(cxx.flags) +OBJECTIFY.c.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(c.flags) +OBJECTIFY.cxx.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(cxx.flags) OBJECTIFY.s.flags = $(ASONLYFLAGS) $(s.flags) -OBJECTIFY.S.flags = $(copt.flags) $(cc.flags) $(o.flags) $(cpp.flags) $(S.flags) -OBJECTIFY.f.flags = $(copt.flags) $(cc.flags) $(o.flags) $(copt.flags) $(S.flags) $(f.flags) -OBJECTIFY.F.flags = $(OBJECTIFY.f.flags) $(cpp.flags) +OBJECTIFY.S.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) +OBJECTIFY.f.flags = $(cc.flags) $(o.flags) $(S.flags) $(f.flags) +OBJECTIFY.F.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(f.flags) PREPROCESS.flags = -E $(copt.flags) $(cc.flags) $(cpp.flags) PREPROCESS.lds.flags = -D__LINKER__ $(filter-out -g%,$(PREPROCESS.flags)) -P -xc @@ -382,7 +391,6 @@ OBJECTIFY.greg.c = \ -fno-optimize-sibling-calls \ -fno-sanitize=all \ -ffreestanding \ - $(MNO_FENTRY) \ -fwrapv \ -c @@ -422,7 +430,6 @@ OBJECTIFY.ncabi.c = \ $(OBJECTIFY.c.flags) \ -mno-sse \ -mfpmath=387 \ - $(MNO_FENTRY) \ -fno-stack-protector \ -fno-instrument-functions \ -fno-optimize-sibling-calls \ @@ -441,7 +448,6 @@ OBJECTIFY.ncabi.c = \ OBJECTIFY.initabi.c = \ $(GCC) \ $(OBJECTIFY.c.flags) \ - $(MNO_FENTRY) \ -fno-stack-protector \ -fno-instrument-functions \ -fno-optimize-sibling-calls \ diff --git a/dsp/tty/config.c b/dsp/tty/config.c index 48a52cc0b..4e10bf9df 100644 --- a/dsp/tty/config.c +++ b/dsp/tty/config.c @@ -31,7 +31,7 @@ */ int ttyconfig(int ttyfd, ttyconf_f fn, int64_t arg, struct termios *opt_out_oldconf) { - struct termios conf[2]; + struct termios conf[2] = {0}; if (tcgetattr(ttyfd, &conf[0]) != -1 && fn(memcpy(&conf[1], &conf[0], sizeof(conf[0])), arg) != -1 && tcsetattr(ttyfd, TCSAFLUSH, &conf[1]) != -1) { diff --git a/examples/script.c b/examples/script.c index e81138030..bf280ff0c 100644 --- a/examples/script.c +++ b/examples/script.c @@ -30,6 +30,7 @@ │ SUCH DAMAGE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/calls/ioctl.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/stat.h" #include "libc/calls/struct/termios.h" diff --git a/libc/calls/calls.mk b/libc/calls/calls.mk index 44fa2b908..5d1f08c8f 100644 --- a/libc/calls/calls.mk +++ b/libc/calls/calls.mk @@ -183,6 +183,18 @@ o/$(MODE)/libc/calls/timeval_frommicros.o: private \ CFLAGS += \ -O2 +# privileged functions +o/$(MODE)/libc/calls/sigenter-freebsd.o \ +o/$(MODE)/libc/calls/sigenter-netbsd.o \ +o/$(MODE)/libc/calls/sigenter-openbsd.o \ +o/$(MODE)/libc/calls/sigenter-linux.o \ +o/$(MODE)/libc/calls/sigenter-xnu.o \ +o/$(MODE)/libc/calls/pledge-linux.o \ +o/$(MODE)/libc/calls/siginfo2cosmo.o: private \ + CFLAGS += \ + -ffreestanding \ + -fno-sanitize=all + o/$(MODE)/libc/calls/pledge-linux.o \ o/$(MODE)/libc/calls/unveil.o: private \ CFLAGS += \ diff --git a/libc/calls/getpriority.c b/libc/calls/getpriority.c index 913bb61cb..2bd037e8f 100644 --- a/libc/calls/getpriority.c +++ b/libc/calls/getpriority.c @@ -48,7 +48,7 @@ * @raise ESRCH if no such process existed * @see setpriority() */ -privileged int getpriority(int which, unsigned who) { +int getpriority(int which, unsigned who) { int rc; #ifdef __x86_64__ char cf; diff --git a/libc/calls/islinux.c b/libc/calls/islinux.c index c715942e7..99e2c51c8 100644 --- a/libc/calls/islinux.c +++ b/libc/calls/islinux.c @@ -21,7 +21,7 @@ #include "libc/runtime/runtime.h" #include "libc/sysv/consts/pr.h" -privileged bool __is_linux_2_6_23(void) { +bool __is_linux_2_6_23(void) { #ifdef __x86_64__ int rc; if (!IsLinux()) return false; diff --git a/libc/calls/mremap-sysv.greg.c b/libc/calls/mremap-sysv.greg.c index dad5eed3d..3a5ad39f3 100644 --- a/libc/calls/mremap-sysv.greg.c +++ b/libc/calls/mremap-sysv.greg.c @@ -34,7 +34,7 @@ * C library runtime won't have any awareness of this memory, so certain * features like ASAN memory safety and kprintf() won't work as well. */ -privileged void *sys_mremap(void *p, size_t n, size_t m, int f, void *q) { +void *sys_mremap(void *p, size_t n, size_t m, int f, void *q) { #ifdef __x86_64__ bool cf; uintptr_t res, rdi, rsi, rdx; diff --git a/libc/calls/prctl.c b/libc/calls/prctl.c index d59b0fa43..80881e247 100644 --- a/libc/calls/prctl.c +++ b/libc/calls/prctl.c @@ -31,7 +31,7 @@ * * @raise ENOSYS on non-Linux */ -privileged int prctl(int operation, ...) { +int prctl(int operation, ...) { int rc; va_list va; intptr_t a, b, c, d; diff --git a/libc/calls/seccomp.c b/libc/calls/seccomp.c index 65ce5ad8f..904c4cec8 100644 --- a/libc/calls/seccomp.c +++ b/libc/calls/seccomp.c @@ -35,7 +35,7 @@ * * @raise ENOSYS on non-Linux. */ -privileged int seccomp(unsigned operation, unsigned flags, void *args) { +int seccomp(unsigned operation, unsigned flags, void *args) { int rc; if (IsLinux()) { #ifdef __x86_64__ diff --git a/libc/calls/sigenter-linux.c b/libc/calls/sigenter-linux.c index ceb7c8b59..4fd3655c6 100644 --- a/libc/calls/sigenter-linux.c +++ b/libc/calls/sigenter-linux.c @@ -41,7 +41,7 @@ privileged void __sigenter_wsl(int sig, struct siginfo *info, ucontext_t *ctx) { ctx->uc_mcontext.fpregs = &ctx->__fpustate; for (i = 0; i < 8; ++i) { long double nan = NAN; - memcpy(ctx->__fpustate.st + i, &nan, 16); + __builtin_memcpy(ctx->__fpustate.st + i, &nan, 16); } } ((sigaction_f)(__executable_start + rva))(sig, info, ctx); diff --git a/libc/calls/struct/fd.internal.h b/libc/calls/struct/fd.internal.h index a607d7402..cc3e79a00 100644 --- a/libc/calls/struct/fd.internal.h +++ b/libc/calls/struct/fd.internal.h @@ -3,20 +3,18 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -enum FdKind { - kFdEmpty, - kFdFile, - kFdSocket, - kFdProcess, - kFdConsole, - kFdSerial, - kFdZip, - kFdEpoll, - kFdReserved -}; +#define kFdEmpty 0 +#define kFdFile 1 +#define kFdSocket 2 +#define kFdProcess 3 +#define kFdConsole 4 +#define kFdSerial 5 +#define kFdZip 6 +#define kFdEpoll 7 +#define kFdReserved 8 struct Fd { - enum FdKind kind; + int kind; unsigned flags; unsigned mode; int64_t handle; diff --git a/libc/calls/tcdrain.c b/libc/calls/tcdrain.c index b673ae904..f368b2c26 100644 --- a/libc/calls/tcdrain.c +++ b/libc/calls/tcdrain.c @@ -24,6 +24,7 @@ #include "libc/dce.h" #include "libc/intrin/strace.internal.h" #include "libc/nt/files.h" +#include "libc/sysv/consts/termios.h" #include "libc/sysv/errfuns.h" static textwindows int sys_tcdrain_nt(int fd) { diff --git a/libc/calls/termios.h b/libc/calls/termios.h index 80453b5dc..0f5df5420 100644 --- a/libc/calls/termios.h +++ b/libc/calls/termios.h @@ -1,9 +1,7 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_TERMIOS_H_ #define COSMOPOLITAN_LIBC_CALLS_TERMIOS_H_ -#include "libc/calls/ioctl.h" #include "libc/calls/struct/termios.h" #include "libc/calls/struct/winsize.h" -#include "libc/sysv/consts/termios.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -38,25 +36,6 @@ uint32_t cfgetispeed(const struct termios *); int tcsetwinsize(int, const struct winsize *); int tcgetwinsize(int, struct winsize *); -/*───────────────────────────────────────────────────────────────────────────│─╗ -│ cosmopolitan § teletypewriter » undiamonding ─╬─│┼ -╚────────────────────────────────────────────────────────────────────────────│*/ -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) - -#define tcsetattr(FD, OPT, TIO) tcsetattr_dispatch(FD, OPT, TIO) -forceinline int tcsetattr_dispatch(int fd, int opt, const struct termios *tio) { - if (__EQUIVALENT(opt, TCSANOW)) return ioctl(fd, TCSETS, (void *)tio); - if (__EQUIVALENT(opt, TCSADRAIN)) return ioctl(fd, TCSETSW, (void *)tio); - if (__EQUIVALENT(opt, TCSAFLUSH)) return ioctl(fd, TCSETSF, (void *)tio); - return (tcsetattr)(fd, opt, tio); -} - -#define tcgetattr(FD, TIO) tcgetattr_dispatch(FD, TIO) -forceinline int tcgetattr_dispatch(int fd, const struct termios *tio) { - return ioctl(fd, TCGETS, (void *)tio); -} - -#endif /* GNUC && !ANSI */ COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_CALLS_TERMIOS_H_ */ diff --git a/libc/calls/wincrash.c b/libc/calls/wincrash.c index 33247766c..f4b2963f9 100644 --- a/libc/calls/wincrash.c +++ b/libc/calls/wincrash.c @@ -36,7 +36,7 @@ #ifdef __x86_64__ -privileged unsigned __wincrash(struct NtExceptionPointers *ep) { +unsigned __wincrash(struct NtExceptionPointers *ep) { int64_t rip; int sig, code; ucontext_t ctx; diff --git a/libc/dce.h b/libc/dce.h index ef6ccd166..0f946bf1d 100644 --- a/libc/dce.h +++ b/libc/dce.h @@ -36,12 +36,6 @@ #define IsModeDbg() 0 #endif -#ifdef __MFENTRY__ -#define HaveFentry() 1 -#else -#define HaveFentry() 0 -#endif - #ifdef TRUSTWORTHY #define IsTrustworthy() 1 #else @@ -72,12 +66,6 @@ #define IsXnuSilicon() 0 #endif -#if defined(__PIE__) || defined(__PIC__) -#define IsPositionIndependent() 1 -#else -#define IsPositionIndependent() 0 -#endif - #define SupportsLinux() ((SUPPORT_VECTOR & _HOSTLINUX) == _HOSTLINUX) #define SupportsMetal() ((SUPPORT_VECTOR & _HOSTMETAL) == _HOSTMETAL) #define SupportsWindows() ((SUPPORT_VECTOR & _HOSTWINDOWS) == _HOSTWINDOWS) diff --git a/libc/elf/checkelfaddress.c b/libc/elf/checkelfaddress.c index e336c8b33..d9207ec71 100644 --- a/libc/elf/checkelfaddress.c +++ b/libc/elf/checkelfaddress.c @@ -17,15 +17,16 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/elf/elf.h" +#include "libc/intrin/kprintf.h" #include "libc/runtime/runtime.h" void CheckElfAddress(const Elf64_Ehdr *elf, size_t mapsize, intptr_t addr, size_t addrsize) { #if !(TRUSTWORTHY + ELF_TRUSTWORTHY + 0) || ELF_UNTRUSTWORTHY + 0 if (addr < (intptr_t)elf || addr + addrsize > (intptr_t)elf + mapsize) { - /* kprintf("%p-%p falls outside interval %p-%p", // */ - /* addr, addr + addrsize, // */ - /* elf, (char *)elf + mapsize); // */ + kprintf("%p-%p falls outside interval %p-%p", // + addr, addr + addrsize, // + elf, (char *)elf + mapsize); // abort(); } #endif diff --git a/libc/fmt/fmt.h b/libc/fmt/fmt.h index 914bc01e8..ba620bf56 100644 --- a/libc/fmt/fmt.h +++ b/libc/fmt/fmt.h @@ -14,14 +14,13 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -int snprintf(char *, size_t, const char *, ...) printfesque(3) - paramsnonnull((3)) dontthrow nocallback; +int snprintf(char *, size_t, const char *, ...) + printfesque(3) dontthrow nocallback; int vsnprintf(char *, size_t, const char *, va_list) - paramsnonnull((3)) dontthrow nocallback; -int sprintf(char *, const char *, ...) printfesque(2) - paramsnonnull((2)) dontthrow nocallback frownedupon(snprintf); +dontthrow nocallback; +int sprintf(char *, const char *, ...) printfesque(2) dontthrow nocallback; int vsprintf(char *, const char *, va_list) - paramsnonnull((2)) dontthrow nocallback frownedupon(vsnprintf); +dontthrow nocallback; int sscanf(const char *, const char *, ...) scanfesque(2); int vsscanf(const char *, const char *, va_list); int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *, diff --git a/libc/integral/c.inc b/libc/integral/c.inc index aab320791..621dbef06 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -729,6 +729,7 @@ void abort(void) wontreturn; #if __GNUC__ >= 11 #pragma GCC diagnostic ignored /* annoying */ "-Wattributes" #pragma GCC diagnostic ignored /* orwellian */ "-Wold-style-definition" +#pragma GCC diagnostic ignored /* what? */ "-Wformat-overflow" #endif /* GCC11+ */ #endif /* GCC9+ */ #endif /* !C++ */ @@ -834,10 +835,10 @@ void abort(void) wontreturn; #if !defined(__STRICT_ANSI__) && !defined(__APPLE__) && defined(__x86_64__) #define YOINK(SYMBOL) \ - asm(".section .yoink\n\tnopl\t%a0\n\t.previous" : : "X"(SYMBOL)) + asm(".section .yoink\n\tnopl\t%0\n\t.previous" : : "m"(SYMBOL)) #elif defined(__aarch64__) #define YOINK(SYMBOL) \ - asm(".section .yoink\n\tb\t%a0\n\t.previous" : : "X"(SYMBOL)) + asm(".section .yoink\n\tb\t%0\n\t.previous" : : "m"(SYMBOL)) #else #define YOINK(SYMBOL) (void)0 #endif diff --git a/libc/intrin/formatint32.c b/libc/intrin/formatint32.c index 9afc72f50..0e13f13e1 100644 --- a/libc/intrin/formatint32.c +++ b/libc/intrin/formatint32.c @@ -24,7 +24,7 @@ * @param p needs at least 12 bytes * @return pointer to nul byte */ -dontinline char *FormatUint32(char p[hasatleast 12], uint32_t x) { +privileged dontinline char *FormatUint32(char p[hasatleast 12], uint32_t x) { char t; size_t i, a, b; i = 0; @@ -49,7 +49,7 @@ dontinline char *FormatUint32(char p[hasatleast 12], uint32_t x) { * @param p needs at least 12 bytes * @return pointer to nul byte */ -char *FormatInt32(char p[hasatleast 12], int32_t x) { +privileged char *FormatInt32(char p[hasatleast 12], int32_t x) { if (x < 0) *p++ = '-', x = -(uint32_t)x; return FormatUint32(p, x); } diff --git a/libc/intrin/getmagnumstr.c b/libc/intrin/getmagnumstr.c index 20834e936..7bcbbc542 100644 --- a/libc/intrin/getmagnumstr.c +++ b/libc/intrin/getmagnumstr.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/magnumstrs.internal.h" -char *GetMagnumStr(const struct MagnumStr *ms, int x) { +privileged char *GetMagnumStr(const struct MagnumStr *ms, int x) { int i; for (i = 0; ms[i].x != MAGNUM_TERMINATOR; ++i) { if (x == MAGNUM_NUMBER(ms, i)) { diff --git a/libc/intrin/intrin.mk b/libc/intrin/intrin.mk index 0adf6ad25..207121538 100644 --- a/libc/intrin/intrin.mk +++ b/libc/intrin/intrin.mk @@ -72,6 +72,7 @@ o/$(MODE)/libc/intrin/mman.greg.o: private \ o/$(MODE)/libc/intrin/asan.o \ o/$(MODE)/libc/intrin/ubsan.o: private \ CFLAGS += \ + -ffreestanding \ -fno-sanitize=all \ -fno-stack-protector @@ -84,7 +85,6 @@ o/$(MODE)/libc/intrin/asan.o: private \ o/$(MODE)/libc/intrin/asanthunk.o: private \ CFLAGS += \ -x-no-pg \ - $(MNO_FENTRY) \ -ffreestanding \ -fno-sanitize=all \ -fno-stack-protector @@ -100,7 +100,6 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: private \ -fpie \ -fwrapv \ -x-no-pg \ - $(MNO_FENTRY) \ -ffreestanding \ -fno-sanitize=all \ -fno-stack-protector @@ -115,7 +114,6 @@ o/$(MODE)/libc/intrin/_spinlock_debug_4.o: private \ CFLAGS += \ -fwrapv \ -x-no-pg \ - $(MNO_FENTRY) \ -ffreestanding \ -fno-sanitize=all \ -mgeneral-regs-only \ @@ -187,6 +185,17 @@ o/$(MODE)/libc/intrin/wsawaitformultipleevents.o: private\ -fno-stack-protector \ -fno-sanitize=all +# privileged functions +o/$(MODE)/libc/intrin/dos2errno.o \ +o/$(MODE)/libc/intrin/have_fsgsbase.o \ +o/$(MODE)/libc/intrin/getmagnumstr.o \ +o/$(MODE)/libc/intrin/formatint32.o \ +o/$(MODE)/libc/intrin/strsignal_r.o \ +o/$(MODE)/libc/intrin/strerror_wr.o: private \ + CFLAGS += \ + -ffreestanding \ + -fno-sanitize=all + o//libc/intrin/memmove.o: private \ CFLAGS += \ -fno-toplevel-reorder diff --git a/libc/intrin/isatleastwindows10.greg.c b/libc/intrin/isatleastwindows10.greg.c index 8829d14b1..b8e4c33ed 100644 --- a/libc/intrin/isatleastwindows10.greg.c +++ b/libc/intrin/isatleastwindows10.greg.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/assert.h" #include "libc/dce.h" #include "libc/nt/version.h" @@ -26,6 +25,5 @@ * This function may only be called if IsWindows() is true. */ privileged bool(IsAtLeastWindows10)(void) { - _unassert(IsWindows()); return IsAtLeastWindows10(); } diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c index a2b389a27..bdbd70086 100644 --- a/libc/intrin/kprintf.greg.c +++ b/libc/intrin/kprintf.greg.c @@ -287,6 +287,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, cols = 0; zero = 0; uppr = 0; + ansi = 0; abet = "0123456789abcdef"; for (;;) { switch ((c = *f++)) { @@ -392,7 +393,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, *p++ = '3'; *p++ = '0' + x % 8; *p++ = 'm'; - ansi = true; + ansi = 1; } } else { x = 666; @@ -527,10 +528,10 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, unixerr = errno; winerr = 0; if (IsWindows()) { - if (type == 1 && _weaken(WSAGetLastError)) { - winerr = _weaken(WSAGetLastError)(); - } else if (_weaken(GetLastError)) { - winerr = _weaken(GetLastError)(); + if (type == 1 && _weaken(__imp_WSAGetLastError)) { + winerr = (*_weaken(__imp_WSAGetLastError))(); + } else if (_weaken(__imp_GetLastError)) { + winerr = (*_weaken(__imp_GetLastError))(); } } if (!unixerr && sign == ' ') { @@ -777,7 +778,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, *p++ = '0'; *p++ = 'm'; } - ansi = false; + ansi = 0; } break; } diff --git a/libc/intrin/nopl.internal.h b/libc/intrin/nopl.internal.h index c8385f21f..dae76ebaf 100644 --- a/libc/intrin/nopl.internal.h +++ b/libc/intrin/nopl.internal.h @@ -2,7 +2,7 @@ #define COSMOPOLITAN_LIBC_INTRIN_NOPL_H_ #if !(__ASSEMBLER__ + __LINKER__ + 0) && defined(__x86_64__) && \ defined(__GNUC__) && !defined(__llvm__) && !defined(__chibicc__) && \ - !defined(__STRICT_ANSI__) + defined(__MNO_RED_ZONE__) && !defined(__STRICT_ANSI__) /** * @fileoverview Turns CALLs into NOPs that are fixupable at runtime. @@ -35,34 +35,39 @@ ".equ\t\"" SECTION "_end\",.\n\t" \ ".previous\n\t" -#define _NOPL0(SECTION, FUNC) \ +#define _NOPL0(SECTION, FUNC) __NOPL0(SECTION, FUNC, IMAGE_BASE_VIRTUAL) +#define __NOPL0(SECTION, FUNC, GARDEN) ___NOPL0(SECTION, FUNC, GARDEN) +#define ___NOPL0(SECTION, FUNC, GARDEN) \ ({ \ asm volatile(_NOPL_PROLOGUE(SECTION) /* */ \ _NOPL_EPILOGUE(SECTION) /* */ \ ".section \".sort.rodata." SECTION ".2\",\"a\",@progbits\n\t" \ ".balign\t4\n\t" \ - ".long\t353f-%a1\n\t" \ + ".long\t353f-" #GARDEN "\n\t" \ ".previous\n353:\t" \ - "nopl\t%a0" \ + "nopl\t" #FUNC "(%%rip)" \ : /* no inputs */ \ - : "X"(FUNC), "X"(IMAGE_BASE_VIRTUAL) \ + : /* no outputs */ \ : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", \ "r11", "memory", "cc"); \ (void)0; \ }) -#define _NOPL1(SECTION, FUNC, ARG) \ +#define _NOPL1(SECTION, FUNC, ARG) \ + __NOPL1(SECTION, FUNC, ARG, IMAGE_BASE_VIRTUAL) +#define __NOPL1(SECTION, FUNC, ARG, GARDEN) ___NOPL1(SECTION, FUNC, ARG, GARDEN) +#define ___NOPL1(SECTION, FUNC, ARG, GARDEN) \ ({ \ register autotype(ARG) __arg asm("rdi") = ARG; \ asm volatile(_NOPL_PROLOGUE(SECTION) /* */ \ _NOPL_EPILOGUE(SECTION) /* */ \ ".section \".sort.rodata." SECTION ".2\",\"a\",@progbits\n\t" \ ".balign\t4\n\t" \ - ".long\t353f-%a2\n\t" \ + ".long\t353f-" #GARDEN "\n\t" \ ".previous\n353:\t" \ - "nopl\t%a1" \ + "nopl\t" #FUNC "(%%rip)" \ : "+D"(__arg) \ - : "X"(FUNC), "X"(IMAGE_BASE_VIRTUAL) \ + : /* no inputs */ \ : "rax", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11", \ "memory", "cc"); \ (void)0; \ diff --git a/libc/intrin/printsystemmappings.greg.c b/libc/intrin/printsystemmappings.greg.c index 6104c71da..a969ee71e 100644 --- a/libc/intrin/printsystemmappings.greg.c +++ b/libc/intrin/printsystemmappings.greg.c @@ -22,7 +22,7 @@ #include "libc/sysv/consts/at.h" #include "libc/sysv/consts/o.h" -privileged void PrintSystemMappings(int outfd) { +void PrintSystemMappings(int outfd) { int infd; ssize_t rc; char buf[64]; diff --git a/libc/intrin/restorewintty.c b/libc/intrin/restorewintty.c index b95c9de80..de37f8510 100644 --- a/libc/intrin/restorewintty.c +++ b/libc/intrin/restorewintty.c @@ -35,7 +35,7 @@ const unsigned char kConsoleHandles[3] = { }; // Puts cmd.exe gui back the way it was. -noinstrument void _restorewintty(void) { +privileged noinstrument void _restorewintty(void) { if (!IsWindows()) return; if (__imp_GetCurrentProcessId() != __pid_exec) return; for (int i = 0; i < 3; ++i) { diff --git a/libc/intrin/strerror_wr.greg.c b/libc/intrin/strerror_wr.greg.c index d6a2444f4..9c1b0fbb0 100644 --- a/libc/intrin/strerror_wr.greg.c +++ b/libc/intrin/strerror_wr.greg.c @@ -16,10 +16,10 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#define ShouldUseMsabiAttribute() 1 #include "libc/dce.h" #include "libc/fmt/fmt.h" #include "libc/intrin/kprintf.h" -#include "libc/intrin/safemacros.internal.h" #include "libc/macros.internal.h" #include "libc/nt/enum/formatmessageflags.h" #include "libc/nt/enum/lang.h" @@ -39,8 +39,14 @@ privileged int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) { char16_t winmsg[256]; const char *sym, *msg; wanting = false; - sym = firstnonnull(_strerrno(err), (wanting = true, "EUNKNOWN")); - msg = firstnonnull(_strerdoc(err), (wanting = true, "No error information")); + if (!(sym = _strerrno(err))) { + sym = "EUNKNOWN"; + wanting = true; + } + if (!(msg = _strerdoc(err))) { + msg = "No error information"; + wanting = true; + } if (IsTiny()) { if (!sym) sym = "EUNKNOWN"; for (; (c = *sym++); --size) @@ -49,7 +55,7 @@ privileged int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) { } else if (!IsWindows() || ((err == winerr || !winerr) && !wanting)) { ksnprintf(buf, size, "%s/%d/%s", sym, err, msg); } else { - if ((n = FormatMessage( + if ((n = __imp_FormatMessageW( kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, 0, winerr, MAKELANGID(kNtLangNeutral, kNtSublangDefault), winmsg, ARRAYLEN(winmsg), 0))) { diff --git a/libc/intrin/strsignal_r.c b/libc/intrin/strsignal_r.c index b030f9b80..bcea1a96d 100644 --- a/libc/intrin/strsignal_r.c +++ b/libc/intrin/strsignal_r.c @@ -36,7 +36,7 @@ * @asyncsignalsafe * @threadsafe */ -char *strsignal_r(int sig, char buf[hasatleast 15]) { +privileged char *strsignal_r(int sig, char buf[hasatleast 15]) { int i; char *p; const char *s; diff --git a/libc/intrin/winerr.greg.c b/libc/intrin/winerr.greg.c index bf32daa35..f79ea332a 100644 --- a/libc/intrin/winerr.greg.c +++ b/libc/intrin/winerr.greg.c @@ -35,7 +35,6 @@ privileged int64_t __winerr(void) { errno_t e; if (IsWindows()) { e = __dos2errno(__imp_GetLastError()); - _npassert(e > 0); } else { e = ENOSYS; } diff --git a/libc/log/gdbexec.c b/libc/log/gdbexec.c index f46a928af..c0f2673db 100644 --- a/libc/log/gdbexec.c +++ b/libc/log/gdbexec.c @@ -28,7 +28,7 @@ /** * Attaches GDB temporarily, to do something like print a variable. */ -privileged int(gdbexec)(const char *cmd) { +relegated int(gdbexec)(const char *cmd) { struct StackFrame *bp; int pid, ttyin, ttyout; intptr_t continuetoaddr; diff --git a/libc/log/log_exit.c b/libc/log/log_exit.c index dc4b761f9..d3871f654 100644 --- a/libc/log/log_exit.c +++ b/libc/log/log_exit.c @@ -19,6 +19,6 @@ #include "libc/log/log.h" #include "libc/runtime/runtime.h" -privileged wontreturn void _log_exit(int exitcode) { +wontreturn void _log_exit(int exitcode) { _Exitr(exitcode); } diff --git a/libc/nexgen32e/fentry.S b/libc/nexgen32e/fentry.S deleted file mode 100644 index 33f833e39..000000000 --- a/libc/nexgen32e/fentry.S +++ /dev/null @@ -1,30 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.internal.h" -.real -.code16 # ∩ .code32 ∩ .code64 - -// Function entry hook stub. -// -// @note cc -pg -mfentry adds this to the start of every function -// @see libc/log/shadowargs.ncabi.c -// @mode long,legacy,real -__fentry__: - ret - .endfn __fentry__,weak diff --git a/libc/nexgen32e/lolendian.S b/libc/nexgen32e/lolendian.S deleted file mode 100644 index c15e47fc2..000000000 --- a/libc/nexgen32e/lolendian.S +++ /dev/null @@ -1,77 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.internal.h" - -// @fileoverview Byte-order conversion functions. -// -// Endianness is deceptively complicated to the uninitiated. Many -// helpers have been written by our top minds to address perceived -// difficulties. These ones got through standardization processes. -// To protect their legacy, all 19 functions have been implemented -// in just 17 bytes. -// -// @see READ32LE(), READ32BE(), etc. -// @asyncsignalsafe - -bswap_64: -htobe64: -htole64: -be64toh: -le64toh:mov %rdi,%rax - bswap %rax - ret - .endfn le64toh,globl - .endfn be64toh,globl - .endfn htole64,globl - .endfn htobe64,globl - .endfn bswap_64,globl - -bswap_32: -htobe32: -htole32: -be32toh: -le32toh: -ntohl: -htonl: mov %edi,%eax - bswap %eax - ret - .endfn htonl,globl - .endfn htole32,globl - .endfn le32toh,globl - .endfn be32toh,globl - .endfn htobe32,globl - .endfn ntohl,globl - .endfn bswap_32,globl - -bswap_16: -htobe16: -htole16: -be16toh: -le16toh: -ntohs: -htons: movzwl %di,%eax - xchg %al,%ah - ret - .endfn htobe16,globl - .endfn htons,globl - .endfn le16toh,globl - .endfn be16toh,globl - .endfn htole16,globl - .endfn ntohs,globl - .endfn bswap_16,globl diff --git a/libc/nt/thunk/process.inc b/libc/nt/thunk/process.inc index e81ff9d66..856164a60 100644 --- a/libc/nt/thunk/process.inc +++ b/libc/nt/thunk/process.inc @@ -1,10 +1,10 @@ #define GetEnvironmentVariable(...) __imp_GetEnvironmentVariableW(__VA_ARGS__) -extern typeof(GetEnvironmentVariable) *const - __imp_GetEnvironmentVariableW __msabi; +extern typeof(GetEnvironmentVariable) *const __imp_GetEnvironmentVariableW + __msabi; #define SetEnvironmentVariable(...) __imp_SetEnvironmentVariableW(__VA_ARGS__) -extern typeof(SetEnvironmentVariable) *const - __imp_SetEnvironmentVariableW __msabi; +extern typeof(SetEnvironmentVariable) *const __imp_SetEnvironmentVariableW + __msabi; #define GetPriorityClass(...) __imp_GetPriorityClass(__VA_ARGS__) extern typeof(GetPriorityClass) *const __imp_GetPriorityClass __msabi; @@ -17,3 +17,4 @@ extern typeof(GetCurrentProcessId) *const __imp_GetCurrentProcessId __msabi; extern typeof(FormatMessage) *const __imp_FormatMessageW __msabi; extern typeof(SetLastError) *const __imp_SetLastError __msabi; +extern typeof(FormatMessage) *const __imp_FormatMessage __msabi; diff --git a/libc/nt/thunk/runtime.inc b/libc/nt/thunk/runtime.inc index a389fa8d2..c5ccfec09 100644 --- a/libc/nt/thunk/runtime.inc +++ b/libc/nt/thunk/runtime.inc @@ -1,13 +1,13 @@ #define FreeEnvironmentStrings(...) __imp_FreeEnvironmentStringsW(__VA_ARGS__) -extern typeof(FreeEnvironmentStrings) *const - __imp_FreeEnvironmentStringsW __msabi; +extern typeof(FreeEnvironmentStrings) *const __imp_FreeEnvironmentStringsW + __msabi; #define GetCommandLine(...) __imp_GetCommandLineW(__VA_ARGS__) extern typeof(GetCommandLine) *const __imp_GetCommandLineW __msabi; #define GetEnvironmentStrings(...) __imp_GetEnvironmentStringsW(__VA_ARGS__) -extern typeof(GetEnvironmentStrings) *const - __imp_GetEnvironmentStringsW __msabi; +extern typeof(GetEnvironmentStrings) *const __imp_GetEnvironmentStringsW + __msabi; #define GetStdHandle(...) __imp_GetStdHandle(__VA_ARGS__) extern typeof(GetStdHandle) *const __imp_GetStdHandle __msabi; @@ -23,8 +23,8 @@ extern typeof(WriteFile) *const __imp_WriteFile __msabi; #define SetDefaultDllDirectories(...) \ __imp_SetDefaultDllDirectories(__VA_ARGS__) -extern typeof(SetDefaultDllDirectories) *const - __imp_SetDefaultDllDirectories __msabi; +extern typeof(SetDefaultDllDirectories) *const __imp_SetDefaultDllDirectories + __msabi; #define GetCurrentProcess(...) __imp_GetCurrentProcess(__VA_ARGS__) extern typeof(GetCurrentProcess) *const __imp_GetCurrentProcess __msabi; diff --git a/libc/nt/thunk/winsock.inc b/libc/nt/thunk/winsock.inc new file mode 100644 index 000000000..1af97c009 --- /dev/null +++ b/libc/nt/thunk/winsock.inc @@ -0,0 +1 @@ +extern typeof(WSAGetLastError) *const __imp_WSAGetLastError __msabi; diff --git a/libc/nt/winsock.h b/libc/nt/winsock.h index 13a45cc7d..ea2273879 100644 --- a/libc/nt/winsock.h +++ b/libc/nt/winsock.h @@ -6,6 +6,7 @@ #include "libc/nt/struct/overlapped.h" #include "libc/nt/struct/pollfd.h" #include "libc/nt/struct/timeval.h" +#include "libc/nt/thunk/msabi.h" #include "libc/sock/sock.h" #include "libc/sock/struct/sockaddr.h" /* ░▓█████████████████████████████████████████████▓▒ @@ -513,6 +514,9 @@ void GetAcceptExSockaddrs( bool32 DisconnectEx(int64_t s, struct NtOverlapped *inout_opt_lpOverlapped, uint32_t dwFlags, uint32_t dwReserved); +#if ShouldUseMsabiAttribute() +#include "libc/nt/thunk/winsock.inc" +#endif /* ShouldUseMsabiAttribute() */ COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_NT_WINSOCK_H_ */ diff --git a/libc/runtime/arch_prctl.c b/libc/runtime/arch_prctl.c index 9436a1cbb..6e3fee7a7 100644 --- a/libc/runtime/arch_prctl.c +++ b/libc/runtime/arch_prctl.c @@ -127,7 +127,7 @@ static int arch_prctl_xnu(int code, int64_t addr) { } } -static privileged dontinline int arch_prctl_openbsd(int code, int64_t addr) { +static dontinline int arch_prctl_openbsd(int code, int64_t addr) { bool failed; int64_t rax; switch (code) { diff --git a/libc/sock/ntohs.c b/libc/runtime/ftrace_install.c similarity index 76% rename from libc/sock/ntohs.c rename to libc/runtime/ftrace_install.c index 1bd5141dd..297cf46e6 100644 --- a/libc/sock/ntohs.c +++ b/libc/runtime/ftrace_install.c @@ -1,7 +1,7 @@ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ @@ -16,12 +16,22 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/bswap.h" -#include "libc/sock/sock.h" +#include "libc/fmt/itoa.h" +#include "libc/intrin/kprintf.h" +#include "libc/runtime/runtime.h" +#include "libc/runtime/stack.h" +#include "libc/runtime/symbols.internal.h" -/** - * Converts network to host short. - */ -uint16_t(ntohs)(uint16_t x) { - return bswap_16(x); +void ftrace_hook(void); + +_Hide int ftrace_stackdigs; + +textstartup int ftrace_install(void) { + if (GetSymbolTable()) { + ftrace_stackdigs = LengthInt64Thousands(GetStackSize()); + return __hook(ftrace_hook, GetSymbolTable()); + } else { + kprintf("error: --ftrace failed to open symbol table\n"); + return -1; + } } diff --git a/libc/runtime/ftracer.c b/libc/runtime/ftracer.c index b74f2245e..f127a589f 100644 --- a/libc/runtime/ftracer.c +++ b/libc/runtime/ftracer.c @@ -27,7 +27,6 @@ #include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/stack.h" -#include "libc/runtime/symbols.internal.h" #include "libc/thread/tls.h" #include "libc/thread/tls2.h" @@ -47,9 +46,7 @@ #define DETOUR_SKEW 8 #endif -void ftrace_hook(void); - -static int g_stackdigs; +extern _Hide int ftrace_stackdigs; static struct CosmoFtrace g_ftrace; static privileged inline int GetNestingLevelImpl(struct StackFrame *frame) { @@ -73,9 +70,11 @@ static privileged inline int GetNestingLevel(struct CosmoFtrace *ft, /** * Prints name of function being called. * - * We insert CALL instructions that point to this function, in the - * prologues of other functions. We assume those functions behave - * according to the System Five NexGen32e ABI. + * Whenever a function is called, ftrace_hook() will be called from the + * function prologue which saves the parameter registers and calls this + * function, which is responsible for logging the function call. + * + * @see ftrace_install() */ privileged void ftracer(void) { uintptr_t fn; @@ -101,20 +100,10 @@ privileged void ftracer(void) { fn = sf->addr + DETOUR_SKEW; if (fn != ft->ft_lastaddr) { stackuse = GetStackAddr() + GetStackSize() - (intptr_t)sf; - kprintf("%rFUN %6P %'13T %'*ld %*s%t\n", g_stackdigs, stackuse, + kprintf("%rFUN %6P %'13T %'*ld %*s%t\n", ftrace_stackdigs, stackuse, GetNestingLevel(ft, sf) * 2, "", fn); ft->ft_lastaddr = fn; } ft->ft_noreentry = false; } } - -textstartup int ftrace_install(void) { - if (GetSymbolTable()) { - g_stackdigs = LengthInt64Thousands(GetStackSize()); - return __hook(ftrace_hook, GetSymbolTable()); - } else { - kprintf("error: --ftrace failed to open symbol table\n"); - return -1; - } -} diff --git a/libc/sock/ntohl.c b/libc/runtime/getsymbol.c similarity index 64% rename from libc/sock/ntohl.c rename to libc/runtime/getsymbol.c index c2b223eeb..d9aab399d 100644 --- a/libc/sock/ntohl.c +++ b/libc/runtime/getsymbol.c @@ -1,7 +1,7 @@ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ Copyright 2023 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ @@ -16,12 +16,41 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/bswap.h" -#include "libc/sock/sock.h" +#include "libc/runtime/runtime.h" +#include "libc/runtime/symbols.internal.h" + +extern _Hide struct SymbolTable *__symtab; /** - * Converts network to host long. + * Returns low index into symbol table for address. + * + * @param t if null will be auto-populated only if already open + * @return index or -1 if nothing found */ -uint32_t(ntohl)(uint32_t x) { - return bswap_32(x); +noinstrument privileged int __get_symbol(struct SymbolTable *t, intptr_t a) { + // we need privileged because: + // kprintf is privileged and it depends on this + // we don't want function tracing because: + // function tracing depends on this function via kprintf + unsigned l, m, r, n, k; + if (!t && __symtab) { + t = __symtab; + } + if (t) { + l = 0; + r = n = t->count; + k = a - t->addr_base; + while (l < r) { + m = (l + r) >> 1; + if (t->symbols[m].y < k) { + l = m + 1; + } else { + r = m; + } + } + if (l < n && t->symbols[l].x <= k && k <= t->symbols[l].y) { + return l; + } + } + return -1; } diff --git a/libc/runtime/getsymboltable.c b/libc/runtime/getsymboltable.c index df491f9e8..b0dae6e1a 100644 --- a/libc/runtime/getsymboltable.c +++ b/libc/runtime/getsymboltable.c @@ -142,37 +142,3 @@ struct SymbolTable *GetSymbolTable(void) { pthread_spin_unlock(&g_lock); return __symtab; } - -/** - * Returns low index into symbol table for address. - * - * @param t if null will be auto-populated only if already open - * @return index or -1 if nothing found - */ -noinstrument privileged int __get_symbol(struct SymbolTable *t, intptr_t a) { - // we need privileged because: - // kprintf is privileged and it depends on this - // we don't want function tracing because: - // function tracing depends on this function via kprintf - unsigned l, m, r, n, k; - if (!t && __symtab) { - t = __symtab; - } - if (t) { - l = 0; - r = n = t->count; - k = a - t->addr_base; - while (l < r) { - m = (l + r) >> 1; - if (t->symbols[m].y < k) { - l = m + 1; - } else { - r = m; - } - } - if (l < n && t->symbols[l].x <= k && k <= t->symbols[l].y) { - return l; - } - } - return -1; -} diff --git a/libc/runtime/morph.greg.c b/libc/runtime/morph.greg.c index 960e68a68..1d754b49b 100644 --- a/libc/runtime/morph.greg.c +++ b/libc/runtime/morph.greg.c @@ -68,7 +68,6 @@ static privileged void __morph_mprotect(void *addr, size_t size, int prot, if (cf) ax = -ax; if (ax == -EPERM) { kprintf("error: need pledge(prot_exec) permission to code morph\n"); - _Exit(26); } #endif if (ax) notpossible; diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 9870e658b..5bac430f8 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -78,7 +78,7 @@ void fpreset(void); void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t); void *mremap(void *, size_t, size_t, int, ...); int munmap(void *, uint64_t); -int mprotect(void *, uint64_t, int) privileged; +int mprotect(void *, uint64_t, int); int msync(void *, size_t, int); int mlock(const void *, size_t); int munlock(const void *, size_t); diff --git a/libc/runtime/runtime.mk b/libc/runtime/runtime.mk index 3d5dfa32e..1e73755d4 100644 --- a/libc/runtime/runtime.mk +++ b/libc/runtime/runtime.mk @@ -70,7 +70,6 @@ o/$(MODE)/libc/runtime/cosmo2.o: private \ o/$(MODE)/libc/runtime/ftracer.o: private \ CFLAGS += \ -x-no-pg \ - $(MNO_FENTRY) \ -ffreestanding \ -fno-sanitize=all @@ -124,6 +123,14 @@ o/$(MODE)/libc/runtime/enable_tls.o: private \ -mcmodel=large endif +# privileged functions +o/$(MODE)/libc/runtime/getsymbol.o \ +o/$(MODE)/libc/runtime/enable_threads.o \ +o/$(MODE)/libc/runtime/morph_tls.o: private \ + CFLAGS += \ + -ffreestanding \ + -fno-sanitize=all + # these assembly files are safe to build on aarch64 o/$(MODE)/libc/runtime/init.o: libc/runtime/init.S @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< diff --git a/libc/runtime/stackchkfail.c b/libc/runtime/stackchkfail.c index 32512169f..4f5a045db 100644 --- a/libc/runtime/stackchkfail.c +++ b/libc/runtime/stackchkfail.c @@ -17,9 +17,8 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/intrin/kprintf.h" -#include "libc/runtime/internal.h" privileged noasan noinstrument void __stack_chk_fail(void) { kprintf("stack smashed\n"); - _Exitr(207); + __builtin_trap(); } diff --git a/libc/sock/htonl.c b/libc/sock/htonl.c deleted file mode 100644 index 8b19af151..000000000 --- a/libc/sock/htonl.c +++ /dev/null @@ -1,27 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 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/intrin/bswap.h" -#include "libc/sock/sock.h" - -/** - * Converts network to host short. - */ -uint32_t(htonl)(uint32_t x) { - return bswap_32(x); -} diff --git a/libc/sock/htons.c b/libc/sock/htons.c deleted file mode 100644 index 654ac5691..000000000 --- a/libc/sock/htons.c +++ /dev/null @@ -1,27 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 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/intrin/bswap.h" -#include "libc/sock/sock.h" - -/** - * Converts host to network short. - */ -uint16_t(htons)(uint16_t x) { - return bswap_16(x); -} diff --git a/libc/stdio/stdio.h b/libc/stdio/stdio.h index ae0075d3e..ce68ec7b6 100644 --- a/libc/stdio/stdio.h +++ b/libc/stdio/stdio.h @@ -166,16 +166,6 @@ int vfprintf_unlocked(FILE *, const char *, va_list) │ cosmopolitan § standard i/o » optimizations ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -#define getc(f) fgetc(f) -#define getwc(f) fgetwc(f) -#define putc(c, f) fputc(c, f) -#define putwc(c, f) fputwc(c, f) - -#define getc_unlocked(f) fgetc_unlocked(f) -#define getwc_unlocked(f) fgetwc_unlocked(f) -#define putc_unlocked(c, f) fputc_unlocked(c, f) -#define putwc_unlocked(c, f) fputwc_unlocked(c, f) - #if defined(__GNUC__) && !defined(__STRICT_ANSI__) /* clang-format off */ #define printf(FMT, ...) (printf)(PFLINK(FMT), ##__VA_ARGS__) diff --git a/libc/sysv/errno_location.greg.c b/libc/sysv/errno_location.greg.c index e0dc52218..fe1fc4cd6 100644 --- a/libc/sysv/errno_location.greg.c +++ b/libc/sysv/errno_location.greg.c @@ -22,7 +22,7 @@ /** * Returns address of errno variable. */ -nocallersavedregisters errno_t *(__errno_location)(void) { +privileged nocallersavedregisters errno_t *(__errno_location)(void) { if (!__tls_enabled) return &__errno; return &__get_tls_privileged()->tib_errno; } diff --git a/libc/vga/tty-klog.greg.c b/libc/vga/tty-klog.greg.c index 4730abd8d..01c60e156 100644 --- a/libc/vga/tty-klog.greg.c +++ b/libc/vga/tty-klog.greg.c @@ -90,7 +90,7 @@ static unsigned short klog_y = 0, klog_x = 0; -privileged void _klog_vga(const char *b, size_t n) { +void _klog_vga(const char *b, size_t n) { struct Tty tty; _vga_reinit(&tty, klog_y, klog_x, kTtyKlog); _TtyWrite(&tty, b, n); diff --git a/test/libc/runtime/ftrace_test.c b/test/libc/runtime/ftrace_test.c index ea32044e0..ea75a3740 100644 --- a/test/libc/runtime/ftrace_test.c +++ b/test/libc/runtime/ftrace_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/dce.h" #include "libc/mem/gc.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" @@ -26,6 +27,7 @@ char testlib_enable_tmp_setup_teardown; TEST(ftrace, test) { + if (!IsOptimized()) return; // TODO(jart): fix me const char *ftraceasm; testlib_extract("/zip/ftraceasm.txt", "ftraceasm.txt", 0755); ftraceasm = _gc(xslurp("ftraceasm.txt", 0)); @@ -38,7 +40,7 @@ TEST(ftrace, test) { #endif fprintf(stderr, "error: ftrace_hook() depends on floating point code\n" - "you need to objdump o//test/libc/runtime/ftraceasm.elf\n" + "you need to objdump -d o//test/libc/runtime/prog/ftraceasm.elf\n" "then compile the guilty module with -mgeneral-regs-only\n"); exit(1); } diff --git a/test/libc/runtime/prog/ftraceasm.c b/test/libc/runtime/prog/ftraceasm.c index caa22ae09..f26a5d8ef 100644 --- a/test/libc/runtime/prog/ftraceasm.c +++ b/test/libc/runtime/prog/ftraceasm.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ void ftrace_hook(void); -void _start(void) { + +privileged void _start(void) { ftrace_hook(); } diff --git a/test/libc/runtime/test.mk b/test/libc/runtime/test.mk index 92cdce597..6397e2a59 100644 --- a/test/libc/runtime/test.mk +++ b/test/libc/runtime/test.mk @@ -55,6 +55,7 @@ o/$(MODE)/test/libc/runtime/%.com.dbg: \ o/$(MODE)/test/libc/runtime/prog/ftraceasm.txt.zip.o \ o/$(MODE)/test/libc/runtime/%.o \ o/$(MODE)/test/libc/runtime/runtime.pkg \ + o/$(MODE)/test/libc/runtime/runtime.pkg \ $(LIBC_TESTMAIN) \ $(CRT) \ $(APE_NO_MODIFY_SELF) @@ -86,7 +87,7 @@ o/$(MODE)/test/libc/runtime/prog/ftraceasm.elf: \ $(TEST_LIBC_RUNTIME_DEPS) \ o/$(MODE)/test/libc/runtime/prog/ftraceasm.o \ o/$(MODE)/test/libc/runtime/runtime.pkg - @$(ELFLINK) + @$(ELFLINK) --gc-sections o/$(MODE)/test/libc/runtime/prog/ftraceasm.txt: \ o/$(MODE)/test/libc/runtime/prog/ftraceasm.elf @$(OBJDUMP) -d $< >$@ diff --git a/test/libc/stdio/system_test.c b/test/libc/stdio/system_test.c index 5cf7089a6..6a97baf32 100644 --- a/test/libc/stdio/system_test.c +++ b/test/libc/stdio/system_test.c @@ -69,6 +69,7 @@ TEST(system, testStdoutRedirect_withSpacesInFilename) { } TEST(system, testStderrRedirect_toStdout) { + if (IsAsan()) return; // TODO(jart): fix me int pipefd[2]; int stdoutBack = dup(1); ASSERT_NE(-1, stdoutBack); diff --git a/test/libc/str/memmove_test.c b/test/libc/str/memmove_test.c deleted file mode 100644 index 7a1703e2b..000000000 --- a/test/libc/str/memmove_test.c +++ /dev/null @@ -1,48 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2021 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/str/str.h" -#include "libc/testlib/testlib.h" - -forceinline void *Memmove(void *restrict d, const void *restrict s, size_t n) { - return __builtin___memmove_chk(d, s, n, __builtin_object_size(d, 0)); -} - -void foo1(void *p, void *q) { - Memmove(p, q, 19); -} - -TEST(memmove, supposedPythonBug_test1) { - char a[32] = "123456789000000000"; - foo1(&a[9], a); - EXPECT_STREQ("123456789123456789000000000", a); - foo1(a, &a[9]); - EXPECT_STREQ("123456789000000000", a); -} - -void foo2(void *p, void *q) { - memmove(p, q, 19); -} - -TEST(memmove, supposedPythonBug_test2) { - char a[32] = "123456789000000000"; - foo2(&a[9], a); - EXPECT_STREQ("123456789123456789000000000", a); - foo2(a, &a[9]); - EXPECT_STREQ("123456789000000000", a); -} diff --git a/test/libc/thread/sem_open_test.c b/test/libc/thread/sem_open_test.c index 8a86a39a0..9b8fbe8c8 100644 --- a/test/libc/thread/sem_open_test.c +++ b/test/libc/thread/sem_open_test.c @@ -107,7 +107,7 @@ TEST(sem_close, withUnnamedSemaphore_isUndefinedBehavior) { SPAWN(fork); IgnoreStderr(); sem_close(&sem); - EXITS(77); + EXITS(23); // see __assert_fail ASSERT_SYS(0, 0, sem_destroy(&sem)); } @@ -118,7 +118,7 @@ TEST(sem_destroy, withNamedSemaphore_isUndefinedBehavior) { SPAWN(fork); IgnoreStderr(); sem_destroy(sem); - EXITS(77); + EXITS(23); // see __assert_fail ASSERT_SYS(0, 0, sem_unlink("/boop")); ASSERT_SYS(0, 0, sem_close(sem)); } diff --git a/test/libc/thread/sem_timedwait_test.c b/test/libc/thread/sem_timedwait_test.c index bb8beb2a7..ddd5d2b28 100644 --- a/test/libc/thread/sem_timedwait_test.c +++ b/test/libc/thread/sem_timedwait_test.c @@ -51,7 +51,7 @@ TEST(sem_post, afterDestroyed_isUndefinedBehavior) { ASSERT_SYS(0, 0, sem_destroy(&sem)); IgnoreStderr(); sem_post(&sem); - EXITS(77); + EXITS(23); // see __assert_fail } TEST(sem_trywait, afterDestroyed_isUndefinedBehavior) { @@ -63,7 +63,7 @@ TEST(sem_trywait, afterDestroyed_isUndefinedBehavior) { ASSERT_SYS(0, 0, sem_destroy(&sem)); IgnoreStderr(); sem_trywait(&sem); - EXITS(77); + EXITS(23); // see __assert_fail } TEST(sem_wait, afterDestroyed_isUndefinedBehavior) { @@ -75,7 +75,7 @@ TEST(sem_wait, afterDestroyed_isUndefinedBehavior) { ASSERT_SYS(0, 0, sem_destroy(&sem)); IgnoreStderr(); sem_wait(&sem); - EXITS(77); + EXITS(23); // see __assert_fail } TEST(sem_timedwait, afterDestroyed_isUndefinedBehavior) { @@ -87,7 +87,7 @@ TEST(sem_timedwait, afterDestroyed_isUndefinedBehavior) { ASSERT_SYS(0, 0, sem_destroy(&sem)); IgnoreStderr(); sem_timedwait(&sem, 0); - EXITS(77); + EXITS(23); // see __assert_fail } void *Worker(void *arg) { diff --git a/third_party/awk/b.c b/third_party/awk/b.c index 843165a2c..a144c8aa4 100644 --- a/third_party/awk/b.c +++ b/third_party/awk/b.c @@ -1214,6 +1214,7 @@ rescan: } break; } + return 0; /* [jart] why wasn't this here? */ } int cgoto(fa *f, int s, int c) diff --git a/third_party/ggml/common.cc b/third_party/ggml/common.cc index 3931996df..b478bc3ce 100644 --- a/third_party/ggml/common.cc +++ b/third_party/ggml/common.cc @@ -34,6 +34,7 @@ #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/sysv/consts/fileno.h" +#include "libc/sysv/consts/termios.h" #include "third_party/ggml/llama.h" #include "third_party/ggml/llama_util.h" #include "third_party/libcxx/algorithm" diff --git a/third_party/ggml/ggml.mk b/third_party/ggml/ggml.mk index afec5a401..6e59f8ec5 100644 --- a/third_party/ggml/ggml.mk +++ b/third_party/ggml/ggml.mk @@ -100,14 +100,6 @@ o/opt/third_party/ggml/ggml.o: private \ CFLAGS += \ -x-no-pg -ifeq ($(ARCH), x86_64) -o/rel/third_party/ggml/ggml.o \ -o/opt/third_party/ggml/ggml.o: private \ - CFLAGS += \ - -fschedule-insns2 \ - -mred-zone -endif - ################################################################################ # command for running inference on large language models # make -j8 o//third_party/ggml/llama.com diff --git a/third_party/linenoise/linenoise.c b/third_party/linenoise/linenoise.c index 60a66e5dc..0da0c74cc 100644 --- a/third_party/linenoise/linenoise.c +++ b/third_party/linenoise/linenoise.c @@ -129,6 +129,7 @@ #include "third_party/linenoise/linenoise.h" #include "libc/assert.h" #include "libc/calls/calls.h" +#include "libc/calls/ioctl.h" #include "libc/calls/sig.internal.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/stat.h" diff --git a/third_party/mbedtls/test/test_suite_shax.c b/third_party/mbedtls/test/test_suite_shax.c index ea8aca576..5852dc13b 100644 --- a/third_party/mbedtls/test/test_suite_shax.c +++ b/third_party/mbedtls/test/test_suite_shax.c @@ -269,7 +269,7 @@ void test_sha512_valid_param_wrapper( void ** params ) void test_sha512_invalid_param( ) { mbedtls_sha512_context ctx; - unsigned char buf[64] = { 0 }; + unsigned char buf[128] = { 0 }; size_t const buflen = sizeof( buf ); int valid_type = 0; int invalid_type = 42; diff --git a/third_party/nsync/atomic.h b/third_party/nsync/atomic.h index d91f579c7..f157cb8b5 100644 --- a/third_party/nsync/atomic.h +++ b/third_party/nsync/atomic.h @@ -4,7 +4,7 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -typedef atomic_uint_fast32_t nsync_atomic_uint32_; +#define nsync_atomic_uint32_ atomic_uint_fast32_t #define NSYNC_ATOMIC_UINT32_INIT_ 0 #define NSYNC_ATOMIC_UINT32_LOAD_(p) (*(p)) diff --git a/third_party/python/Modules/posixmodule.c b/third_party/python/Modules/posixmodule.c index 955571644..73eed567a 100644 --- a/third_party/python/Modules/posixmodule.c +++ b/third_party/python/Modules/posixmodule.c @@ -5,9 +5,11 @@ │ https://docs.python.org/3/license.html │ ╚─────────────────────────────────────────────────────────────────────────────*/ #define PY_SSIZE_T_CLEAN +#include "third_party/python/Modules/posixmodule.h" #include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/ioctl.h" #include "libc/calls/makedev.h" #include "libc/calls/struct/dirent.h" #include "libc/calls/struct/iovec.h" @@ -56,6 +58,7 @@ #include "libc/sysv/consts/sf.h" #include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/st.h" +#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/w.h" #include "libc/sysv/consts/waitid.h" #include "libc/sysv/errfuns.h" @@ -87,7 +90,6 @@ #include "third_party/python/Include/warnings.h" #include "third_party/python/Include/yoink.h" #include "third_party/python/Modules/_multiprocessing/multiprocessing.h" -#include "third_party/python/Modules/posixmodule.h" #include "third_party/python/pyconfig.h" /* clang-format off */ diff --git a/third_party/unzip/ttyio.c b/third_party/unzip/ttyio.c index 59179c918..566221be7 100644 --- a/third_party/unzip/ttyio.c +++ b/third_party/unzip/ttyio.c @@ -32,6 +32,8 @@ #include "libc/calls/struct/termios.h" #include "libc/calls/termios.h" #include "third_party/unzip/crypt.h" +#include "libc/sysv/consts/termios.h" +#include "libc/calls/ioctl.h" #include "third_party/unzip/globals.h" #if (CRYPT || (defined(UNZIP) && !defined(FUNZIP))) diff --git a/tool/build/emubin/emubin.mk b/tool/build/emubin/emubin.mk index 00c154cd4..671b6e2c0 100644 --- a/tool/build/emubin/emubin.mk +++ b/tool/build/emubin/emubin.mk @@ -48,17 +48,17 @@ o/$(MODE)/tool/build/emubin/%.bin.dbg: \ $(TOOL_BUILD_EMUBIN_A) \ o/$(MODE)/tool/build/emubin/%.o \ $(TOOL_BUILD_EMUBIN_A).pkg - @$(ELFLINK) -e emucrt -z max-page-size=0x10 + @$(ELFLINK) -e emucrt -z common-page-size=0x10 -z max-page-size=0x10 o/tiny/tool/build/emubin/spiral.bin.dbg: \ $(TOOL_BUILD_EMUBIN_DEPS) \ o/tiny/tool/build/emubin/spiral.real.o - @$(ELFLINK) -z max-page-size=0x10 -T tool/build/emucrt/real.lds + @$(ELFLINK) -z common-page-size=0x10 -z max-page-size=0x10 -T tool/build/emucrt/real.lds o/tiny/tool/build/emubin/mdatest.bin.dbg: \ $(TOOL_BUILD_EMUBIN_DEPS) \ o/tiny/tool/build/emubin/mdatest.real.o - @$(ELFLINK) -z max-page-size=0x10 -T tool/build/emucrt/real.lds + @$(ELFLINK) -z common-page-size=0x10 -z max-page-size=0x10 -T tool/build/emucrt/real.lds $(TOOL_BUILD_EMUBIN_OBJS): private \ CFLAGS += \ diff --git a/tool/build/fixupobj.c b/tool/build/fixupobj.c index 557929bf1..20bcc2cae 100644 --- a/tool/build/fixupobj.c +++ b/tool/build/fixupobj.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" #include "libc/dce.h" @@ -26,9 +27,11 @@ #include "libc/elf/struct/sym.h" #include "libc/errno.h" #include "libc/fmt/itoa.h" +#include "libc/intrin/kprintf.h" #include "libc/log/check.h" #include "libc/log/log.h" #include "libc/macros.internal.h" +#include "libc/mem/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "libc/sysv/consts/map.h" @@ -41,20 +44,21 @@ * @fileoverview GCC Codegen Fixer-Upper. */ -#define GETOPTS "h" +#define GETOPTS "ch" #define USAGE \ "\ Usage: fixupobj.com [-h] ARGS...\n\ -?\n\ -h show help\n\ + -c check-only mode\n\ " #define COSMO_TLS_REG 28 #define MRS_TPIDR_EL0 0xd53bd040u #define MOV_REG(DST, SRC) (0xaa0003e0u | (SRC) << 16 | (DST)) -static const unsigned char kFatNops[8][8] = { +const unsigned char kFatNops[8][8] = { {}, // {0x90}, // nop {0x66, 0x90}, // xchg %ax,%ax @@ -65,31 +69,43 @@ static const unsigned char kFatNops[8][8] = { {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, // nopl 0x00000000(%rax) }; -void Write(const char *s, ...) { +int mode; +char *symstrs; +char *secstrs; +ssize_t esize; +Elf64_Sym *syms; +const char *epath; +Elf64_Xword symcount; +const Elf64_Ehdr *elf; + +void Print(int fd, const char *s, ...) { va_list va; + char buf[2048]; va_start(va, s); + buf[0] = 0; do { - write(2, s, strlen(s)); + strlcat(buf, s, sizeof(buf)); } while ((s = va_arg(va, const char *))); + strlcat(buf, "\n", sizeof(buf)); + write(fd, buf, strlen(buf)); va_end(va); } -wontreturn void SysExit(int rc, const char *call, const char *thing) { - int err; - char ibuf[12]; - const char *estr; - err = errno; - FormatInt32(ibuf, err); - estr = _strerdoc(err); - if (!estr) estr = "EUNKNOWN"; - Write(thing, ": ", call, "() failed: ", estr, " (", ibuf, ")\n", NULL); - exit(rc); +wontreturn void SysExit(const char *func) { + const char *errstr; + if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; + Print(2, epath, ": ", func, " failed with ", errstr, "\n", NULL); + exit(1); } -static void GetOpts(int argc, char *argv[]) { +void GetOpts(int argc, char *argv[]) { int opt; + mode = O_RDWR; while ((opt = getopt(argc, argv, GETOPTS)) != -1) { switch (opt) { + case 'c': + mode = O_RDONLY; + break; case 'h': case '?': write(1, USAGE, sizeof(USAGE) - 1); @@ -101,17 +117,56 @@ static void GetOpts(int argc, char *argv[]) { } } +Elf64_Shdr *FindElfSectionByName(const char *name) { + long i; + Elf64_Shdr *shdr; + for (i = 0; i < elf->e_shnum; ++i) { + shdr = GetElfSectionHeaderAddress(elf, esize, i); + if (!strcmp(GetElfString(elf, esize, secstrs, shdr->sh_name), name)) { + return shdr; + } + } + return 0; +} + +void CheckPrivilegedCrossReferences(void) { + long i, x; + Elf64_Shdr *shdr; + const char *secname; + Elf64_Rela *rela, *erela; + if (!(shdr = FindElfSectionByName(".rela.privileged"))) return; + rela = GetElfSectionAddress(elf, esize, shdr); + erela = rela + shdr->sh_size / sizeof(*rela); + for (; rela < erela; ++rela) { + if (!ELF64_R_TYPE(rela->r_info)) continue; + if (!(x = ELF64_R_SYM(rela->r_info))) continue; + if (syms[x].st_shndx == SHN_ABS) continue; + if (!syms[x].st_shndx) continue; + shdr = GetElfSectionHeaderAddress(elf, esize, syms[x].st_shndx); + if (~shdr->sh_flags & SHF_EXECINSTR) continue; // data reference + secname = GetElfString(elf, esize, secstrs, shdr->sh_name); + if (strcmp(".privileged", secname)) { + Print(2, epath, + ": code in .privileged section " + "references symbol '", + GetElfString(elf, esize, symstrs, syms[x].st_name), + "' in unprivileged code section '", secname, "'\n", NULL); + exit(1); + } + } +} + // Modify ARM64 code to use x28 for TLS rather than tpidr_el0. -void RewriteTlsCode(Elf64_Ehdr *elf, size_t elfsize) { +void RewriteTlsCode(void) { int i, dest; Elf64_Shdr *shdr; uint32_t *p, *pe; for (i = 0; i < elf->e_shnum; ++i) { - shdr = GetElfSectionHeaderAddress(elf, elfsize, i); + shdr = GetElfSectionHeaderAddress(elf, esize, i); if (shdr->sh_type == SHT_PROGBITS && // (shdr->sh_flags & SHF_ALLOC) && // (shdr->sh_flags & SHF_EXECINSTR) && // - (p = GetElfSectionAddress(elf, elfsize, shdr))) { + (p = GetElfSectionAddress(elf, esize, shdr))) { for (pe = p + shdr->sh_size / 4; p <= pe; ++p) { if ((*p & -32) == MRS_TPIDR_EL0) { *p = MOV_REG(*p & 31, COSMO_TLS_REG); @@ -131,19 +186,16 @@ void RewriteTlsCode(Elf64_Ehdr *elf, size_t elfsize) { * In order for this to work, the function symbol must be declared as * `STT_FUNC` and `st_size` must have the function's byte length. */ -void OptimizePatchableFunctionEntries(Elf64_Ehdr *elf, size_t elfsize) { +void OptimizePatchableFunctionEntries(void) { #ifdef __x86_64__ long i, n; int nopcount; - Elf64_Sym *syms; Elf64_Shdr *shdr; - Elf64_Xword symcount; unsigned char *p, *pe; - CHECK_NOTNULL((syms = GetElfSymbolTable(elf, elfsize, &symcount))); for (i = 0; i < symcount; ++i) { if (ELF64_ST_TYPE(syms[i].st_info) == STT_FUNC && syms[i].st_size) { - shdr = GetElfSectionHeaderAddress(elf, elfsize, syms[i].st_shndx); - p = GetElfSectionAddress(elf, elfsize, shdr); + shdr = GetElfSectionHeaderAddress(elf, esize, syms[i].st_shndx); + p = GetElfSectionAddress(elf, esize, shdr); p += syms[i].st_value; pe = p + syms[i].st_size; for (; p + 1 < pe; p += n) { @@ -159,27 +211,22 @@ void OptimizePatchableFunctionEntries(Elf64_Ehdr *elf, size_t elfsize) { #endif /* __x86_64__ */ } -void OptimizeRelocations(Elf64_Ehdr *elf, size_t elfsize) { - char *strs; +void OptimizeRelocations(void) { Elf64_Half i; - Elf64_Sym *syms; Elf64_Rela *rela; - Elf64_Xword symcount; unsigned char *code, *p; Elf64_Shdr *shdr, *shdrcode; - CHECK_NOTNULL((strs = GetElfStringTable(elf, elfsize))); - CHECK_NOTNULL((syms = GetElfSymbolTable(elf, elfsize, &symcount))); for (i = 0; i < elf->e_shnum; ++i) { - shdr = GetElfSectionHeaderAddress(elf, elfsize, i); + shdr = GetElfSectionHeaderAddress(elf, esize, i); if (shdr->sh_type == SHT_RELA) { CHECK_EQ(sizeof(struct Elf64_Rela), shdr->sh_entsize); CHECK_NOTNULL( - (shdrcode = GetElfSectionHeaderAddress(elf, elfsize, shdr->sh_info))); + (shdrcode = GetElfSectionHeaderAddress(elf, esize, shdr->sh_info))); if (!(shdrcode->sh_flags & SHF_EXECINSTR)) continue; - CHECK_NOTNULL((code = GetElfSectionAddress(elf, elfsize, shdrcode))); - for (rela = GetElfSectionAddress(elf, elfsize, shdr); + CHECK_NOTNULL((code = GetElfSectionAddress(elf, esize, shdrcode))); + for (rela = GetElfSectionAddress(elf, esize, shdr); ((uintptr_t)rela + shdr->sh_entsize <= - MIN((uintptr_t)elf + elfsize, + MIN((uintptr_t)elf + esize, (uintptr_t)elf + shdr->sh_offset + shdr->sh_size)); ++rela) { @@ -189,7 +236,7 @@ void OptimizeRelocations(Elf64_Ehdr *elf, size_t elfsize) { * Then libc/runtime/ftrace.greg.c morphs it back at runtime. */ if (ELF64_R_TYPE(rela->r_info) == R_X86_64_GOTPCRELX && - strcmp(GetElfString(elf, elfsize, strs, + strcmp(GetElfString(elf, esize, symstrs, syms[ELF64_R_SYM(rela->r_info)].st_name), "mcount") == 0) { rela->r_info = R_X86_64_NONE; @@ -207,7 +254,7 @@ void OptimizeRelocations(Elf64_Ehdr *elf, size_t elfsize) { */ if ((ELF64_R_TYPE(rela->r_info) == R_X86_64_PC32 || ELF64_R_TYPE(rela->r_info) == R_X86_64_PLT32) && - strcmp(GetElfString(elf, elfsize, strs, + strcmp(GetElfString(elf, esize, symstrs, syms[ELF64_R_SYM(rela->r_info)].st_name), "mcount") == 0) { rela->r_info = R_X86_64_NONE; @@ -223,45 +270,65 @@ void OptimizeRelocations(Elf64_Ehdr *elf, size_t elfsize) { } } -void RewriteObject(const char *path) { +void FixupObject(void) { int fd; - struct stat st; - Elf64_Ehdr *elf; - if ((fd = open(path, O_RDWR)) == -1) { - SysExit(__COUNTER__ + 1, "open", path); + if ((fd = open(epath, mode)) == -1) { + SysExit("open"); } - if (fstat(fd, &st) == -1) { - SysExit(__COUNTER__ + 1, "fstat", path); + if ((esize = lseek(fd, 0, SEEK_END)) == -1) { + SysExit("lseek"); } - if (st.st_size >= 64) { - if ((elf = mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, - 0)) == MAP_FAILED) { - SysExit(__COUNTER__ + 1, "mmap", path); + if (esize) { + if ((elf = mmap(0, esize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == + MAP_FAILED) { + SysExit("mmap"); } - if (elf->e_machine == EM_NEXGEN32E) { - OptimizeRelocations(elf, st.st_size); - OptimizePatchableFunctionEntries(elf, st.st_size); + if (!IsElf64Binary(elf, esize)) { + Print(2, epath, ": not an elf64 binary\n", NULL); + exit(1); } - if (elf->e_machine == EM_AARCH64) { - RewriteTlsCode(elf, st.st_size); + if (!(syms = GetElfSymbolTable(elf, esize, &symcount))) { + Print(2, epath, ": missing elf symbol table\n", NULL); + exit(1); } - if (msync(elf, st.st_size, MS_ASYNC | MS_INVALIDATE)) { - SysExit(__COUNTER__ + 1, "msync", path); + if (!(secstrs = GetElfSectionNameStringTable(elf, esize))) { + Print(2, epath, ": missing elf section string table\n", NULL); + exit(1); } - if (munmap(elf, st.st_size)) { - SysExit(__COUNTER__ + 1, "munmap", path); + if (!(symstrs = GetElfStringTable(elf, esize))) { + Print(2, epath, ": missing elf symbol string table\n", NULL); + exit(1); + } + CheckPrivilegedCrossReferences(); + if (mode == O_RDWR) { + if (elf->e_machine == EM_NEXGEN32E) { + OptimizeRelocations(); + OptimizePatchableFunctionEntries(); + } + if (elf->e_machine == EM_AARCH64) { + RewriteTlsCode(); + } + if (msync(elf, esize, MS_ASYNC | MS_INVALIDATE)) { + SysExit("msync"); + } + } + if (munmap(elf, esize)) { + SysExit("munmap"); } } if (close(fd)) { - SysExit(__COUNTER__ + 1, "close", path); + SysExit("close"); } } int main(int argc, char *argv[]) { int i, opt; - if (IsModeDbg()) ShowCrashReports(); + if (!IsOptimized()) { + ShowCrashReports(); + } GetOpts(argc, argv); for (i = optind; i < argc; ++i) { - RewriteObject(argv[i]); + epath = argv[i]; + FixupObject(); } } diff --git a/tool/build/lib/persist.c b/tool/build/lib/persist.c deleted file mode 100644 index 601110453..000000000 --- a/tool/build/lib/persist.c +++ /dev/null @@ -1,120 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/calls.h" -#include "libc/calls/struct/iovec.h" -#include "libc/intrin/bsr.h" -#include "libc/log/check.h" -#include "libc/macros.internal.h" -#include "libc/mem/gc.h" -#include "libc/sock/sock.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/o.h" -#include "libc/x/x.h" -#include "tool/build/lib/persist.h" - -static bool IsWithin(size_t sz1, void *vp1, size_t sz2, void *vp2) { - char *p1 = vp1, *p2 = vp2; - return p1 >= p2 && p1 + sz1 <= p2 + sz2; -} - -static bool IsOverlapping(void *vx1, void *vy1, void *vx2, void *vy2) { - char *x1 = vx1, *y1 = vy1, *x2 = vx2, *y2 = vy2; - return (x1 >= x2 && x1 <= y2) || (y1 >= x2 && y1 <= y2); -} - -static bool IsOverlappingIov(struct iovec *a, struct iovec *b) { - char *ap = a->iov_base, *bp = b->iov_base; - return IsOverlapping(ap, ap + a->iov_len, bp, bp + b->iov_len); -} - -/** - * Writes struct w/ dynamic arrays to mappable file, e.g. - * - * PersistObject(path, 64, &(struct ObjectParam){ - * sizeof(*o), o, &o->magic, &o->abi, - * &(struct ObjectArrayParam){ - * {&o->a1.i, sizeof(o->a1.p[0]), &o->a1.p}, - * {&o->a2.i, sizeof(o->a2.p[0]), &o->a2.p}, - * {0}, - * }}); - * - * @param obj->magic needs to be unique for struct - * @param obj->abi monotonically tracks breaking changes - * @param obj->arrays needs sentinel with item size of zero - * @note non-recursive i.e. array elements can't have pointers - * @see MapObject() - */ -void PersistObject(const char *path, size_t align, - const struct ObjectParam *obj) { - const char *pad; - struct iovec *iov; - int i, n, fd, iovlen; - long len, size, bytes, filesize; - unsigned char *hdr, *p1, *p2, **pp; - intptr_t arrayptroffset, arraydataoffset; - filesize = 0; - DCHECK_GE(align, 1); - CHECK_GT(*obj->magic, 0); - CHECK_GT(*obj->abi, 0); - CHECK(IsWithin(sizeof(*obj->magic), obj->magic, obj->size, obj->p)); - CHECK(IsWithin(sizeof(*obj->abi), obj->abi, obj->size, obj->p)); - for (n = i = 0; obj->arrays[i].size; ++i) ++n; - iovlen = (n + 1) * 2; - pad = _gc(xcalloc(align, 1)); - hdr = _gc(xmalloc(obj->size)); - iov = _gc(xcalloc(iovlen, sizeof(*iov))); - bytes = obj->size; - iov[0].iov_base = memcpy(hdr, obj->p, obj->size); - iov[0].iov_len = bytes; - iov[1].iov_base = pad; - iov[1].iov_len = ROUNDUP(bytes, align) - bytes; - filesize += ROUNDUP(bytes, align); - for (i = 0; i < n; ++i) { - pp = obj->arrays[i].pp; - len = obj->arrays[i].len; - size = obj->arrays[i].size; - if (!*pp || !len) continue; - p1 = obj->p; - p2 = obj->arrays[i].pp; - arrayptroffset = p2 - p1; - arraydataoffset = filesize; - CHECK((!len || _bsrl(len) + _bsrl(size) < 31), - "path=%s i=%d len=%,lu size=%,lu", path, i, len, size); - CHECK(IsWithin(sizeof(void *), pp, obj->size, obj->p)); - CHECK(!IsOverlapping(pp, pp + sizeof(void *), obj->magic, - obj->magic + sizeof(*obj->magic))); - CHECK(!IsOverlapping(pp, pp + sizeof(void *), obj->abi, - obj->abi + sizeof(*obj->abi))); - memcpy(hdr + arrayptroffset, &arraydataoffset, sizeof(intptr_t)); - CHECK_LT(filesize + arraydataoffset, 0x7ffff000); - bytes = len * size; - iov[(i + 1) * 2 + 0].iov_base = *pp; - iov[(i + 1) * 2 + 0].iov_len = bytes; - iov[(i + 1) * 2 + 1].iov_base = pad; - iov[(i + 1) * 2 + 1].iov_len = ROUNDUP(bytes, align) - bytes; - filesize += ROUNDUP(bytes, align); - CHECK(!IsOverlappingIov(&iov[(i + 0) * 2], &iov[(i + 1) * 2]), - "iov[%d]={%#p,%#x}, iov[%d]={%#p,%#x} path=%s", (i + 0) * 2, - iov[(i + 0) * 2].iov_base, iov[(i + 0) * 2].iov_len, (i + 1) * 2, - iov[(i + 1) * 2].iov_base, iov[(i + 1) * 2].iov_len, path); - } - CHECK_NE(-1, (fd = creat(path, 0644)), "%s", path); - CHECK_EQ(filesize, writev(fd, iov, iovlen)); - CHECK_NE(-1, close(fd)); -} diff --git a/tool/build/lib/persist.h b/tool/build/lib/persist.h deleted file mode 100644 index 731b63b49..000000000 --- a/tool/build/lib/persist.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PERSIST_H_ -#define COSMOPOLITAN_TOOL_BUILD_LIB_PERSIST_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -struct ObjectArrayParam { - size_t len; - size_t size; - void *pp; -}; - -struct ObjectParam { - size_t size; - void *p; - uint32_t *magic; - int32_t *abi; - struct ObjectArrayParam * arrays; -}; - -void PersistObject(const char *, size_t, const struct ObjectParam *); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PERSIST_H_ */ diff --git a/tool/build/package.c b/tool/build/package.c index e4ffd2bcb..2894135b9 100644 --- a/tool/build/package.c +++ b/tool/build/package.c @@ -17,14 +17,18 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/stat.h" +#include "libc/dce.h" #include "libc/elf/elf.h" +#include "libc/elf/struct/rela.h" #include "libc/elf/struct/shdr.h" #include "libc/elf/struct/sym.h" +#include "libc/errno.h" #include "libc/intrin/bswap.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/log/check.h" +#include "libc/intrin/kprintf.h" #include "libc/log/log.h" +#include "libc/macros.internal.h" #include "libc/mem/alg.h" #include "libc/mem/arraylist.internal.h" #include "libc/mem/mem.h" @@ -36,7 +40,8 @@ #include "third_party/getopt/getopt.h" #include "third_party/xed/x86.h" #include "tool/build/lib/getargs.h" -#include "tool/build/lib/persist.h" + +STATIC_YOINK("realloc"); /** * @fileoverview Build Package Script. @@ -67,7 +72,21 @@ */ #define PACKAGE_MAGIC bswap_32(0xBEEFBEEFu) -#define PACKAGE_ABI 1 +#define PACKAGE_ABI 2 + +struct ObjectArrayParam { + size_t len; + size_t size; + void *pp; +}; + +struct ObjectParam { + size_t size; + void *p; + uint32_t *magic; + int32_t *abi; + struct ObjectArrayParam *arrays; +}; struct Packages { size_t i, n; @@ -77,7 +96,7 @@ struct Packages { uint32_t path; // pkg->strings.p[path] int64_t fd; // not persisted void *addr; // not persisted - size_t size; // not persisted + ssize_t size; // not persisted struct Strings { size_t i, n; char *p; // persisted as pkg+RVA @@ -86,28 +105,29 @@ struct Packages { size_t i, n; struct Object { uint32_t path; // pkg->strings.p[path] - unsigned mode; // not persisted struct Elf64_Ehdr *elf; // not persisted size_t size; // not persisted char *strs; // not persisted Elf64_Sym *syms; // not persisted Elf64_Xword symcount; // not persisted - struct Sections { - size_t i, n; - struct Section { - enum SectionKind { - kUndef, - kText, - kData, - kPiroRelo, - kPiroData, - kPiroBss, - kBss, - } kind; - } * p; - } sections; // not persisted - } * p; // persisted as pkg+RVA + int section_offset; + int section_count; + } * p; } objects; + struct Sections { + size_t i, n; + struct Section { + int name; + enum SectionKind { + kUndef, + kText, + kPrivilegedText, + kData, + kBss, + kOther, + } kind; + } * p; + } sections; struct Symbols { size_t i, n; struct Symbol { @@ -115,80 +135,223 @@ struct Packages { enum SectionKind kind : 8; uint8_t bind_ : 4; uint8_t type : 4; - uint16_t object; // pkg->objects.p[object] - } * p; // persisted as pkg+RVA - } symbols, undefs; // TODO(jart): hash undefs? - } * *p; // persisted across multiple files + uint16_t object; // pkg->objects.p[object] + uint16_t section; // pkg->sections.p[section] + } * p; // persisted as pkg+RVA + } symbols, undefs; // TODO(jart): hash undefs? + } * *p; // persisted across multiple files }; -int CompareSymbolName(const struct Symbol *a, const struct Symbol *b, - const char *tab) { +struct Relas { + size_t i, n; + struct Strings s; + struct Rela { + const char *symbol_name; + const char *object_path; + } * p; +} prtu; + +nullterminated() static void Print(int fd, const char *s, ...) { + va_list va; + char buf[2048]; + va_start(va, s); + buf[0] = 0; + do { + strlcat(buf, s, sizeof(buf)); + } while ((s = va_arg(va, const char *))); + write(fd, buf, strlen(buf)); + va_end(va); +} + +static wontreturn void SysExit(const char *path, const char *func) { + const char *errstr; + if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; + Print(2, path, ": ", func, " failed with ", errstr, "\n", NULL); + exit(1); +} + +static int CompareSymbolName(const struct Symbol *a, const struct Symbol *b, + const char *tab) { return strcmp(tab + a->name, tab + b->name); } -struct Package *LoadPackage(const char *path) { +static void PrintSymbols(struct Package *pkg, struct Symbols *syms, + const char *name) { + int i; + kprintf(" - %s=%d\n", name, syms->i); + for (i = 0; i < syms->i; ++i) { + kprintf(" - id=%d\n", i); + kprintf(" name=%d [%s]\n", syms->p[i].name, + pkg->strings.p + syms->p[i].name); + kprintf(" kind=%d\n", syms->p[i].kind); + kprintf(" bind=%d\n", syms->p[i].bind_); + kprintf(" type=%d\n", syms->p[i].type); + kprintf(" object=%d [%s]\n", syms->p[i].object, + pkg->strings.p + pkg->objects.p[syms->p[i].object].path); + kprintf(" section=%d [%s]\n", syms->p[i].section, + syms->p[i].section == SHN_ABS + ? "SHN_ABS" + : pkg->strings.p + pkg->sections.p[syms->p[i].section].name); + } +} + +static void PrintObject(struct Package *pkg, struct Object *obj) { + int i, o; + kprintf(" path=%d [%s]\n", obj->path, pkg->strings.p + obj->path); + kprintf(" sections=%d\n", obj->section_count); + for (i = 0; i < obj->section_count; ++i) { + o = obj->section_offset; + kprintf(" - id=%d %p (%d+%d)\n", i, pkg->sections.p, o, i); + kprintf(" name=%d [%s]\n", pkg->sections.p[o + i].name, + pkg->strings.p + pkg->sections.p[o + i].name); + kprintf(" kind=%d\n", pkg->sections.p[o + i].kind); + } +} + +static void PrintPackage(struct Package *pkg) { + int i, j, o; + kprintf("- %s\n", pkg->strings.p + pkg->path); + kprintf(" objects=%d\n", pkg->objects.i); + for (i = 0; i < pkg->objects.i; ++i) { + kprintf(" - id=%d\n", i); + PrintObject(pkg, pkg->objects.p + i); + } + PrintSymbols(pkg, &pkg->symbols, "symbols"); + PrintSymbols(pkg, &pkg->undefs, "undefs"); +} + +static void PrintPackages(struct Package *p, int n) { + int i; + for (i = 0; i < n; ++i) { + PrintPackage(p + i); + } +} + +static struct Package *LoadPackage(const char *path) { int fd; - ssize_t i; - struct stat st; + ssize_t i, size; struct Package *pkg; - CHECK(fileexists(path), "%s: %s: %s\n", "error", path, "not found"); - CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path); - CHECK_NE(-1, fstat(fd, &st)); - CHECK_NE(MAP_FAILED, - (pkg = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, - fd, 0)), - "path=%s", path); - CHECK_NE(-1, close(fd)); - CHECK_EQ(PACKAGE_MAGIC, pkg->magic, "corrupt package: %`'s", path); - pkg->strings.p = (char *)((intptr_t)pkg->strings.p + (intptr_t)pkg); - pkg->objects.p = (struct Object *)((intptr_t)pkg->objects.p + (intptr_t)pkg); - pkg->symbols.p = (struct Symbol *)((intptr_t)pkg->symbols.p + (intptr_t)pkg); + if ((fd = open(path, O_RDONLY)) == -1) { + SysExit(path, "open"); + } + if ((size = lseek(fd, 0, SEEK_END)) == -1) { + SysExit(path, "lseek"); + } + if ((pkg = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) == + MAP_FAILED) { + SysExit(path, "mmap"); + } + close(fd); + if (pkg->magic != PACKAGE_MAGIC) { + Print(2, path, ": not a cosmo .pkg file\n", NULL); + exit(1); + } + if (pkg->abi < PACKAGE_ABI) { + Print(2, path, ": package has old abi try running make clean\n", NULL); + exit(1); + } + pkg->strings.p = (void *)((uintptr_t)pkg->strings.p + (uintptr_t)pkg); + pkg->objects.p = (void *)((uintptr_t)pkg->objects.p + (uintptr_t)pkg); + pkg->symbols.p = (void *)((uintptr_t)pkg->symbols.p + (uintptr_t)pkg); + pkg->sections.p = (void *)((uintptr_t)pkg->sections.p + (uintptr_t)pkg); pkg->addr = pkg; - pkg->size = st.st_size; - CHECK_NE(-1, mprotect(pkg, st.st_size, PROT_READ)); + pkg->size = size; + if (mprotect(pkg, size, PROT_READ)) { + SysExit(path, "mprotect"); + } return pkg; } -void AddDependency(struct Packages *deps, const char *path) { +static void AddDependency(struct Packages *deps, const char *path) { struct Package *pkg; pkg = LoadPackage(path); - CHECK_NE(-1, append(deps, &pkg)); + append(deps, &pkg); } -void WritePackage(struct Package *pkg) { - CHECK_NE(0, PACKAGE_MAGIC); +static void WritePackage(struct Package *pkg) { + int fd; + size_t n; + int64_t o; + const char *path; pkg->magic = PACKAGE_MAGIC; pkg->abi = PACKAGE_ABI; - DEBUGF("%s has %,ld objects, %,ld symbols, and a %,ld byte string table", - &pkg->strings.p[pkg->path], pkg->objects.i, pkg->symbols.i, - pkg->strings.i); - PersistObject( - &pkg->strings.p[pkg->path], 64, - &(struct ObjectParam){ - sizeof(struct Package), - pkg, - &pkg->magic, - &pkg->abi, - (struct ObjectArrayParam[]){ - {pkg->strings.i, sizeof(pkg->strings.p[0]), &pkg->strings.p}, - {pkg->objects.i, sizeof(pkg->objects.p[0]), &pkg->objects.p}, - {pkg->symbols.i, sizeof(pkg->symbols.p[0]), &pkg->symbols.p}, - {0}, - }, - }); + path = pkg->strings.p + pkg->path; + if ((fd = creat(path, 0644)) == -1) { + SysExit(path, "creat"); + } + o = sizeof(*pkg); + // write objects + n = pkg->objects.i * sizeof(*pkg->objects.p); + if (pwrite(fd, pkg->objects.p, n, o) != n) { + SysExit(path, "pwrite"); + } + pkg->objects.p = (void *)o; + o += n; + // write symbols + n = pkg->symbols.i * sizeof(*pkg->symbols.p); + if (pwrite(fd, pkg->symbols.p, n, o) != n) { + SysExit(path, "pwrite"); + } + pkg->symbols.p = (void *)o; + o += n; + // write sections + n = pkg->sections.i * sizeof(*pkg->sections.p); + if (pwrite(fd, pkg->sections.p, n, o) != n) { + SysExit(path, "pwrite"); + } + pkg->sections.p = (void *)o; + o += n; + // write strings + n = pkg->strings.i * sizeof(*pkg->strings.p); + pwrite(fd, pkg->strings.p, n, o); + pkg->strings.p = (void *)o; + // write header + if (pwrite(fd, pkg, sizeof(*pkg), 0) != sizeof(*pkg)) { + SysExit(path, "pwrite"); + } + // we're done + if (close(fd) == -1) { + SysExit(path, "close"); + } } -void GetOpts(struct Package *pkg, struct Packages *deps, int argc, - char *argv[]) { +static wontreturn void PrintUsage(int fd, int exitcode) { + Print(fd, "\ +NAME\n\ +\n\ + Cosmopolitan Monorepo Packager\n\ +\n\ +SYNOPSIS\n\ +\n\ + ", + program_invocation_name, " [FLAGS] OBJECT...\n\ +\n\ +DESCRIPTION\n\ +\n\ + This program verifies the well-formedness of symbolic references\n\ + and package dependencies in the cosmopolitan monolithic repository.\n\ + Validation happens incrementally and is granular to static libraries.\n\ + Each .a file should have its own .pkg file too, created by this tool.\n\ +\n\ +FLAGS\n\ +\n\ + -h show this help\n\ + -o PATH package output path\n\ + -d PATH package dependency path [repeatable]\n\ +\n\ +", + NULL); + exit(exitcode); +} + +static void GetOpts(struct Package *pkg, struct Packages *deps, int argc, + char *argv[]) { long i, si, opt; const char *arg; struct GetArgs ga; pkg->path = -1; - while ((opt = getopt(argc, argv, "vho:d:")) != -1) { + while ((opt = getopt(argc, argv, "ho:d:")) != -1) { switch (opt) { - case 'v': - __log_level = kLogDebug; - break; case 'o': pkg->path = concat(&pkg->strings, optarg, strlen(optarg) + 1); break; @@ -196,72 +359,74 @@ void GetOpts(struct Package *pkg, struct Packages *deps, int argc, AddDependency(deps, optarg); break; case 'h': - exit(0); + PrintUsage(1, 0); default: - fprintf(stderr, "%s: %s [%s %s] [%s %s] %s\n", "Usage", - program_invocation_name, "-o", "OUTPACKAGE", "-d", "DEPPACKAGE", - "OBJECT..."); - exit(1); + PrintUsage(2, 1); } } - CHECK_NE(-1, pkg->path, "no packages passed to package.com"); - CHECK_LT(optind, argc, - "no objects passed to package.com; " - "is your foo.mk $(FOO_OBJS) glob broken?"); + if (pkg->path == -1) { + Print(2, "error: no packages passed to package.com\n", NULL); + exit(1); + } + if (optind == argc) { + Print(2, + "no objects passed to package.com; is your foo.mk $(FOO_OBJS) glob " + "broken?\n", + NULL); + exit(1); + } getargs_init(&ga, argv + optind); while ((arg = getargs_next(&ga))) { - CHECK_NE(-1, (si = concat(&pkg->strings, arg, strlen(arg) + 1))); - CHECK_NE(-1, append(&pkg->objects, (&(struct Object){si}))); + struct Object obj = {0}; + obj.path = concat(&pkg->strings, arg, strlen(arg) + 1); + append(&pkg->objects, &obj); } getargs_destroy(&ga); } -void IndexSections(struct Object *obj) { - size_t i; +static void IndexSections(struct Package *pkg, struct Object *obj) { + int i; const char *name; const uint8_t *code; struct Section sect; const Elf64_Shdr *shdr; struct XedDecodedInst xedd; + obj->section_offset = pkg->sections.i; for (i = 0; i < obj->elf->e_shnum; ++i) { bzero(§, sizeof(sect)); - CHECK_NOTNULL((shdr = GetElfSectionHeaderAddress(obj->elf, obj->size, i))); - if (shdr->sh_type != SHT_NULL) { - CHECK_NOTNULL((name = GetElfSectionName(obj->elf, obj->size, shdr))); - if (_startswith(name, ".sort.")) name += 5; - if ((strcmp(name, ".piro.relo") == 0 || - _startswith(name, ".piro.relo.")) || - (strcmp(name, ".data.rel.ro") == 0 || - _startswith(name, ".data.rel.ro."))) { - sect.kind = kPiroRelo; - } else if (strcmp(name, ".piro.data") == 0 || - _startswith(name, ".piro.data.")) { - sect.kind = kPiroData; - } else if (strcmp(name, ".piro.bss") == 0 || - _startswith(name, ".piro.bss.")) { - sect.kind = kPiroBss; - } else if (strcmp(name, ".data") == 0 || _startswith(name, ".data.")) { - sect.kind = kData; - } else if (strcmp(name, ".bss") == 0 || _startswith(name, ".bss.")) { - sect.kind = kBss; - } else { + shdr = GetElfSectionHeaderAddress(obj->elf, obj->size, i); + name = GetElfSectionName(obj->elf, obj->size, shdr); + if (shdr->sh_type == SHT_NULL) { + sect.kind = kUndef; + } else if (shdr->sh_type == SHT_NOBITS) { + sect.kind = kBss; + } else if (shdr->sh_type == SHT_PROGBITS && + !(shdr->sh_flags & SHF_EXECINSTR)) { + sect.kind = kData; + } else if (shdr->sh_type == SHT_PROGBITS && + (shdr->sh_flags & SHF_EXECINSTR)) { + if (strcmp(name, ".privileged")) { sect.kind = kText; + } else { + sect.kind = kPrivilegedText; } } else { - sect.kind = kUndef; /* should always and only be section #0 */ + sect.kind = kOther; } - CHECK_NE(-1, append(&obj->sections, §)); + sect.name = concat(&pkg->strings, name, strlen(name) + 1); + append(&pkg->sections, §); + ++obj->section_count; } } -enum SectionKind ClassifySection(struct Object *obj, uint8_t type, - Elf64_Section shndx) { +static enum SectionKind ClassifySection(struct Package *pkg, struct Object *obj, + uint8_t type, Elf64_Section shndx) { + if (shndx == SHN_ABS) return kOther; if (type == STT_COMMON) return kBss; - if (!obj->sections.i) return kText; - return obj->sections.p[min(max(0, shndx), obj->sections.i - 1)].kind; + return pkg->sections.p[obj->section_offset + shndx].kind; } -void LoadSymbols(struct Package *pkg, uint32_t object) { +static void LoadSymbols(struct Package *pkg, uint32_t object) { Elf64_Xword i; const char *name; struct Object *obj; @@ -269,57 +434,104 @@ void LoadSymbols(struct Package *pkg, uint32_t object) { obj = &pkg->objects.p[object]; symbol.object = object; for (i = 0; i < obj->symcount; ++i) { + symbol.section = obj->section_offset + obj->syms[i].st_shndx; symbol.bind_ = ELF64_ST_BIND(obj->syms[i].st_info); symbol.type = ELF64_ST_TYPE(obj->syms[i].st_info); if (symbol.bind_ != STB_LOCAL && (symbol.type == STT_OBJECT || symbol.type == STT_FUNC || symbol.type == STT_COMMON || symbol.type == STT_NOTYPE)) { name = GetElfString(obj->elf, obj->size, obj->strs, obj->syms[i].st_name); - DEBUGF("%s", name); - if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") != 0) { - symbol.kind = ClassifySection(obj, symbol.type, obj->syms[i].st_shndx); - CHECK_NE(-1, - (symbol.name = concat(&pkg->strings, name, strlen(name) + 1))); - CHECK_NE(-1, - append(symbol.kind != kUndef ? &pkg->symbols : &pkg->undefs, - &symbol)); + if (strcmp(name, "_GLOBAL_OFFSET_TABLE_")) { + symbol.kind = + ClassifySection(pkg, obj, symbol.type, obj->syms[i].st_shndx); + symbol.name = concat(&pkg->strings, name, strlen(name) + 1); + append(symbol.kind != kUndef ? &pkg->symbols : &pkg->undefs, &symbol); } } } } -void OpenObject(struct Package *pkg, struct Object *obj, int mode, int prot, - int flags) { +static Elf64_Shdr *FindElfSectionByName(Elf64_Ehdr *elf, size_t esize, + const char *name) { + long i; + Elf64_Shdr *shdr; + for (i = 0; i < elf->e_shnum; ++i) { + shdr = GetElfSectionHeaderAddress(elf, esize, i); + if (!strcmp(GetElfSectionName(elf, esize, shdr), name)) { + return shdr; + } + } + return 0; +} + +static void LoadPriviligedRefsToUndefs(struct Package *pkg, + struct Object *obj) { + long x; + struct Rela r; + const char *s; + Elf64_Shdr *shdr; + Elf64_Rela *rela, *erela; + if ((shdr = FindElfSectionByName(obj->elf, obj->size, ".rela.privileged"))) { + rela = GetElfSectionAddress(obj->elf, obj->size, shdr); + erela = rela + shdr->sh_size / sizeof(*rela); + for (; rela < erela; ++rela) { + if (!ELF64_R_TYPE(rela->r_info)) continue; + if (!(x = ELF64_R_SYM(rela->r_info))) continue; + if (obj->syms[x].st_shndx) continue; // symbol is defined + if (ELF64_ST_BIND(obj->syms[x].st_info) != STB_WEAK && + ELF64_ST_BIND(obj->syms[x].st_info) != STB_GLOBAL) { + Print(2, "warning: undefined symbol not global\n", NULL); + continue; + } + r.symbol_name = strdup( + GetElfString(obj->elf, obj->size, obj->strs, obj->syms[x].st_name)); + r.object_path = strdup(pkg->strings.p + obj->path); + append(&prtu, &r); + } + } +} + +static void OpenObject(struct Package *pkg, struct Object *obj, int oid) { int fd; - struct stat st; - CHECK_NE(-1, (fd = open(&pkg->strings.p[obj->path], (obj->mode = mode))), - "path=%`'s", &pkg->strings.p[obj->path]); - CHECK_NE(-1, fstat(fd, &st)); - CHECK_NE( - MAP_FAILED, - (obj->elf = mmap(NULL, (obj->size = st.st_size), prot, flags, fd, 0)), - "path=%`'s", &pkg->strings.p[obj->path]); - CHECK_NE(-1, close(fd)); - CHECK(IsElf64Binary(obj->elf, obj->size), "path=%`'s", - &pkg->strings.p[obj->path]); - CHECK_NOTNULL((obj->strs = GetElfStringTable(obj->elf, obj->size)), "on %s", - &pkg->strings.p[obj->path]); - CHECK_NOTNULL( - (obj->syms = GetElfSymbolTable(obj->elf, obj->size, &obj->symcount))); - CHECK_NE(0, obj->symcount); - IndexSections(obj); + const char *path; + path = pkg->strings.p + obj->path; + if ((fd = open(path, O_RDONLY)) == -1) { + SysExit(path, "open"); + } + if ((obj->size = lseek(fd, 0, SEEK_END)) == -1) { + SysExit(path, "lseek"); + } + if ((obj->elf = mmap(0, obj->size, PROT_READ, MAP_SHARED, fd, 0)) == + MAP_FAILED) { + SysExit(path, "mmap"); + } + close(fd); + if (!IsElf64Binary(obj->elf, obj->size)) { + Print(2, path, ": not an elf64 binary\n", NULL); + exit(1); + } + if (!(obj->strs = GetElfStringTable(obj->elf, obj->size))) { + Print(2, path, ": missing elf string table\n", NULL); + exit(1); + } + if (!(obj->syms = GetElfSymbolTable(obj->elf, obj->size, &obj->symcount))) { + Print(2, path, ": missing elf symbol table\n", NULL); + exit(1); + } + IndexSections(pkg, obj); + LoadPriviligedRefsToUndefs(pkg, obj); } -void CloseObject(struct Object *obj) { - CHECK_NE(-1, munmap(obj->elf, obj->size)); +static void CloseObject(struct Object *obj) { + if (munmap(obj->elf, obj->size)) notpossible; } -void LoadObjects(struct Package *pkg) { +static void LoadObjects(struct Package *pkg) { size_t i; struct Object *obj; for (i = 0; i < pkg->objects.i; ++i) { obj = pkg->objects.p + i; - OpenObject(pkg, obj, O_RDONLY, PROT_READ, MAP_SHARED); + OpenObject(pkg, obj, i); LoadSymbols(pkg, i); CloseObject(obj); } @@ -327,7 +539,7 @@ void LoadObjects(struct Package *pkg) { (void *)CompareSymbolName, pkg->strings.p); } -struct Symbol *BisectSymbol(struct Package *pkg, const char *name) { +static struct Symbol *BisectSymbol(struct Package *pkg, const char *name) { int c; long m, l, r; l = 0; @@ -346,9 +558,9 @@ struct Symbol *BisectSymbol(struct Package *pkg, const char *name) { return NULL; } -bool FindSymbol(const char *name, struct Package *pkg, - struct Packages *directdeps, struct Package **out_pkg, - struct Symbol **out_sym) { +static bool FindSymbol(const char *name, struct Package *pkg, + struct Packages *directdeps, struct Package **out_pkg, + struct Symbol **out_sym) { size_t i, j; struct Symbol *sym; if ((sym = BisectSymbol(pkg, name))) { @@ -366,7 +578,7 @@ bool FindSymbol(const char *name, struct Package *pkg, return false; } -void CheckStrictDeps(struct Package *pkg, struct Packages *deps) { +static void CheckStrictDeps(struct Package *pkg, struct Packages *deps) { size_t i, j; struct Package *dep; struct Symbol *undef; @@ -374,15 +586,13 @@ void CheckStrictDeps(struct Package *pkg, struct Packages *deps) { undef = &pkg->undefs.p[i]; if (undef->bind_ == STB_WEAK) continue; if (!FindSymbol(pkg->strings.p + undef->name, pkg, deps, NULL, NULL)) { - fprintf(stderr, "%s: %`'s (%s) %s %s\n", "error", - pkg->strings.p + undef->name, - pkg->strings.p + pkg->objects.p[undef->object].path, - "not defined by direct deps of", pkg->strings.p + pkg->path); + Print(2, pkg->strings.p + pkg->path, ": undefined symbol '", + pkg->strings.p + undef->name, "' (", + pkg->strings.p + pkg->objects.p[undef->object].path, + ") not defined by direct dependencies:\n", NULL); for (j = 0; j < deps->i; ++j) { dep = deps->p[j]; - fputc('\t', stderr); - fputs(dep->strings.p + dep->path, stderr); - fputc('\n', stderr); + Print(2, "\t", dep->strings.p + dep->path, "\n", NULL); } exit(1); } @@ -391,43 +601,53 @@ void CheckStrictDeps(struct Package *pkg, struct Packages *deps) { bzero(&pkg->undefs, sizeof(pkg->undefs)); } -forceinline bool IsRipRelativeModrm(uint8_t modrm) { - return (modrm & 0b11000111) == 0b00000101; +static void CheckYourPrivilege(struct Package *pkg, struct Packages *deps) { + int i, j, o, f; + const char *name; + struct Symbol *sym; + struct Package *dep; + for (f = i = 0; i < prtu.i; ++i) { + name = prtu.p[i].symbol_name; + if (FindSymbol(name, pkg, deps, &dep, &sym) && + dep->sections.p[sym->section].kind == kText) { + Print(2, prtu.p[i].object_path, + ": privileged code referenced unprivileged symbol '", name, + "' in section '", + dep->strings.p + dep->sections.p[sym->section].name, "'\n", NULL); + ++f; + } + } + if (f) exit(1); } -forceinline uint8_t ChangeRipToRbx(uint8_t modrm) { - return (modrm & 0b00111000) | 0b10000011; +static bool IsSymbolDirectlyReachable(struct Package *pkg, + struct Packages *deps, + const char *symbol) { + return FindSymbol(symbol, pkg, deps, 0, 0); } -bool IsSymbolDirectlyReachable(struct Package *pkg, struct Packages *deps, - const char *symbol) { - return FindSymbol(symbol, pkg, deps, NULL, NULL); -} - -void Package(int argc, char *argv[], struct Package *pkg, - struct Packages *deps) { +static void Package(int argc, char *argv[], struct Package *pkg, + struct Packages *deps) { size_t i, j; GetOpts(pkg, deps, argc, argv); LoadObjects(pkg); CheckStrictDeps(pkg, deps); + CheckYourPrivilege(pkg, deps); WritePackage(pkg); for (i = 0; i < deps->i; ++i) { - CHECK_NE(-1, munmap(deps->p[i]->addr, deps->p[i]->size)); + if (munmap(deps->p[i]->addr, deps->p[i]->size)) notpossible; } - for (i = 0; i < pkg->objects.i; ++i) { - free(pkg->objects.p[i].sections.p); - } - free(pkg->strings.p); - free(pkg->objects.p); - free(pkg->symbols.p); - free(deps->p); } int main(int argc, char *argv[]) { struct Package pkg; struct Packages deps; - if (argc == 2 && !strcmp(argv[1], "-n")) exit(0); - if (IsModeDbg()) ShowCrashReports(); + if (argc == 2 && !strcmp(argv[1], "-n")) { + exit(0); + } + if (!IsOptimized()) { + ShowCrashReports(); + } bzero(&pkg, sizeof(pkg)); bzero(&deps, sizeof(deps)); Package(argc, argv, &pkg, &deps); diff --git a/tool/build/strace.c b/tool/build/strace.c index c42f3827d..d66b0171a 100644 --- a/tool/build/strace.c +++ b/tool/build/strace.c @@ -1052,7 +1052,9 @@ wontreturn void StraceMain(int argc, char *argv[]) { exit(1); } - if (IsModeDbg()) ShowCrashReports(); + if (!IsOptimized()) { + ShowCrashReports(); + } if (argc < 2) { kprintf("Usage: %s PROGRAM [ARGS...]%n", argv[0]); diff --git a/tool/build/unbuffer.c b/tool/build/unbuffer.c index 42492df13..1d8224ac1 100644 --- a/tool/build/unbuffer.c +++ b/tool/build/unbuffer.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/calls/ioctl.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/termios.h" #include "libc/calls/struct/winsize.h" diff --git a/tool/emacs/cosmo-stuff.el b/tool/emacs/cosmo-stuff.el index 3c40f17c4..3788641e6 100644 --- a/tool/emacs/cosmo-stuff.el +++ b/tool/emacs/cosmo-stuff.el @@ -25,6 +25,7 @@ (require 'ld-script) (require 'make-mode) +(setq cosmo-dbg-mode "zero") (setq c-doc-comment-style 'javadown) (add-to-list 'auto-mode-alist '("\\.x$" . c-mode)) ;; -aux-info @@ -162,13 +163,13 @@ (cond ((eq arg 1) "tiny") ((eq arg 2) "opt") ((eq arg 3) "rel") - ((eq arg 4) "dbg") + ((eq arg 4) cosmo-dbg-mode) ((eq arg 5) "") ((eq arg 6) "llvm") ((eq arg 7) "aarch64") ((eq arg 8) "aarch64-tiny") (default default) - ((cosmo-intest) "dbg") + ((cosmo-intest) cosmo-dbg-mode) (t "fastbuild"))) (defun cosmo--make-suffix (arg) @@ -684,7 +685,7 @@ (let* ((this (or (buffer-file-name) dired-directory)) (root (locate-dominating-file this "Makefile"))) (when root - (let* ((mode (cosmo--make-mode arg "dbg")) + (let* ((mode (cosmo--make-mode arg cosmo-dbg-mode)) (name (file-relative-name this root)) (next (file-name-sans-extension name)) (exec (format "o/%s/%s.com.dbg" mode next)) diff --git a/tool/net/net.mk b/tool/net/net.mk index f74f3583a..43fc32fd6 100644 --- a/tool/net/net.mk +++ b/tool/net/net.mk @@ -249,6 +249,7 @@ o/$(MODE)/tool/net/redbean-demo.com: \ o/$(MODE)/tool/net/redbean-static.com.dbg: \ $(TOOL_NET_DEPS) \ + $(TOOL_NET_REDBEAN_LUA_MODULES) \ o/$(MODE)/tool/net/redbean-static.o \ o/$(MODE)/tool/net/net.pkg \ $(CRT) \ @@ -300,6 +301,7 @@ o/$(MODE)/tool/net/redbean-unsecure.com: \ o/$(MODE)/tool/net/redbean-original.com.dbg: \ $(TOOL_NET_DEPS) \ + $(TOOL_NET_REDBEAN_LUA_MODULES) \ o/$(MODE)/tool/net/redbean-original.o \ o/$(MODE)/tool/net/net.pkg \ $(CRT) \