Merge remote-tracking branch 'origin' into lua-tls-api

This commit is contained in:
s0ph0s 2024-02-07 20:11:19 -05:00
commit d372a5820e
6292 changed files with 499430 additions and 169454 deletions

3
.gitignore vendored
View file

@ -1,7 +1,8 @@
# -*- conf -*- # -*- conf -*-
/o /o
/.prompt.jtlp /cosmocc
/.cosmocc
# TODO: Find some way to have Python write to o/ # TODO: Find some way to have Python write to o/
__pycache__ __pycache__

View file

@ -2,23 +2,41 @@
We'd love to accept your patches! Please read this guide first. We'd love to accept your patches! Please read this guide first.
## Identity Disclosure
This project does not accept anonymous contributions. Justine Tunney
won't merge pull requests from strangers. In order to change the Cosmo
codebase, and have your changes be upstreamed, she has to know who you
are. You're encouraged to disclose your full name and email address to
the public too, by including them in your git commit messages; however
that's not a requirement; as we're happy to respect the wishes of
contributors who prefer to remain anonymous to the public.
## Copyright Assignment ## Copyright Assignment
Please send an email to Justine Tunney <jtunney@gmail.com> stating that The first time you send a pull request, you need to send an email to
you intend to assign her the copyright to the changes you contribute to Justine Tunney <jtunney@gmail.com> stating that you intend to assign her
Cosmopolitan. Please use the same email address you use for git commits the copyright to the changes you contribute to Cosmopolitan. This only
which should only contain original source code from you or other people applies to the code you *choose* to contribute. It only has to happen
who are also assigning copyright. Please note that, if you're employed, once. The email should be sent from an email address associated with
you may need to get your employer's approval beforehand. If you can not your identity. Your email should link to your pull request.
assign copyright due to local laws, then you may alternatively consider
disclaiming it using the language in [Unlicense](https://unlicense.org)
or [CC-0](http://creativecommons.org/share-your-work/public-domain/cc0)
This is important because we can't produce 12kb single-file executables Please note that in order to give Justine the copyright, it has to be
that comply with license requirements if we have to embed lots of them. yours to give in the first place. If you're employed, then you should
Although that's less of an issue depending on the purpose of the files. get your employer's approval to do this beforehand. Even with big
For example, ownership is much less of a concern in the unit test files companies like Google, this process is quick and painless. Usually we
so you're encouraged to put your copyright on those, provided it's ISC. see employers granting authorization in less than one day.
If you live in a country that doesn't recognize one's ability to assign
copyright, then you may alternatively consider disclaiming it using the
language in [Unlicense](https://unlicense.org) or
[CC-0](http://creativecommons.org/share-your-work/public-domain/cc0).
If you're checking-in third party code, then you need to have headers at
the top of each source file (but never header files) documenting its
owners and the code should go in the `third_party/` folder. Every third
party project should have a `README.cosmo` file that documents its
provenance as well as any local changes you've made.
## Style Guide ## Style Guide

125
Makefile
View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #
@ -73,10 +73,13 @@ MODE := $(m)
endif endif
endif endif
COMMA := ,
PWD := $(shell pwd)
# detect wsl2 running cosmopolitan binaries on the host by checking whether: # detect wsl2 running cosmopolitan binaries on the host by checking whether:
# - user ran build/bootstrap/make.com, in which case make's working directory is in wsl # - user ran build/bootstrap/make.com, in which case make's working directory is in wsl
# - user ran make, in which case cocmd.com's working directory is in wsl # - user ran make, in which case cocmd.com's working directory is in wsl
ifneq ($(findstring //wsl.localhost/,$(CURDIR) $(shell pwd)),) ifneq ($(findstring //wsl.localhost/,$(CURDIR) $(PWD)),)
$(warning wsl2 interop is enabled) $(warning wsl2 interop is enabled)
$(error you need to run sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop') $(error you need to run sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop')
endif endif
@ -89,14 +92,33 @@ ifeq ($(MAKE_VERSION), 3.81)
$(error please use build/bootstrap/make.com) $(error please use build/bootstrap/make.com)
endif endif
# provide instructions to non-linux users on unbundling gcc LC_ALL = C
ifeq ($(TOOLCHAIN),) # if TOOLCHAIN isn't defined SOURCE_DATE_EPOCH = 0
ifeq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","") # if our gcc isn't unbundled
ifneq ($(UNAME_M)-$(UNAME_S), x86_64-Linux) # if this is not amd64 linux ARFLAGS = rcsD
$(error please run tool/cosmocc/fetch.sh) ZFLAGS ?=
endif XARGS ?= xargs -P4 -rs8000
endif DOT ?= dot
endif CLANG = clang
TMPDIR = o/tmp
AR = build/bootstrap/ar.com
CP = build/bootstrap/cp.com
RM = build/bootstrap/rm.com -f
GZIP = build/bootstrap/gzip.com
ECHO = build/bootstrap/echo.com
CHMOD = build/bootstrap/chmod.com
TOUCH = build/bootstrap/touch.com
PKG = build/bootstrap/package.com
MKDEPS = build/bootstrap/mkdeps.com
ZIPOBJ = build/bootstrap/zipobj.com
ZIPCOPY = build/bootstrap/zipcopy.com
PECHECK = build/bootstrap/pecheck.com
FIXUPOBJ = build/bootstrap/fixupobj.com
MKDIR = build/bootstrap/mkdir.com -p
COMPILE = build/bootstrap/compile.com -V9 -M2048m -P8192 $(QUOTA)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
# the default build modes is empty string # the default build modes is empty string
# on x86_64 hosts, MODE= is the same as MODE=x86_64 # on x86_64 hosts, MODE= is the same as MODE=x86_64
@ -110,6 +132,44 @@ MODE := aarch64
endif endif
endif endif
ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
HOSTS ?= pi studio freebsdarm
else
ARCH = x86_64
HOSTS ?= freebsd rhel7 xnu win10 openbsd netbsd
endif
ZIPOBJ_FLAGS += -a$(ARCH)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
export ADDR2LINE
export LC_ALL
export MKDIR
export MODE
export SOURCE_DATE_EPOCH
export TMPDIR
COSMOCC = .cosmocc/3.2
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.2 28b48682595f0f46b45ab381118cdffdabc8fcfa29aa54e301fe6ffe35269f5e)
AS = $(TOOLCHAIN)as
CC = $(TOOLCHAIN)gcc
CXX = $(TOOLCHAIN)g++
CXXFILT = $(TOOLCHAIN)c++filt
LD = $(TOOLCHAIN)ld.bfd
NM = $(TOOLCHAIN)nm
GCC = $(TOOLCHAIN)gcc
STRIP = $(TOOLCHAIN)strip
OBJCOPY = $(TOOLCHAIN)objcopy
OBJDUMP = $(TOOLCHAIN)objdump
ifneq ($(wildcard $(PWD)/$(TOOLCHAIN)addr2line),)
ADDR2LINE = $(PWD)/$(TOOLCHAIN)addr2line
else
ADDR2LINE = $(TOOLCHAIN)addr2line
endif
# primary build rules # primary build rules
all: o all: o
o: o/$(MODE) o: o/$(MODE)
@ -138,7 +198,7 @@ $(warning please run ape/apeinstall.sh if you intend to use landlock make)
$(shell sleep .5) $(shell sleep .5)
endif endif
endif endif
ifeq ($(USE_SYSTEM_TOOLCHAIN),) ifneq ($(TOOLCHAIN),)
.STRICT = 1 .STRICT = 1
endif endif
endif endif
@ -149,8 +209,8 @@ endif
libc/stdbool.h \ libc/stdbool.h \
libc/disclaimer.inc \ libc/disclaimer.inc \
rwc:/dev/shm \ rwc:/dev/shm \
rx:cosmocc \
rx:build/bootstrap \ rx:build/bootstrap \
rx:o/third_party/gcc \
r:build/portcosmo.h \ r:build/portcosmo.h \
/proc/stat \ /proc/stat \
rw:/dev/null \ rw:/dev/null \
@ -189,7 +249,6 @@ include libc/calls/BUILD.mk #─┐
include libc/irq/BUILD.mk # ├──SYSTEMS RUNTIME include libc/irq/BUILD.mk # ├──SYSTEMS RUNTIME
include third_party/nsync/BUILD.mk # │ You can issue system calls include third_party/nsync/BUILD.mk # │ You can issue system calls
include libc/runtime/BUILD.mk # │ include libc/runtime/BUILD.mk # │
include third_party/double-conversion/BUILD.mk # │
include libc/crt/BUILD.mk # │ include libc/crt/BUILD.mk # │
include third_party/dlmalloc/BUILD.mk #─┘ include third_party/dlmalloc/BUILD.mk #─┘
include libc/mem/BUILD.mk #─┐ include libc/mem/BUILD.mk #─┐
@ -198,9 +257,9 @@ include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
include libc/proc/BUILD.mk # │ You can now use threads include libc/proc/BUILD.mk # │ You can now use threads
include libc/dlopen/BUILD.mk # │ You can now use processes include libc/dlopen/BUILD.mk # │ You can now use processes
include libc/thread/BUILD.mk # │ You can finally call malloc() include libc/thread/BUILD.mk # │ You can finally call malloc()
include tool/hello/BUILD.mk # │
include third_party/zlib/BUILD.mk # │ include third_party/zlib/BUILD.mk # │
include libc/stdio/BUILD.mk # │ include libc/stdio/BUILD.mk # │
include tool/hello/BUILD.mk # │
include libc/time/BUILD.mk # │ include libc/time/BUILD.mk # │
include net/BUILD.mk # │ include net/BUILD.mk # │
include third_party/vqsort/BUILD.mk # │ include third_party/vqsort/BUILD.mk # │
@ -213,9 +272,8 @@ include third_party/intel/BUILD.mk # │
include third_party/aarch64/BUILD.mk # │ include third_party/aarch64/BUILD.mk # │
include libc/BUILD.mk #─┘ include libc/BUILD.mk #─┘
include libc/sock/BUILD.mk #─┐ include libc/sock/BUILD.mk #─┐
include libc/dns/BUILD.mk # ├──ONLINE RUNTIME include net/http/BUILD.mk # ├──ONLINE RUNTIME
include net/http/BUILD.mk # │ You can communicate with the network include third_party/musl/BUILD.mk # │ You can communicate with the network
include third_party/musl/BUILD.mk # │
include libc/x/BUILD.mk # │ include libc/x/BUILD.mk # │
include dsp/scale/BUILD.mk # │ include dsp/scale/BUILD.mk # │
include dsp/mpeg/BUILD.mk # │ include dsp/mpeg/BUILD.mk # │
@ -223,11 +281,18 @@ include dsp/tty/BUILD.mk # │
include dsp/BUILD.mk # │ include dsp/BUILD.mk # │
include third_party/stb/BUILD.mk # │ include third_party/stb/BUILD.mk # │
include third_party/mbedtls/BUILD.mk # │ include third_party/mbedtls/BUILD.mk # │
include third_party/ncurses/BUILD.mk # │
include third_party/readline/BUILD.mk # │
include third_party/libunwind/BUILD.mk # |
include third_party/libcxxabi/BUILD.mk # |
include third_party/libcxx/BUILD.mk # │ include third_party/libcxx/BUILD.mk # │
include third_party/ggml/BUILD.mk # │ include third_party/openmp/BUILD.mk # │
include third_party/radpajama/BUILD.mk # │ include third_party/double-conversion/BUILD.mk # │
include third_party/pcre/BUILD.mk # │
include third_party/less/BUILD.mk # │
include net/https/BUILD.mk # │ include net/https/BUILD.mk # │
include third_party/regex/BUILD.mk #─┘ include third_party/regex/BUILD.mk # │
include third_party/bash/BUILD.mk #─┘
include third_party/tidy/BUILD.mk include third_party/tidy/BUILD.mk
include third_party/BUILD.mk include third_party/BUILD.mk
include third_party/nsync/testing/BUILD.mk include third_party/nsync/testing/BUILD.mk
@ -235,6 +300,7 @@ include libc/testlib/BUILD.mk
include tool/viz/lib/BUILD.mk include tool/viz/lib/BUILD.mk
include tool/args/BUILD.mk include tool/args/BUILD.mk
include test/posix/BUILD.mk include test/posix/BUILD.mk
include test/libcxx/BUILD.mk
include test/tool/args/BUILD.mk include test/tool/args/BUILD.mk
include third_party/linenoise/BUILD.mk include third_party/linenoise/BUILD.mk
include third_party/maxmind/BUILD.mk include third_party/maxmind/BUILD.mk
@ -254,7 +320,6 @@ include third_party/argon2/BUILD.mk
include third_party/smallz4/BUILD.mk include third_party/smallz4/BUILD.mk
include third_party/sqlite3/BUILD.mk include third_party/sqlite3/BUILD.mk
include third_party/mbedtls/test/BUILD.mk include third_party/mbedtls/test/BUILD.mk
include third_party/quickjs/BUILD.mk
include third_party/lz4cli/BUILD.mk include third_party/lz4cli/BUILD.mk
include third_party/zip/BUILD.mk include third_party/zip/BUILD.mk
include third_party/xxhash/BUILD.mk include third_party/xxhash/BUILD.mk
@ -266,6 +331,7 @@ include third_party/python/BUILD.mk
include tool/build/BUILD.mk include tool/build/BUILD.mk
include tool/curl/BUILD.mk include tool/curl/BUILD.mk
include third_party/qemu/BUILD.mk include third_party/qemu/BUILD.mk
include third_party/libcxxabi/test/BUILD.mk
include examples/BUILD.mk include examples/BUILD.mk
include examples/pyapp/BUILD.mk include examples/pyapp/BUILD.mk
include examples/pylife/BUILD.mk include examples/pylife/BUILD.mk
@ -294,7 +360,6 @@ include test/libc/calls/BUILD.mk
include test/libc/x/BUILD.mk include test/libc/x/BUILD.mk
include test/libc/xed/BUILD.mk include test/libc/xed/BUILD.mk
include test/libc/fmt/BUILD.mk include test/libc/fmt/BUILD.mk
include test/libc/dns/BUILD.mk
include test/libc/time/BUILD.mk include test/libc/time/BUILD.mk
include test/libc/proc/BUILD.mk include test/libc/proc/BUILD.mk
include test/libc/stdio/BUILD.mk include test/libc/stdio/BUILD.mk
@ -370,7 +435,6 @@ loc: o/$(MODE)/tool/build/summy.com
COSMOPOLITAN_OBJECTS = \ COSMOPOLITAN_OBJECTS = \
TOOL_ARGS \ TOOL_ARGS \
NET_HTTP \ NET_HTTP \
LIBC_DNS \
LIBC_SOCK \ LIBC_SOCK \
LIBC_NT_WS2_32 \ LIBC_NT_WS2_32 \
LIBC_NT_IPHLPAPI \ LIBC_NT_IPHLPAPI \
@ -378,8 +442,11 @@ COSMOPOLITAN_OBJECTS = \
THIRD_PARTY_GETOPT \ THIRD_PARTY_GETOPT \
LIBC_LOG \ LIBC_LOG \
LIBC_TIME \ LIBC_TIME \
THIRD_PARTY_OPENMP \
THIRD_PARTY_MUSL \ THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB_GZ \ THIRD_PARTY_ZLIB_GZ \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
LIBC_STDIO \ LIBC_STDIO \
THIRD_PARTY_GDTOA \ THIRD_PARTY_GDTOA \
THIRD_PARTY_REGEX \ THIRD_PARTY_REGEX \
@ -421,7 +488,6 @@ COSMOPOLITAN_H_PKGS = \
APE \ APE \
LIBC \ LIBC \
LIBC_CALLS \ LIBC_CALLS \
LIBC_DNS \
LIBC_ELF \ LIBC_ELF \
LIBC_FMT \ LIBC_FMT \
LIBC_DLOPEN \ LIBC_DLOPEN \
@ -450,12 +516,16 @@ COSMOPOLITAN_H_PKGS = \
THIRD_PARTY_GETOPT \ THIRD_PARTY_GETOPT \
THIRD_PARTY_MUSL \ THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB \ THIRD_PARTY_ZLIB \
THIRD_PARTY_ZLIB_GZ \
THIRD_PARTY_REGEX THIRD_PARTY_REGEX
COSMOCC_PKGS = \ COSMOCC_PKGS = \
$(COSMOPOLITAN_H_PKGS) \ $(COSMOPOLITAN_H_PKGS) \
THIRD_PARTY_AARCH64 \ THIRD_PARTY_AARCH64 \
THIRD_PARTY_LIBCXX \ THIRD_PARTY_LIBCXX \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
THIRD_PARTY_OPENMP \
THIRD_PARTY_INTEL THIRD_PARTY_INTEL
o/$(MODE)/cosmopolitan.a: \ o/$(MODE)/cosmopolitan.a: \
@ -480,18 +550,15 @@ o/cosmopolitan.h: o/cosmopolitan.h.txt \
$(wildcard libc/integral/*) \ $(wildcard libc/integral/*) \
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS)) \ $(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS)) \
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_INCS)) $(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_INCS))
@$(ECHO) '#ifndef __STRICT_ANSI__' >$@
@$(ECHO) '#define _COSMO_SOURCE' >>$@
@$(ECHO) '#endif' >>$@
@$(COMPILE) -AROLLUP -T$@ build/bootstrap/rollup.com @$< >>$@ @$(COMPILE) -AROLLUP -T$@ build/bootstrap/rollup.com @$< >>$@
o/cosmopolitan.html: private .UNSANDBOXED = 1 o/cosmopolitan.html: private .UNSANDBOXED = 1
o/cosmopolitan.html: \ o/cosmopolitan.html: \
o/$(MODE)/third_party/chibicc/chibicc.com.dbg \ o/$(MODE)/third_party/chibicc/chibicc.com.dbg \
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \ $(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \
$(SRCS) \ $(filter-out %.cc,$(SRCS)) \
$(HDRS) $(HDRS)
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS)))) $(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.cc,$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS)))))
o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \ o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \
-fno-common -include libc/integral/normalize.inc -o $@ \ -fno-common -include libc/integral/normalize.inc -o $@ \
-DCOSMO @$(TMPDIR)/$(subst /,_,$@) -DCOSMO @$(TMPDIR)/$(subst /,_,$@)

View file

@ -12,10 +12,11 @@ possible performance and the tiniest footprint imaginable.
## Background ## Background
For an introduction to this project, please read the [αcτµαlly pδrταblε For an introduction to this project, please read the [actually portable
εxεcµταblε](https://justine.lol/ape.html) blog post and [cosmopolitan executable](https://justine.lol/ape.html) blog post and [cosmopolitan
libc](https://justine.lol/cosmopolitan/index.html) website. We also have libc](https://justine.lol/cosmopolitan/index.html) website. We also have
[API documentation](https://justine.lol/cosmopolitan/documentation.html). [API
documentation](https://justine.lol/cosmopolitan/documentation.html).
## Getting Started ## Getting Started
@ -75,18 +76,7 @@ make install
## Cosmopolitan Source Builds ## Cosmopolitan Source Builds
Cosmopolitan can be compiled from source on any of our supported Cosmopolitan can be compiled from source on any of our supported
platforms. First, you need to download or clone the repository. If platforms. The Makefile will download cosmocc automatically.
you're not using x86-64 Linux then you'll need cosmocc too.
```sh
git clone https://github.com/jart/cosmopolitan cosmo
cd cosmo
mkdir -p o/third_party/gcc
pushd o/third_party/gcc
wget https://cosmo.zip/pub/cosmocc/cosmocc.zip
unzip cosmocc.zip
popd
```
It's recommended that you install a systemwide APE Loader. This command It's recommended that you install a systemwide APE Loader. This command
requires `sudo` access to copy the `ape` command to a system folder and requires `sudo` access to copy the `ape` command to a system folder and
@ -102,7 +92,7 @@ guaranteed to be compatible and furthermore includes our extensions for
doing build system sandboxing. doing build system sandboxing.
```sh ```sh
o//third_party/gcc/bin/make -j8 build/bootstrap/make.com -j8
o//examples/hello.com o//examples/hello.com
``` ```
@ -113,7 +103,7 @@ depends on core LIBC packages.
```sh ```sh
rm -rf o//libc o//test rm -rf o//libc o//test
o//third_party/gcc/bin/make o//test/posix/signal_test.com build/bootstrap/make.com o//test/posix/signal_test.com
o//test/posix/signal_test.com o//test/posix/signal_test.com
``` ```
@ -122,21 +112,21 @@ list out each individual one. For example if you wanted to build and run
all the unit tests in the `TEST_POSIX` package, you could say: all the unit tests in the `TEST_POSIX` package, you could say:
```sh ```sh
o//third_party/gcc/bin/make o//test/posix build/bootstrap/make.com o//test/posix
``` ```
Cosmopolitan provides a variety of build modes. For example, if you want Cosmopolitan provides a variety of build modes. For example, if you want
really tiny binaries (as small as 12kb in size) then you'd say: really tiny binaries (as small as 12kb in size) then you'd say:
```sh ```sh
o//third_party/gcc/bin/make m=tiny build/bootstrap/make.com m=tiny
``` ```
You can furthermore cut out the bloat of other operating systems, and You can furthermore cut out the bloat of other operating systems, and
have Cosmopolitan become much more similar to Musl Libc. have Cosmopolitan become much more similar to Musl Libc.
```sh ```sh
o//third_party/gcc/bin/make m=tinylinux build/bootstrap/make.com m=tinylinux
``` ```
For further details, see [//build/config.mk](build/config.mk). For further details, see [//build/config.mk](build/config.mk).

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
# #
# OVERVIEW # OVERVIEW
# #
@ -78,7 +78,8 @@ APE_LOADER_FLAGS = \
$< $<
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@ @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
o/$(MODE)/ape/ape.elf.dbg: \ o/$(MODE)/ape/ape.elf.dbg: \
o/$(MODE)/ape/start.o \ o/$(MODE)/ape/start.o \
@ -88,7 +89,7 @@ o/$(MODE)/ape/ape.elf.dbg: \
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^) @$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
o/$(MODE)/ape/loader.o: ape/loader.c ape/ape.h o/$(MODE)/ape/loader.o: ape/loader.c ape/ape.h
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS) @$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=33 -g $(APE_LOADER_FLAGS)
o/$(MODE)/ape/start.o: ape/start.S o/$(MODE)/ape/start.o: ape/start.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/ape/launch.o: ape/launch.S o/$(MODE)/ape/launch.o: ape/launch.S
@ -167,14 +168,11 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
libc/macros.internal.h \ libc/macros.internal.h \
libc/nexgen32e/uart.internal.h \ libc/nexgen32e/uart.internal.h \
libc/calls/metalfile.internal.h \ libc/calls/metalfile.internal.h \
libc/nexgen32e/vidya.internal.h \
libc/nt/pedef.internal.h \ libc/nt/pedef.internal.h \
libc/runtime/e820.internal.h \ libc/runtime/e820.internal.h \
libc/runtime/mman.internal.h \ libc/runtime/mman.internal.h \
libc/runtime/pc.internal.h \ libc/runtime/pc.internal.h \
libc/sysv/consts/prot.h \ libc/sysv/consts/prot.h \
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz \
o/$(MODE)/ape/ape.elf o/$(MODE)/ape/ape.elf
@$(COMPILE) \ @$(COMPILE) \
-AOBJECTIFY.S \ -AOBJECTIFY.S \
@ -198,14 +196,11 @@ o/$(MODE)/ape/ape-copy-self.o: \
libc/macros.internal.h \ libc/macros.internal.h \
libc/nexgen32e/uart.internal.h \ libc/nexgen32e/uart.internal.h \
libc/calls/metalfile.internal.h \ libc/calls/metalfile.internal.h \
libc/nexgen32e/vidya.internal.h \
libc/nt/pedef.internal.h \ libc/nt/pedef.internal.h \
libc/runtime/e820.internal.h \ libc/runtime/e820.internal.h \
libc/runtime/mman.internal.h \ libc/runtime/mman.internal.h \
libc/runtime/pc.internal.h \ libc/runtime/pc.internal.h \
libc/sysv/consts/prot.h \ libc/sysv/consts/prot.h
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz
@$(COMPILE) \ @$(COMPILE) \
-AOBJECTIFY.S \ -AOBJECTIFY.S \
$(OBJECTIFY.S) \ $(OBJECTIFY.S) \
@ -264,10 +259,6 @@ endif
o/$(MODE)/ape/ape.o: ape/ape.S o/$(MODE)/ape/ape.o: ape/ape.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/ape/ape.o: \
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz
o/$(MODE)/ape/ape.lds: \ o/$(MODE)/ape/ape.lds: \
ape/ape.lds \ ape/ape.lds \
ape/macros.internal.h \ ape/macros.internal.h \

View file

@ -1,5 +1,5 @@
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│ /*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
│ vi: set noet sts=2 tw=2 fenc=utf-8 :vi │ │ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
╚─────────────────────────────────────────────────────────────────────────────*/ ╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/thread/tls.h" #include "libc/thread/tls.h"

View file

@ -35,9 +35,7 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#define pagesz 16384 #define pagesz 16384
#define VARNAME "COSMOPOLITAN_PROGRAM_EXECUTABLE="
#define VARSIZE (sizeof(VARNAME) - 1)
/* maximum path size that cosmo can take */ /* maximum path size that cosmo can take */
#define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024) #define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024)
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24) #define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
@ -105,36 +103,39 @@ struct Syslib {
char *(*dlerror)(void); char *(*dlerror)(void);
}; };
#define ELFCLASS32 1 #define ELFCLASS32 1
#define ELFDATA2LSB 1 #define ELFDATA2LSB 1
#define EM_AARCH64 183 #define EM_AARCH64 183
#define ET_EXEC 2 #define ET_EXEC 2
#define ET_DYN 3 #define ET_DYN 3
#define PT_LOAD 1 #define PT_LOAD 1
#define PT_DYNAMIC 2 #define PT_DYNAMIC 2
#define PT_INTERP 3 #define PT_INTERP 3
#define EI_CLASS 4 #define EI_CLASS 4
#define EI_DATA 5 #define EI_DATA 5
#define PF_X 1 #define PF_X 1
#define PF_W 2 #define PF_W 2
#define PF_R 4 #define PF_R 4
#define AT_PHDR 3 #define AT_PHDR 3
#define AT_PHENT 4 #define AT_PHENT 4
#define AT_PHNUM 5 #define AT_PHNUM 5
#define AT_PAGESZ 6 #define AT_PAGESZ 6
#define AT_BASE 7 #define AT_BASE 7
#define AT_ENTRY 9 #define AT_FLAGS 8
#define AT_UID 11 #define AT_FLAGS_PRESERVE_ARGV0_BIT 0
#define AT_EUID 12 #define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
#define AT_GID 13 #define AT_ENTRY 9
#define AT_EGID 14 #define AT_UID 11
#define AT_HWCAP 16 #define AT_EUID 12
#define AT_HWCAP2 16 #define AT_GID 13
#define AT_SECURE 23 #define AT_EGID 14
#define AT_RANDOM 25 #define AT_HWCAP 16
#define AT_EXECFN 31 #define AT_HWCAP2 16
#define AT_SECURE 23
#define AT_RANDOM 25
#define AT_EXECFN 31
#define AUXV_WORDS 29 #define AUXV_WORDS 31
/* from the xnu codebase */ /* from the xnu codebase */
#define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul #define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul
@ -203,11 +204,8 @@ struct PathSearcher {
unsigned long namelen; unsigned long namelen;
const char *name; const char *name;
const char *syspath; const char *syspath;
char varname[VARSIZE];
char path[PATHSIZE]; char path[PATHSIZE];
}; };
_Static_assert(offsetof(struct PathSearcher, varname) + VARSIZE ==
offsetof(struct PathSearcher, path), "struct layout");
struct ApeLoader { struct ApeLoader {
struct PathSearcher ps; struct PathSearcher ps;
@ -321,28 +319,13 @@ __attribute__((__noreturn__)) static void Pexit(const char *c, int failed,
} }
static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) { static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
if (!pathlen && *ps->name != '/') { if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) {
if (!getcwd(ps->path, sizeof(ps->path) - 1 - ps->namelen)) {
Pexit("getcwd", -errno, "failed");
}
pathlen = strlen(ps->path);
} else if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) {
return 0; return 0;
} }
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/'; if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
memmove(ps->path + pathlen, ps->name, ps->namelen); memmove(ps->path + pathlen, ps->name, ps->namelen);
ps->path[pathlen + ps->namelen] = 0; ps->path[pathlen + ps->namelen] = 0;
if (!access(ps->path, X_OK)) { return !access(ps->path, X_OK);
if (ps->indirect) {
ps->namelen -= 4;
ps->path[pathlen + ps->namelen] = 0;
if (access(ps->path, X_OK) < 0) {
Pexit(ps->path, -errno, "access(X_OK)");
}
}
return 1;
}
return 0;
} }
static char SearchPath(struct PathSearcher *ps) { static char SearchPath(struct PathSearcher *ps) {
@ -368,12 +351,8 @@ static char FindCommand(struct PathSearcher *ps) {
ps->path[0] = 0; ps->path[0] = 0;
/* paths are always 100% taken literally when a slash exists /* paths are always 100% taken literally when a slash exists
$ ape foo/bar.com arg1 arg2 */ $ ape foo/bar.com arg1 arg2
if (memchr(ps->name, '/', ps->namelen)) { we don't run files in the current directory
return AccessCommand(ps, 0);
}
/* we don't run files in the current directory
$ ape foo.com arg1 arg2 $ ape foo.com arg1 arg2
unless $PATH has an empty string entry, e.g. unless $PATH has an empty string entry, e.g.
$ expert PATH=":/bin" $ expert PATH=":/bin"
@ -381,8 +360,8 @@ static char FindCommand(struct PathSearcher *ps) {
however we will execute this however we will execute this
$ ape - foo.com foo.com arg1 arg2 $ ape - foo.com foo.com arg1 arg2
because cosmo's execve needs it */ because cosmo's execve needs it */
if (ps->literally && AccessCommand(ps, 0)) { if (ps->literally || memchr(ps->name, '/', ps->namelen)) {
return 1; return AccessCommand(ps, 0);
} }
/* otherwise search for name on $PATH */ /* otherwise search for name on $PATH */
@ -392,7 +371,8 @@ static char FindCommand(struct PathSearcher *ps) {
static char *Commandv(struct PathSearcher *ps, const char *name, static char *Commandv(struct PathSearcher *ps, const char *name,
const char *syspath) { const char *syspath) {
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin"; ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
if (!(ps->namelen = StrLen((ps->name = name)))) return 0; ps->name = name;
if (!(ps->namelen = ps->indirect ? ps->indirect : StrLen(ps->name))) return 0;
if (ps->namelen + 1 > sizeof(ps->path)) return 0; if (ps->namelen + 1 > sizeof(ps->path)) return 0;
if (FindCommand(ps)) { if (FindCommand(ps)) {
return ps->path; return ps->path;
@ -563,7 +543,8 @@ static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds,
__attribute__((__noreturn__)) static void Spawn(const char *exe, int fd, __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
long *sp, struct ElfEhdr *e, long *sp, struct ElfEhdr *e,
struct ElfPhdr *p, struct ElfPhdr *p,
struct Syslib *lib) { struct Syslib *lib,
char *path) {
long rc; long rc;
int prot; int prot;
int flags; int flags;
@ -734,11 +715,11 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
close(fd); close(fd);
register long *x0 __asm__("x0") = sp; register long *x0 __asm__("x0") = sp;
register char *x2 __asm__("x2") = path;
register int x3 __asm__("x3") = 8; /* _HOSTXNU */
register struct Syslib *x15 __asm__("x15") = lib; register struct Syslib *x15 __asm__("x15") = lib;
register long x16 __asm__("x16") = e->e_entry; register long x16 __asm__("x16") = e->e_entry;
__asm__ volatile("mov\tx1,#0\n\t" __asm__ volatile("mov\tx1,#0\n\t"
"mov\tx2,#0\n\t"
"mov\tx3,#0\n\t"
"mov\tx4,#0\n\t" "mov\tx4,#0\n\t"
"mov\tx5,#0\n\t" "mov\tx5,#0\n\t"
"mov\tx6,#0\n\t" "mov\tx6,#0\n\t"
@ -767,7 +748,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
"mov\tx0,#0\n\t" "mov\tx0,#0\n\t"
"br\tx16" "br\tx16"
: /* no outputs */ : /* no outputs */
: "r"(x0), "r"(x15), "r"(x16) : "r"(x0), "r"(x2), "r"(x3), "r"(x15), "r"(x16)
: "memory"); : "memory");
__builtin_unreachable(); __builtin_unreachable();
} }
@ -870,28 +851,30 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
auxv[7] = ebuf->ehdr.e_entry; auxv[7] = ebuf->ehdr.e_entry;
auxv[8] = AT_PAGESZ; auxv[8] = AT_PAGESZ;
auxv[9] = pagesz; auxv[9] = pagesz;
auxv[10] = AT_UID; auxv[10] = AT_FLAGS;
auxv[11] = getuid(); auxv[11] = M->ps.literally ? AT_FLAGS_PRESERVE_ARGV0 : 0;
auxv[12] = AT_EUID; auxv[12] = AT_UID;
auxv[13] = geteuid(); auxv[13] = getuid();
auxv[14] = AT_GID; auxv[14] = AT_EUID;
auxv[15] = getgid(); auxv[15] = geteuid();
auxv[16] = AT_EGID; auxv[16] = AT_GID;
auxv[17] = getegid(); auxv[17] = getgid();
auxv[18] = AT_HWCAP; auxv[18] = AT_EGID;
auxv[19] = 0xffb3ffffu; auxv[19] = getegid();
auxv[20] = AT_HWCAP2; auxv[20] = AT_HWCAP;
auxv[21] = 0x181; auxv[21] = 0xffb3ffffu;
auxv[22] = AT_SECURE; auxv[22] = AT_HWCAP2;
auxv[23] = issetugid(); auxv[23] = 0x181;
auxv[24] = AT_RANDOM; auxv[24] = AT_SECURE;
auxv[25] = (long)M->rando; auxv[25] = issetugid();
auxv[26] = AT_EXECFN; auxv[26] = AT_RANDOM;
auxv[27] = (long)execfn; auxv[27] = (long)M->rando;
auxv[28] = 0; auxv[28] = AT_EXECFN;
auxv[29] = (long)execfn;
auxv[30] = 0;
/* we're now ready to load */ /* we're now ready to load */
Spawn(exe, fd, sp, e, p, &M->lib); Spawn(exe, fd, sp, e, p, &M->lib, M->ps.path);
} }
int main(int argc, char **argv, char **envp) { int main(int argc, char **argv, char **envp) {
@ -900,8 +883,7 @@ int main(int argc, char **argv, char **envp) {
struct ApeLoader *M; struct ApeLoader *M;
long *sp, *sp2, *auxv; long *sp, *sp2, *auxv;
union ElfEhdrBuf *ebuf; union ElfEhdrBuf *ebuf;
char *p, *pe, *exe, *prog, char *p, *pe, *exe, *prog, *execfn;
*execfn, *shell, **varpos;
/* allocate loader memory in program's arg block */ /* allocate loader memory in program's arg block */
n = sizeof(struct ApeLoader); n = sizeof(struct ApeLoader);
@ -964,16 +946,16 @@ int main(int argc, char **argv, char **envp) {
M->lib.dlerror = dlerror; M->lib.dlerror = dlerror;
/* getenv("_") is close enough to at_execfn */ /* getenv("_") is close enough to at_execfn */
execfn = argc > 0 ? argv[0] : 0; execfn = 0;
varpos = 0;
for (i = 0; envp[i]; ++i) { for (i = 0; envp[i]; ++i) {
if (envp[i][0] == '_' && envp[i][1] == '=') { if (envp[i][0] == '_' && envp[i][1] == '=') {
execfn = envp[i] + 2; execfn = envp[i] + 2;
} else if (!memcmp(VARNAME, envp[i], VARSIZE)) {
assert(!varpos);
varpos = envp + i;
} }
} }
prog = GetEnv(envp + i + 1, "executable_path");
if (!execfn) {
execfn = prog;
}
/* sneak the system five abi back out of args */ /* sneak the system five abi back out of args */
sp = (long *)(argv - 1); sp = (long *)(argv - 1);
@ -982,7 +964,7 @@ int main(int argc, char **argv, char **envp) {
/* create new bottom of stack for spawned program /* create new bottom of stack for spawned program
system v abi aligns this on a 16-byte boundary system v abi aligns this on a 16-byte boundary
grows down the alloc by poking the guard pages */ grows down the alloc by poking the guard pages */
n = (auxv - sp + !varpos + AUXV_WORDS + 1) * sizeof(long); n = (auxv - sp + AUXV_WORDS + 1) * sizeof(long);
sp2 = (long *)__builtin_alloca(n); sp2 = (long *)__builtin_alloca(n);
if ((long)sp2 & 15) ++sp2; if ((long)sp2 & 15) ++sp2;
for (; n > 0; n -= pagesz) { for (; n > 0; n -= pagesz) {
@ -991,18 +973,12 @@ int main(int argc, char **argv, char **envp) {
memmove(sp2, sp, (auxv - sp) * sizeof(long)); memmove(sp2, sp, (auxv - sp) * sizeof(long));
argv = (char **)(sp2 + 1); argv = (char **)(sp2 + 1);
envp = (char **)(sp2 + 1 + argc + 1); envp = (char **)(sp2 + 1 + argc + 1);
if (varpos) {
varpos = (char **)((long *)varpos - sp + sp2);
} else {
varpos = envp + i++;
*(envp + i) = 0;
}
auxv = (long *)(envp + i + 1); auxv = (long *)(envp + i + 1);
sp = sp2; sp = sp2;
/* interpret command line arguments */ /* interpret command line arguments */
if ((M->ps.indirect = argc > 0 ? GetIndirectOffset(argv[0]) : 0)) { if ((M->ps.indirect = GetIndirectOffset(prog))) {
/* if argv[0] is $prog.ape, then we strip off the .ape and run /* if called as $prog.ape, then strip off the .ape and run the
$prog. This allows you to use symlinks to trick the OS when $prog. This allows you to use symlinks to trick the OS when
a native executable is required. For example, let's say you a native executable is required. For example, let's say you
want to use the APE binary /opt/cosmos/bin/bash as a system want to use the APE binary /opt/cosmos/bin/bash as a system
@ -1011,13 +987,7 @@ int main(int argc, char **argv, char **envp) {
but it will if you say: but it will if you say:
ln -sf /usr/local/bin/ape /opt/cosmos/bin/bash.ape ln -sf /usr/local/bin/ape /opt/cosmos/bin/bash.ape
and then use #!/opt/cosmos/bin/bash.ape instead. */ and then use #!/opt/cosmos/bin/bash.ape instead. */
M->ps.literally = 0; M->ps.literally = 1;
if (*argv[0] == '-' && (shell = GetEnv(envp, "SHELL")) &&
!StrCmp(argv[0] + 1, BaseName(shell))) {
execfn = prog = shell;
} else {
prog = (char *)sp[1];
}
argc = sp[0]; argc = sp[0];
argv = (char **)(sp + 1); argv = (char **)(sp + 1);
} else if ((M->ps.literally = argc >= 3 && !StrCmp(argv[1], "-"))) { } else if ((M->ps.literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
@ -1031,9 +1001,9 @@ int main(int argc, char **argv, char **envp) {
} else if (argc < 2) { } else if (argc < 2) {
Emit("usage: ape PROG [ARGV1,ARGV2,...]\n" Emit("usage: ape PROG [ARGV1,ARGV2,...]\n"
" ape - PROG [ARGV0,ARGV1,...]\n" " ape - PROG [ARGV0,ARGV1,...]\n"
" ($0 = PROG.ape) [ARGV1,ARGV2,...]\n" " PROG.ape [ARGV1,ARGV2,...]\n"
"actually portable executable loader silicon 1.9\n" "actually portable executable loader silicon 1.10\n"
"copyright 2023 justine alexandra roberts tunney\n" "copyrights 2023 justine alexandra roberts tunney\n"
"https://justine.lol/ape.html\n"); "https://justine.lol/ape.html\n");
_exit(1); _exit(1);
} else { } else {
@ -1061,12 +1031,6 @@ int main(int argc, char **argv, char **envp) {
} }
pe = ebuf->buf + rc; pe = ebuf->buf + rc;
/* inject program executable as first environment variable,
swapping the old first variable for it. */
memmove(M->ps.varname, VARNAME, VARSIZE);
*varpos = *envp;
*envp = M->ps.varname;
/* generate some hard random data */ /* generate some hard random data */
if ((rc = sys_getentropy(M->rando, sizeof(M->rando))) < 0) { if ((rc = sys_getentropy(M->rando, sizeof(M->rando))) < 0) {
Pexit(argv[0], rc, "getentropy"); Pexit(argv[0], rc, "getentropy");

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2020 Justine Alexandra Roberts Tunney
@ -592,9 +592,7 @@ ape_disk:
#ifdef APE_IS_SHELL_SCRIPT #ifdef APE_IS_SHELL_SCRIPT
apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii "m=$(/bin/uname -m 2>/dev/null) || " .ascii "m=$(uname -m 2>/dev/null) || m=x86_64\n"
.ascii "m=$(/usr/bin/uname -m 2>/dev/null) || "
.ascii "m=x86_64\n"
.ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n" .ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n"
// Until all operating systems can be updated to support APE, // Until all operating systems can be updated to support APE,
@ -617,15 +615,15 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii APE_VERSION_STR .ascii APE_VERSION_STR
.ascii "\"\n" .ascii "\"\n"
.ascii "[ -x \"$t\" ] || {\n" .ascii "[ -x \"$t\" ] || {\n"
.ascii "/bin/mkdir -p \"${t%/*}\" &&\n" .ascii "mkdir -p \"${t%/*}\" &&\n"
.ascii "/bin/dd if=\"$o\" of=\"$t.$$\" skip=" .ascii "dd if=\"$o\" of=\"$t.$$\" skip="
.shstub ape_loader_dd_skip,2 .shstub ape_loader_dd_skip,2
.ascii " count=" .ascii " count="
.shstub ape_loader_dd_count,2 .shstub ape_loader_dd_count,2
.ascii " bs=64 2>/dev/null\n" .ascii " bs=64 2>/dev/null\n"
#if SupportsXnu() #if SupportsXnu()
.ascii "[ -d /Applications ] && " .ascii "[ -d /Applications ] && "
.ascii "/bin/dd if=\"$t.$$\"" .ascii "dd if=\"$t.$$\""
.ascii " of=\"$t.$$\"" .ascii " of=\"$t.$$\""
.ascii " skip=5" .ascii " skip=5"
.ascii " count=8" .ascii " count=8"
@ -633,8 +631,8 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii " conv=notrunc" .ascii " conv=notrunc"
.ascii " 2>/dev/null\n" .ascii " 2>/dev/null\n"
#endif /* SupportsXnu() */ #endif /* SupportsXnu() */
.ascii "/bin/chmod 755 \"$t.$$\"\n" .ascii "chmod 755 \"$t.$$\"\n"
.ascii "/bin/mv -f \"$t.$$\" \"$t\"\n" .ascii "mv -f \"$t.$$\" \"$t\"\n"
.ascii "}\n" .ascii "}\n"
.ascii "exec \"$t\" \"$o\" \"$@\"\n" .ascii "exec \"$t\" \"$o\" \"$@\"\n"
.ascii "}\n" .ascii "}\n"
@ -650,9 +648,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii "t=\"${TMPDIR:-${HOME:-.}}/$0\"\n" .ascii "t=\"${TMPDIR:-${HOME:-.}}/$0\"\n"
.ascii "[ x\"$1\" != x--assimilate ] || [ ! -e \"$t\" ] && {\n" .ascii "[ x\"$1\" != x--assimilate ] || [ ! -e \"$t\" ] && {\n"
.ascii "[ x\"$1\" != x--assimilate ] && {\n" .ascii "[ x\"$1\" != x--assimilate ] && {\n"
.ascii "/bin/mkdir -p \"${t%/*}\" 2>/dev/null\n" .ascii "mkdir -p \"${t%/*}\" 2>/dev/null\n"
.ascii "/bin/cp -f \"$o\" \"$t.$$\" &&\n" .ascii "cp -f \"$o\" \"$t.$$\" &&\n"
.ascii "/bin/mv -f \"$t.$$\" \"$t\" || exit 120\n" .ascii "mv -f \"$t.$$\" \"$t\" || exit 120\n"
.ascii "o=\"$t\"\n" .ascii "o=\"$t\"\n"
.ascii "}\n" .ascii "}\n"
#endif /* APE_NO_MODIFY_SELF */ #endif /* APE_NO_MODIFY_SELF */
@ -683,7 +681,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii "exec 7<&-\n" .ascii "exec 7<&-\n"
#if SupportsXnu() #if SupportsXnu()
.ascii "[ -d /Applications ] && " .ascii "[ -d /Applications ] && "
.ascii "/bin/dd if=\"$o\"" .ascii "dd if=\"$o\""
.ascii " of=\"$o\"" .ascii " of=\"$o\""
.ascii " bs=8" .ascii " bs=8"
.ascii " skip=" .ascii " skip="
@ -702,38 +700,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
#endif /* APE_NO_MODIFY_SELF */ #endif /* APE_NO_MODIFY_SELF */
.ascii "exit $?\n" .ascii "exit $?\n"
.ascii "fi\n" // x86_64 .ascii "fi\n" // x86_64
// ... .ascii "echo error: this ape binary only supports x86_64 >&2\n"
// decentralized section (.apesh)
// ...
.ascii "PHDRS='' <<'@'\n"
.endobj apesh
// elf program headers get inserted here
// because they need to be in the first 4096 bytes
.section .emushprologue,"a",@progbits
emush: .ascii "\n@\n#'\"\n"
.ascii "s=$(/bin/uname -s 2>/dev/null) || "
.ascii "s=$(/usr/bin/uname -s 2>/dev/null) || "
.ascii "s=Darwin\n"
// our script is running on a non-x86_64 architecture
// 1. `dd` out the appropriate blink vm blob
// 2. gunzip the blink virtual machine executable
// 3. relaunch this program inside the blink vm
.ascii "o=\"$(command -v \"$0\")\"\n"
.ascii "e=\"${TMPDIR:-${HOME:-.}}/.ape-blink-1.0.0\"\n"
.previous
// ...
// decentralized section (.emush)
// - __static_yoink("blink_linux_aarch64"); // for raspberry pi
// - __static_yoink("blink_xnu_aarch64"); // is apple silicon
// ...
.section .emushepilogue,"a",@progbits
.ascii "echo \"$0: this ape binary lacks $m support\" >&2\n"
.rept 16
.ascii "exit 127\n"
.endr
.ascii "exit 1\n" .ascii "exit 1\n"
.previous .endobj apesh
#ifdef APE_LOADER #ifdef APE_LOADER
.section .ape.loader,"a",@progbits .section .ape.loader,"a",@progbits

View file

@ -2,7 +2,7 @@
#define COSMOPOLITAN_APE_APE_H_ #define COSMOPOLITAN_APE_APE_H_
#define APE_VERSION_MAJOR 1 #define APE_VERSION_MAJOR 1
#define APE_VERSION_MINOR 9 #define APE_VERSION_MINOR 10
#define APE_VERSION_STR APE_VERSION_STR_(APE_VERSION_MAJOR, APE_VERSION_MINOR) #define APE_VERSION_STR APE_VERSION_STR_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
#define APE_VERSION_NOTE APE_VERSION_NOTE_(APE_VERSION_MAJOR, APE_VERSION_MINOR) #define APE_VERSION_NOTE APE_VERSION_NOTE_(APE_VERSION_MAJOR, APE_VERSION_MINOR)

View file

@ -1,5 +1,5 @@
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│ /*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
│ vi: set noet sts=2 tw=2 fenc=utf-8 :vi │ │ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
╞══════════════════════════════════════════════════════════════════════════════╡ ╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │ │ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │ │ │
@ -229,7 +229,6 @@ SECTIONS {
/* Real Mode */ /* Real Mode */
KEEP(*(.head)) KEEP(*(.head))
KEEP(*(.apesh))
KEEP(*(.text.head)) KEEP(*(.text.head))
/* Executable & Linkable Format */ /* Executable & Linkable Format */
@ -238,10 +237,6 @@ SECTIONS {
KEEP(*(.elf.phdrs)) KEEP(*(.elf.phdrs))
ape_phdrs_end = .; ape_phdrs_end = .;
KEEP(*(.emushprologue))
KEEP(*(.emush))
KEEP(*(.emushepilogue))
/* OpenBSD */ /* OpenBSD */
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0); . = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
ape_note = .; ape_note = .;
@ -301,7 +296,6 @@ SECTIONS {
KEEP(*(.textwindowsprologue)) KEEP(*(.textwindowsprologue))
*(.text.windows) *(.text.windows)
KEEP(*(.textwindowsepilogue)) KEEP(*(.textwindowsepilogue))
KEEP(*(.blink))
*(SORT_BY_ALIGNMENT(.text.modernity)) *(SORT_BY_ALIGNMENT(.text.modernity))
*(SORT_BY_ALIGNMENT(.text.modernity.*)) *(SORT_BY_ALIGNMENT(.text.modernity.*))
*(SORT_BY_ALIGNMENT(.text.hot)) *(SORT_BY_ALIGNMENT(.text.hot))
@ -613,29 +607,6 @@ SHSTUB2(ape_loader_dd_count,
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64 ? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
: 0); : 0);
#if defined(APE_IS_SHELL_SCRIPT) && !IsTiny()
#define IDENTITY(X) X
#define APE_DECLARE_FIXED_DECIMAL(F, X) \
X##_quad = DEFINED(X) ? ((F(X) < 1000000000 ? 32 : F(X) / 1000000000 % 10 + 48) << 000 | \
(F(X) < 100000000 ? 32 : F(X) / 100000000 % 10 + 48) << 010 | \
(F(X) < 10000000 ? 32 : F(X) / 10000000 % 10 + 48) << 020 | \
(F(X) < 1000000 ? 32 : F(X) / 1000000 % 10 + 48) << 030 | \
(F(X) < 100000 ? 32 : F(X) / 100000 % 10 + 48) << 040 | \
(F(X) < 10000 ? 32 : F(X) / 10000 % 10 + 48) << 050 | \
(F(X) < 1000 ? 32 : F(X) / 1000 % 10 + 48) << 060 | \
(F(X) < 100 ? 32 : F(X) / 100 % 10 + 48) << 070) : 0; \
X##_short = DEFINED(X) ? ((F(X) < 10 ? 32 : F(X) / 10 % 10 + 48) << 000 | \
(F(X) % 10 + 48) << 010) : 0
APE_DECLARE_FIXED_DECIMAL(RVA, blink_linux_aarch64);
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_linux_aarch64_size);
APE_DECLARE_FIXED_DECIMAL(RVA, blink_xnu_aarch64);
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_xnu_aarch64_size);
#endif /* APE_IS_SHELL_SCRIPT */
#if SupportsMetal() #if SupportsMetal()
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512; v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
v_ape_realbytes = v_ape_realsectors * 512; v_ape_realbytes = v_ape_realsectors * 512;

View file

@ -10,73 +10,98 @@ if [ ! -f ape/loader.c ]; then
cd "$COSMO" || exit cd "$COSMO" || exit
fi fi
if [ -x build/bootstrap/make.com ]; then
MAKE=build/bootstrap/make.com
else
MAKE=make
fi
if [ "$(id -u)" -eq 0 ]; then if [ "$(id -u)" -eq 0 ]; then
SUDO= SUDO=
else elif command -v sudo >/dev/null 2>&1; then
SUDO=sudo SUDO=sudo
elif command -v doas >/dev/null 2>&1; then
SUDO=doas
else
echo "need root or sudo" >&2
exit
fi
if command -v install >/dev/null 2>&1; then
if [ x"$(uname -s)" = xLinux ]; then
INSTALL="install -o root -g root -m 755"
else
INSTALL="install -o root -g wheel -m 755"
fi
else
INSTALL="cp -f"
fi fi
echo "Actually Portable Executable (APE) Installer" >&2 echo "Actually Portable Executable (APE) Installer" >&2
echo "Author: Justine Tunney <jtunney@gmail.com>" >&2 echo "Author: Justine Tunney <jtunney@gmail.com>" >&2
# special installation process for apple silicon # special installation process for apple silicon
if [ "$(uname -s)" = "Darwin" ] && [ "$(uname -m)" = "arm64" ]; then if [ x"$(uname -s)" = xDarwin ] && [ x"$(uname -m)" = xarm64 ]; then
echo "cc -O -o $TMPDIR/ape.$$ ape/ape-m1.c" >&2 echo "cc -O -o $TMPDIR/ape.$$ ape/ape-m1.c" >&2
cc -O -o "$TMPDIR/ape.$$" ape/ape-m1.c || exit cc -O -o "$TMPDIR/ape.$$" ape/ape-m1.c || exit
trap 'rm "$TMPDIR/ape.$$"' EXIT
if [ ! -d /usr/local/bin ]; then if [ ! -d /usr/local/bin ]; then
echo "$SUDO mkdir -p /usr/local/bin" >&2 echo "$SUDO mkdir -p /usr/local/bin" >&2
$SUDO mkdir -p /usr/local/bin || exit $SUDO mkdir -p /usr/local/bin || exit
fi fi
echo "$SUDO mv -f $TMPDIR/ape.$$ /usr/local/bin/ape" >&2 echo "$SUDO $INSTALL $TMPDIR/ape.$$ /usr/local/bin/ape" >&2
$SUDO mv -f "$TMPDIR/ape.$$" /usr/local/bin/ape || exit $SUDO $INSTALL "$TMPDIR/ape.$$" /usr/local/bin/ape || exit
exit
fi
if [ x"$(uname -m)" = xarm64 ] || [ x"$(uname -m)" = xaarch64 ]; then
MODE=aarch64
EXT=elf
BEXT=aarch64
elif [ x"$(uname -m)" = xx86_64 ]; then
MODE=
if [ x"$(uname -s)" = xDarwin ]; then
EXT=macho
else
EXT=elf
fi
BEXT=$EXT
else
echo "unsupported architecture $(uname -m)" >&2
exit exit
fi fi
################################################################################ ################################################################################
# INSTALL APE LOADER SYSTEMWIDE # INSTALL APE LOADER SYSTEMWIDE
if [ -f o/depend ] && make -j8 o//ape; then if [ -f o/$MODE/depend ] && $MAKE -j8 o/$MODE/ape; then
echo "successfully recompiled ape loader" >&2 echo "successfully recompiled ape loader" >&2
elif [ -x o//ape/ape.elf ] && [ -x o//ape/ape.macho ]; then elif [ -x o/$MODE/ape/ape.$EXT ]; then
echo "using ape loader you compiled earlier" >&2 echo "using ape loader you compiled earlier" >&2
elif [ -d build/bootstrap ]; then elif [ -d build/bootstrap ]; then
# if make isn't being used then it's unlikely the user changed the sources # if make isn't being used then it's unlikely the user changed the sources
# in that case the prebuilt binaries should be completely up-to-date # in that case the prebuilt binaries should be completely up-to-date
echo "using prebuilt ape loader from cosmo repo" >&2 echo "using prebuilt ape loader from cosmo repo" >&2
mkdir -p o//ape || exit mkdir -p o/$MODE/ape || exit
cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit cp -af build/bootstrap/ape.$BEXT o/$MODE/ape/ape.$EXT || exit
cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit
else else
echo "no cosmopolitan libc repository here" >&2 echo "no cosmopolitan libc repository here" >&2
echo "fetching ape loader from justine.lol" >&2 echo "fetching ape loader from justine.lol" >&2
mkdir -p o//ape || exit mkdir -p o/$MODE/ape || exit
if command -v wget >/dev/null 2>&1; then if command -v wget >/dev/null 2>&1; then
wget -qO o//ape/ape.elf https://justine.lol/ape.elf || exit wget -qO o/$MODE/ape/ape.$EXT https://justine.lol/ape.$BEXT || exit
wget -qO o//ape/ape.macho https://justine.lol/ape.macho || exit
else else
curl -Rso o//ape/ape.elf https://justine.lol/ape.elf || exit curl -Rso o/$MODE/ape/ape.$EXT https://justine.lol/ape.$BEXT || exit
curl -Rso o//ape/ape.macho https://justine.lol/ape.macho || exit
fi fi
chmod +x o//ape/ape.elf || exit chmod +x o/$MODE/ape/ape.$EXT || exit
chmod +x o//ape/ape.macho || exit
fi fi
if [ "$(uname -s)" = "Darwin" ]; then if ! [ /usr/bin/ape -nt o/$MODE/ape/ape.$EXT ]; then
if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then echo >&2
echo >&2 echo "installing o/$MODE/ape/ape.$EXT to /usr/bin/ape" >&2
echo "installing o//ape/ape.macho to /usr/bin/ape" >&2 echo "$SUDO $INSTALL o/$MODE/ape/ape.$EXT /usr/bin/ape" >&2
echo "$SUDO cp -f o//ape/ape.macho /usr/bin/ape" >&2 $SUDO $INSTALL o/$MODE/ape/ape.$EXT /usr/bin/ape || exit
$SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit echo "done" >&2
echo "done" >&2
fi
else
if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then
echo >&2
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
$SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit
echo "done" >&2
fi
fi fi
################################################################################ ################################################################################

View file

@ -11,8 +11,13 @@ fi
if [ "$UID" = "0" ]; then if [ "$UID" = "0" ]; then
SUDO= SUDO=
else elif command -v sudo >/dev/null 2>&1; then
SUDO=sudo SUDO=sudo
elif command -v doas >/dev/null 2>&1; then
SUDO=doas
else
echo "need root or sudo" >&2
exit
fi fi
{ {
@ -54,8 +59,7 @@ for x in .ape \
.ape-1.7 \ .ape-1.7 \
.ape-1.8 \ .ape-1.8 \
.ape-1.9 \ .ape-1.9 \
.ape-blink-0.9.2 \ .ape-1.10; do
.ape-blink-1.0.0; do
rm -f \ rm -f \
~/$x \ ~/$x \
/tmp/$x \ /tmp/$x \

Binary file not shown.

Binary file not shown.

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney Copyright 2023 Justine Alexandra Roberts Tunney
@ -31,17 +31,16 @@
// //
// @param rdi is passed through as-is // @param rdi is passed through as-is
// @param rsi is address of entrypoint (becomes zero) // @param rsi is address of entrypoint (becomes zero)
// @param rdx is stack pointer (becomes zero) // @param rdx is passed through as-is
// @param rcx is passed through as-is // @param rcx is passed through as-is
// @param r8 is stack pointer (becomes zero)
// @noreturn // @noreturn
Launch: Launch:
#ifdef __aarch64__ #ifdef __aarch64__
mov x16,x1 mov x16,x1
mov sp,x2 mov sp,x4
mov x1,0 mov x1,0
mov x2,0
mov x3,0
mov x4,0 mov x4,0
mov x5,0 mov x5,0
mov x6,0 mov x6,0
@ -71,6 +70,7 @@ Launch:
#else #else
mov %r8,%rsp
xor %r8d,%r8d xor %r8d,%r8d
xor %r9d,%r9d xor %r9d,%r9d
xor %r10d,%r10d xor %r10d,%r10d
@ -79,8 +79,6 @@ Launch:
xor %r13d,%r13d xor %r13d,%r13d
xor %r14d,%r14d xor %r14d,%r14d
xor %r15d,%r15d xor %r15d,%r15d
mov %rdx,%rsp
xor %edx,%edx
push %rsi push %rsi
xor %esi,%esi xor %esi,%esi
xor %ebp,%ebp xor %ebp,%ebp

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney Copyright 2021 Justine Alexandra Roberts Tunney

View file

@ -87,6 +87,8 @@
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y)) #define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y)) #define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
#define PATH_MAX 1024 /* XXX verify */
#define SupportsLinux() (SUPPORT_VECTOR & LINUX) #define SupportsLinux() (SUPPORT_VECTOR & LINUX)
#define SupportsXnu() (SUPPORT_VECTOR & XNU) #define SupportsXnu() (SUPPORT_VECTOR & XNU)
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD) #define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
@ -111,41 +113,44 @@
#define EXTERN_C #define EXTERN_C
#endif #endif
#define O_RDONLY 0 #define O_RDONLY 0
#define PROT_NONE 0 #define PROT_NONE 0
#define PROT_READ 1 #define PROT_READ 1
#define PROT_WRITE 2 #define PROT_WRITE 2
#define PROT_EXEC 4 #define PROT_EXEC 4
#define MAP_SHARED 1 #define MAP_SHARED 1
#define MAP_PRIVATE 2 #define MAP_PRIVATE 2
#define MAP_FIXED 16 #define MAP_FIXED 16
#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096) #define MAP_ANONYMOUS (IsLinux() ? 32 : 4096)
#define MAP_NORESERVE (IsLinux() ? 16384 : 0) #define MAP_NORESERVE (IsLinux() ? 16384 : 0)
#define ELFCLASS32 1 #define ELFCLASS32 1
#define ELFDATA2LSB 1 #define ELFDATA2LSB 1
#define EM_NEXGEN32E 62 #define EM_NEXGEN32E 62
#define EM_AARCH64 183 #define EM_AARCH64 183
#define ET_EXEC 2 #define ET_EXEC 2
#define ET_DYN 3 #define ET_DYN 3
#define PT_LOAD 1 #define PT_LOAD 1
#define PT_DYNAMIC 2 #define PT_DYNAMIC 2
#define PT_INTERP 3 #define PT_INTERP 3
#define EI_CLASS 4 #define EI_CLASS 4
#define EI_DATA 5 #define EI_DATA 5
#define PF_X 1 #define PF_X 1
#define PF_W 2 #define PF_W 2
#define PF_R 4 #define PF_R 4
#define AT_PHDR 3 #define AT_PHDR 3
#define AT_PHENT 4 #define AT_PHENT 4
#define AT_PHNUM 5 #define AT_PHNUM 5
#define AT_PAGESZ 6 #define AT_PAGESZ 6
#define AT_EXECFN_LINUX 31 #define AT_FLAGS 8
#define AT_EXECFN_NETBSD 2014 #define AT_FLAGS_PRESERVE_ARGV0_BIT 0
#define X_OK 1 #define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
#define XCR0_SSE 2 #define AT_EXECFN_LINUX 31
#define XCR0_AVX 4 #define AT_EXECFN_NETBSD 2014
#define PR_SET_MM 35 #define X_OK 1
#define PR_SET_MM_EXE_FILE 13 #define XCR0_SSE 2
#define XCR0_AVX 4
#define PR_SET_MM 35
#define PR_SET_MM_EXE_FILE 13
#define READ32(S) \ #define READ32(S) \
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \ ((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
@ -212,17 +217,18 @@ struct PathSearcher {
const char *name; const char *name;
const char *syspath; const char *syspath;
unsigned long namelen; unsigned long namelen;
char path[1024]; char path[PATH_MAX];
}; };
struct ApeLoader { struct ApeLoader {
union ElfPhdrBuf phdr; union ElfPhdrBuf phdr;
struct PathSearcher ps; struct PathSearcher ps;
char path[1024]; char path[PATH_MAX];
}; };
EXTERN_C long SystemCall(long, long, long, long, long, long, long, int); EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
EXTERN_C void Launch(void *, long, void *, int) __attribute__((__noreturn__)); EXTERN_C void Launch(void *, long, void *, int, void *)
__attribute__((__noreturn__));
extern char __executable_start[]; extern char __executable_start[];
extern char _end[]; extern char _end[];
@ -239,12 +245,13 @@ static int StrCmp(const char *l, const char *r) {
return (l[i] & 255) - (r[i] & 255); return (l[i] & 255) - (r[i] & 255);
} }
static const char *BaseName(const char *s) { #if 0
int c;
const char *b = ""; static const char *StrRChr(const char *s, int c) {
const char *b = 0;
if (s) { if (s) {
while ((c = *s++)) { for (; *s; ++s) {
if (c == '/') { if (*s == c) {
b = s; b = s;
} }
} }
@ -252,6 +259,13 @@ static const char *BaseName(const char *s) {
return b; return b;
} }
static const char *BaseName(const char *s) {
const char *b = StrRChr(s, '/');
return b ? b + 1 : s;
}
#endif
static void Bzero(void *a, unsigned long n) { static void Bzero(void *a, unsigned long n) {
long z; long z;
char *p, *e; char *p, *e;
@ -343,7 +357,7 @@ static char *Utox(char p[19], unsigned long x) {
return p; return p;
} }
static char *Utoa(char p[21], unsigned long x) { static char *Utoa(char p[20], unsigned long x) {
char t; char t;
unsigned long i, a, b; unsigned long i, a, b;
i = 0; i = 0;
@ -561,45 +575,22 @@ static char SearchPath(struct PathSearcher *ps) {
} }
} }
static char FindCommand(struct PathSearcher *ps) { static char *Commandv(struct PathSearcher *ps, int os, char *name,
ps->path[0] = 0;
/* paths are always 100% taken literally when a slash exists
$ ape foo/bar.com arg1 arg2 */
if (MemChr(ps->name, '/', ps->namelen)) {
return AccessCommand(ps, 0);
}
/* we don't run files in the current directory
$ ape foo.com arg1 arg2
unless $PATH has an empty string entry, e.g.
$ expert PATH=":/bin"
$ ape foo.com arg1 arg2
however we will execute this
$ ape - foo.com foo.com arg1 arg2
because cosmo's execve needs it */
if (ps->literally && AccessCommand(ps, 0)) {
return 1;
}
/* otherwise search for name on $PATH */
return SearchPath(ps);
}
static char *Commandv(struct PathSearcher *ps, int os, const char *name,
const char *syspath) { const char *syspath) {
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
if (ps->literally || MemChr(ps->name, '/', ps->namelen)) return name;
ps->os = os; ps->os = os;
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin"; ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
if (ps->namelen + 1 > sizeof(ps->path)) return 0; if (ps->namelen + 1 > sizeof(ps->path)) return 0;
if (FindCommand(ps)) { ps->path[0] = 0;
if (SearchPath(ps)) {
return ps->path; return ps->path;
} else { } else {
return 0; return 0;
} }
} }
__attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
long *sp, unsigned long pagesz, long *sp, unsigned long pagesz,
struct ElfEhdr *e, struct ElfEhdr *e,
struct ElfPhdr *p) { struct ElfPhdr *p) {
@ -757,11 +748,11 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
Msyscall(dynbase + code, codesize, os); Msyscall(dynbase + code, codesize, os);
/* call program entrypoint */ /* call program entrypoint */
Launch(IsFreebsd() ? sp : 0, dynbase + e->e_entry, sp, os); Launch(IsFreebsd() ? sp : 0, dynbase + e->e_entry, exe, os, sp);
} }
static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf, static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
const char *exe, int fd, long *sp, long *auxv, char *exe, int fd, long *sp, long *auxv,
unsigned long pagesz, int os) { unsigned long pagesz, int os) {
long i, rc; long i, rc;
unsigned size; unsigned size;
@ -885,18 +876,13 @@ __attribute__((__noreturn__)) static void ShowUsage(int os, int fd, int rc) {
"NAME\n" "NAME\n"
"\n" "\n"
" actually portable executable loader version " APE_VERSION_STR "\n" " actually portable executable loader version " APE_VERSION_STR "\n"
" copyright 2023 justine alexandra roberts tunney\n" " copyrights 2024 justine alexandra roberts tunney\n"
" https://justine.lol/ape.html\n" " https://justine.lol/ape.html\n"
"\n" "\n"
"USAGE\n" "USAGE\n"
"\n" "\n"
" ape [FLAGS] PROG [ARGV1,ARGV2,...]\n" " ape PROG [ARGV1,ARGV2,...]\n"
" ape [FLAGS] - PROG [ARGV0,ARGV1,...]\n" " ape - PROG [ARGV0,ARGV1,...]\n"
"\n"
"FLAGS\n"
"\n"
" -h show this help\n"
" -f force loading of program (do not use execve)\n"
"\n", "\n",
0l); 0l);
Exit(rc, os); Exit(rc, os);
@ -906,10 +892,10 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
char dl) { char dl) {
int rc, n; int rc, n;
unsigned i; unsigned i;
char literally;
const char *ape; const char *ape;
int c, fd, os, argc; int c, fd, os, argc;
struct ApeLoader *M; struct ApeLoader *M;
char arg0, literally;
unsigned long pagesz; unsigned long pagesz;
union ElfEhdrBuf *ebuf; union ElfEhdrBuf *ebuf;
long *auxv, *ap, *endp, *sp2; long *auxv, *ap, *endp, *sp2;
@ -954,11 +940,15 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
/* detect netbsd and find end of words */ /* detect netbsd and find end of words */
pagesz = 0; pagesz = 0;
arg0 = 0;
for (ap = auxv; ap[0]; ap += 2) { for (ap = auxv; ap[0]; ap += 2) {
if (ap[0] == AT_PAGESZ) { if (ap[0] == AT_PAGESZ) {
pagesz = ap[1]; pagesz = ap[1];
} else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) { } else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) {
os = NETBSD; os = NETBSD;
} else if (SupportsLinux() && ap[0] == AT_FLAGS) {
// TODO(mrdomino): maybe set/insert this when we are called as "ape -".
arg0 = !!(ap[1] & AT_FLAGS_PRESERVE_ARGV0);
} }
} }
if (!pagesz) { if (!pagesz) {
@ -971,22 +961,13 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
os = LINUX; os = LINUX;
} }
/* parse flags */
while (argc > 1) {
if (argv[1][0] != '-') break; /* normal argument */
if (!argv[1][1]) break; /* hyphen argument */
if (!StrCmp(argv[1], "-h") || !StrCmp(argv[1], "--help")) {
ShowUsage(os, 1, 0);
} else {
Print(os, 2, ape, ": invalid flag (pass -h for help)\n", 0l);
Exit(1, os);
}
*++sp = --argc;
++argv;
}
/* we can load via shell, shebang, or binfmt_misc */ /* we can load via shell, shebang, or binfmt_misc */
if ((literally = argc >= 3 && !StrCmp(argv[1], "-"))) { if (arg0) {
literally = 1;
prog = (char *)sp[2];
argc = sp[2] = sp[0] - 2;
argv = (char **)((sp += 2) + 1);
} else if ((literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
/* if the first argument is a hyphen then we give the user the /* if the first argument is a hyphen then we give the user the
power to change argv[0] or omit it entirely. most operating power to change argv[0] or omit it entirely. most operating
systems don't permit the omission of argv[0] but we do, b/c systems don't permit the omission of argv[0] but we do, b/c
@ -995,9 +976,13 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
argc = sp[3] = sp[0] - 3; argc = sp[3] = sp[0] - 3;
argv = (char **)((sp += 3) + 1); argv = (char **)((sp += 3) + 1);
} else if (argc < 2) { } else if (argc < 2) {
Print(os, 2, ape, ": missing command name (pass -h for help)\n", 0l); ShowUsage(os, 2, 1);
Exit(1, os);
} else { } else {
if (argv[1][0] == '-') {
rc = !((argv[1][1] == 'h' && !argv[1][2]) ||
!StrCmp(argv[1] + 1, "-help"));
ShowUsage(os, 1 + rc, rc);
}
prog = (char *)sp[2]; prog = (char *)sp[2];
argc = sp[1] = sp[0] - 1; argc = sp[1] = sp[0] - 1;
argv = (char **)((sp += 1) + 1); argv = (char **)((sp += 1) + 1);
@ -1042,12 +1027,6 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
} }
pe = ebuf->buf + rc; pe = ebuf->buf + rc;
/* change argv[0] to resolved path if it's ambiguous */
if (argc > 0 && ((*prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
!StrCmp(BaseName(prog), argv[0]))) {
argv[0] = exe;
}
/* ape intended behavior /* ape intended behavior
1. if ape, will scan shell script for elf printf statements 1. if ape, will scan shell script for elf printf statements
2. shell script may have multiple lines producing elf headers 2. shell script may have multiple lines producing elf headers

View file

@ -1,5 +1,5 @@
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│ /*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
│ vi: set noet sts=2 tw=2 fenc=utf-8 :vi │ │ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
╞══════════════════════════════════════════════════════════════════════════════╡ ╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2023 Justine Alexandra Roberts Tunney │ │ Copyright 2023 Justine Alexandra Roberts Tunney │
│ │ │ │

View file

@ -22,119 +22,6 @@
#ifdef __ASSEMBLER__ #ifdef __ASSEMBLER__
/* clang-format off */ /* clang-format off */
/**
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
*/
// Calls near (i.e. pc+pcrel<64kB) FUNCTION.
// @mode long,legacy,real
// @cost 9 bytes overhead
.macro rlcall function:req
.byte 0x50 # push %[er]ax
.byte 0xb8,0,0 # mov $?,%[e]ax
jmp 911f
.byte 0x58 # pop %[er]ax
.byte 0xe8 # call Jvds
.long \function\()-.-4
jmp 912f
911: .byte 0x58 # pop %[er]ax
.byte 0xe8 # call Jvds
.short \function\()-.-2
912:
.endm
// Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
// @mode long,legacy,real
.macro movesdi address:req
.byte 0xbf # mov $0x????xxxx,%[e]di
.short \address>>4
.byte 0x8e,0xc7 # mov %di,%es
.byte 0xbf # mov $0x????xxxx,%[e]di
.short \address&0xf
jmp 297f
.byte 0xbf # mov $0x????xxxx,%edi
.long \address
297:
.endm
// Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
// @mode long,legacy,real
.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req
.ifnb \abcd
.if (\constexpr)<128 && (\constexpr)>=0
pushpop \constexpr,\abcd
.exitm
.endif
.endif
movb $(\constexpr)>>8&0xff,\abcd.hi
movb $(\constexpr)&0xff,\abcd.lo
.endm
// Compares 16-bit CONSTEXPR with Qw-register.
// @mode long,legacy,real
.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req
cmpb $(\constexpr)>>8&0xff,\abcd.hi
jnz 387f
cmpb $(\constexpr)&0xff,\abcd.lo
387:
.endm
// Adds 16-bit CONSTEXPR to Qw-register.
// @mode long,legacy,real
.macro bbadd constexpr:req abcd.hi:req abcd.lo:req
addb $(\constexpr)&0xff,\abcd.lo
.if (\constexpr) != 0
adcb $(\constexpr)>>8&0xff,\abcd.hi
.endif
.endm
// Subtracts 16-bit CONSTEXPR from Qw-register.
// @mode long,legacy,real
.macro bbsub constexpr:req abcd.hi:req abcd.lo:req
subb $(\constexpr)&0xff,\abcd.lo
.if (\constexpr) != 0
sbbb $(\constexpr)>>8&0xff,\abcd.hi
.endif
.endm
// Ands Qw-register with 16-bit CONSTEXPR.
// @mode long,legacy,real
.macro bband constexpr:req abcd.hi:req abcd.lo:req
.if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff
andb $(\constexpr)&0xff,\abcd.lo
.endif
.if ((\constexpr)>>8&0xff) != 0xff
andb $(\constexpr)>>8&0xff,\abcd.hi
.endif
.endm
// Ors Qw-register with 16-bit CONSTEXPR.
// @mode long,legacy,real
.macro bbor constexpr:req abcd.hi:req abcd.lo:req
.if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0
orb $(\constexpr)&0xff,\abcd.lo
.endif
.if ((\constexpr)>>8&0xff) != 0
orb $(\constexpr)>>8&0xff,\abcd.hi
.endif
.endm
// Performs ACTION only if in real mode.
// @mode long,legacy,real
.macro rlo clobber:req action:vararg
990: mov $0,\clobber
.if .-990b!=3
.error "bad clobber or assembler mode"
.endif
991: \action
.rept 2-(.-991b)
nop
.endr
.if .-991b!=2
.error "ACTION must be 1-2 bytes"
.endif
.endm
// Initializes real mode stack. // Initializes real mode stack.
// The most holiest of holy code. // The most holiest of holy code.
// @mode real // @mode real

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney Copyright 2023 Justine Alexandra Roberts Tunney

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney Copyright 2023 Justine Alexandra Roberts Tunney

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
# Default Mode # Default Mode
# #

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #
@ -53,91 +53,6 @@
# OVERRIDE_FOO set ~/.cosmo.mk and target-specific (use rarely) # OVERRIDE_FOO set ~/.cosmo.mk and target-specific (use rarely)
# #
LC_ALL = C
SOURCE_DATE_EPOCH = 0
ARFLAGS = rcsD
ZFLAGS ?=
XARGS ?= xargs -P4 -rs8000
DOT ?= dot
CLANG = clang
TMPDIR = o/tmp
AR = build/bootstrap/ar.com
CP = build/bootstrap/cp.com
RM = build/bootstrap/rm.com -f
GZIP = build/bootstrap/gzip.com
ECHO = build/bootstrap/echo.com
CHMOD = build/bootstrap/chmod.com
TOUCH = build/bootstrap/touch.com
PKG = build/bootstrap/package.com
MKDEPS = build/bootstrap/mkdeps.com
ZIPOBJ = build/bootstrap/zipobj.com
ZIPCOPY = build/bootstrap/zipcopy.com
PECHECK = build/bootstrap/pecheck.com
FIXUPOBJ = build/bootstrap/fixupobj.com
MKDIR = build/bootstrap/mkdir.com -p
COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
COMMA := ,
PWD := $(shell build/bootstrap/pwd.com)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
HOSTS ?= pi silicon
else
ARCH = x86_64
HOSTS ?= freebsd rhel7 xnu win10 openbsd netbsd
endif
ZIPOBJ_FLAGS += -a$(ARCH)
ifeq ($(PREFIX),)
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
ifeq ($(ARCH),x86_64)
ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","")
PREFIX = o/third_party/gcc/bin/x86_64-linux-cosmo-
else
IGNORE := $(shell build/bootstrap/unbundle.com)
PREFIX = o/third_party/gcc/bin/x86_64-linux-musl-
endif
endif # ($(ARCH),x86_64))
ifeq ($(ARCH),aarch64)
ifneq ("$(wildcard o/third_party/gcc/bin/aarch64-linux-cosmo-*)","")
PREFIX = o/third_party/gcc/bin/aarch64-linux-cosmo-
else
IGNORE := $(shell build/bootstrap/unbundle.com)
PREFIX = o/third_party/gcc/bin/aarch64-linux-musl-
endif
endif # ($(ARCH),aarch64)
endif # ($(USE_SYSTEM_TOOLCHAIN),)
endif # ($(PREFIX),)
AS = $(PREFIX)as
CC = $(PREFIX)gcc
CXX = $(PREFIX)g++
CXXFILT = $(PREFIX)c++filt
LD = $(PREFIX)ld.bfd
NM = $(PREFIX)nm
GCC = $(PREFIX)gcc
STRIP = $(PREFIX)strip
OBJCOPY = $(PREFIX)objcopy
OBJDUMP = $(PREFIX)objdump
ifneq ($(wildcard $(PWD)/$(PREFIX)addr2line),)
ADDR2LINE = $(PWD)/$(PREFIX)addr2line
else
ADDR2LINE = $(PREFIX)addr2line
endif
export ADDR2LINE
export LC_ALL
export MKDIR
export MODE
export SOURCE_DATE_EPOCH
export TMPDIR
ifeq ($(LANDLOCKMAKE_VERSION),) ifeq ($(LANDLOCKMAKE_VERSION),)
TMPSAFE = $(join $(TMPDIR),$(subst /,_,$@)).tmp TMPSAFE = $(join $(TMPDIR),$(subst /,_,$@)).tmp
else else

101
build/download-cosmocc.sh Executable file
View file

@ -0,0 +1,101 @@
#!/bin/sh
# cosmocc downloader script
# https://justine.lol/cosmo3/#install
# https://github.com/jart/cosmopolitan/blob/master/tool/cosmocc/README.md
# collect arguments
OUTPUT_DIR=${1:?OUTPUT_DIR}
COSMOCC_VERSION=${2:?COSMOCC_VERSION}
COSMOCC_SHA256SUM=${3:?COSMOCC_SHA256SUM}
URL1="https://github.com/jart/cosmopolitan/releases/download/${COSMOCC_VERSION}/cosmocc-${COSMOCC_VERSION}.zip"
URL2="https://cosmo.zip/pub/cosmocc/cosmocc-${COSMOCC_VERSION}.zip"
# helper function
abort() {
printf '%s\n' "download terminated." >&2
exit 1
}
# exit if already downloaded
# we need it because directory timestamps work wierdly
OUTPUT_DIR=${OUTPUT_DIR%/}
if [ -d "${OUTPUT_DIR}" ]; then
exit 0
fi
# find commands we need to securely download cosmocc
if ! UNZIP=$(command -v unzip 2>/dev/null); then
printf '%s\n' "$0: fatal error: you need the unzip command" >&2
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/unzip and put it on the system path" >&2
abort
fi
if command -v sha256sum >/dev/null 2>&1; then
# can use system sha256sum
true
elif command -v shasum >/dev/null 2>&1; then
sha256sum() {
shasum -a 256 "$@"
}
else
if [ ! -f build/sha256sum.c ]; then
printf '%s\n' "$0: fatal error: you need to install sha256sum" >&2
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/sha256sum and put it on the system path" >&2
abort
fi
if ! SHA256SUM=$(command -v "$PWD/o/build/sha256sum" 2>/dev/null); then
if ! CC=$(command -v "$CC" 2>/dev/null); then
if ! CC=$(command -v cc 2>/dev/null); then
if ! CC=$(command -v cosmocc 2>/dev/null); then
printf '%s\n' "$0: fatal error: you need to install either sha256sum, cc, or cosmocc" >&2
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/sha256sum and put it on the system path" >&2
abort
fi
fi
fi
mkdir -p o/build || abort
SHA256SUM="$PWD/o/build/sha256sum"
printf '%s\n' "${CC} -w -O2 -o ${SHA256SUM} build/sha256sum.c" >&2
"${CC}" -w -O2 -o "${SHA256SUM}.$$" build/sha256sum.c || abort
mv -f "${SHA256SUM}.$$" "${SHA256SUM}" || abort
fi
sha256sum() {
"${SHA256SUM}" "$@"
}
fi
if WGET=$(command -v wget 2>/dev/null); then
DOWNLOAD=$WGET
DOWNLOAD_ARGS=-O
elif CURL=$(command -v curl 2>/dev/null); then
DOWNLOAD=$CURL
DOWNLOAD_ARGS=-fLo
else
printf '%s\n' "$0: fatal error: you need to install either wget or curl" >&2
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/wget and put it on the system path" >&2
abort
fi
# create temporary output directory
OLDPWD=$PWD
OUTPUT_TMP="${OUTPUT_DIR}.tmp.$$/"
mkdir -p "${OUTPUT_TMP}" || abort
cd "${OUTPUT_TMP}"
die() {
cd "${OLDPWD}"
rm -rf "${OUTPUT_TMP}"
abort
}
# download cosmocc toolchain
# multiple urls avoids outages and national firewalls
if ! "${DOWNLOAD}" ${DOWNLOAD_ARGS} cosmocc.zip "${URL1}"; then
rm -f cosmocc.zip
"${DOWNLOAD}" ${DOWNLOAD_ARGS} cosmocc.zip "${URL2}" || die
fi
printf '%s\n' "${COSMOCC_SHA256SUM} *cosmocc.zip" >cosmocc.zip.sha256sum
sha256sum -c cosmocc.zip.sha256sum || die
"${UNZIP}" cosmocc.zip || die
rm -f cosmocc.zip cosmocc.zip.sha256sum
# commit output directory
cd "${OLDPWD}" || die
mv "${OUTPUT_TMP}" "${OUTPUT_DIR}" || die

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐ #-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘ #── vi: set et ft=sh ts=2 sts=2 fenc=utf-8 :vi ─────────────┘
# #
# OVERVIEW # OVERVIEW
# #
@ -66,7 +66,7 @@ set -- --regex-c='/^extern [^(]*(\*const \([^)]*\))(/\1/b' "$@"
# struct WorstSoftwareEver; # struct WorstSoftwareEver;
set -- --regex-c='/^struct.*;$/uehocruehcroue/b' "$@" set -- --regex-c='/^struct.*;$/uehocruehcroue/b' "$@"
exec $TAGS \ build/run $TAGS \
-e \ -e \
--langmap=c:.c.h \ --langmap=c:.c.h \
--exclude=libc/nt/struct/imagefileheader.internal.h \ --exclude=libc/nt/struct/imagefileheader.internal.h \

View file

@ -6,14 +6,14 @@ if [ -n "$OBJDUMP" ]; then
fi fi
find_objdump() { find_objdump() {
if [ -x o/third_party/gcc/bin/$1-linux-cosmo-objdump ]; then if [ -x .cosmocc/3.2/bin/$1-linux-cosmo-objdump ]; then
OBJDUMP=o/third_party/gcc/bin/$1-linux-cosmo-objdump OBJDUMP=.cosmocc/3.2/bin/$1-linux-cosmo-objdump
elif [ -x o/third_party/gcc/bin/$1-linux-musl-objdump ]; then elif [ -x .cosmocc/3.2/bin/$1-linux-musl-objdump ]; then
OBJDUMP=o/third_party/gcc/bin/$1-linux-musl-objdump OBJDUMP=.cosmocc/3.2/bin/$1-linux-musl-objdump
elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-objdump" ]; then elif [ -x "$COSMO/.cosmocc/3.2/bin/$1-linux-cosmo-objdump" ]; then
OBJDUMP="$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-objdump" OBJDUMP="$COSMO/.cosmocc/3.2/bin/$1-linux-cosmo-objdump"
elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-musl-objdump" ]; then elif [ -x "$COSMO/.cosmocc/3.2/bin/$1-linux-musl-objdump" ]; then
OBJDUMP="$COSMO/o/third_party/gcc/bin/$1-linux-musl-objdump" OBJDUMP="$COSMO/.cosmocc/3.2/bin/$1-linux-musl-objdump"
else else
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2 echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
exit 1 exit 1

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #

View file

@ -1,5 +1,5 @@
#-*-mode:sed;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:sed;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: et ft=sed ts=8 tw=8 fenc=utf-8 :vi─────────────────┘ #── vi: et ft=sed ts=8 sw=8 fenc=utf-8 :vi ────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #
@ -40,6 +40,9 @@ o/$(MODE)/%.h: %.c
o/$(MODE)/%.o: %.cc o/$(MODE)/%.o: %.cc
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.o: %.cpp
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.lds: %.lds o/$(MODE)/%.lds: %.lds
@$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $< @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<

View file

@ -1,9 +1,8 @@
#!/bin/sh #!/bin/sh
if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then UNAMEM=$(uname -m)
if [ ! -f o/third_party/qemu/qemu-aarch64 ]; then UNAMES=$(uname -s)
make -j8 o/third_party/qemu/qemu-aarch64 if [ x"$UNAMES" = x"Darwin" ] && [ x"$UNAMEM" = x"arm64" ]; then
fi exec ape "$@"
exec o/third_party/qemu/qemu-aarch64 "$@"
else else
exec "$@" exec "$@"
fi fi

443
build/sha256sum.c Normal file
View file

@ -0,0 +1,443 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et 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 <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// this file should not have dependencies, because everything will be
// re-downloaded if the o/tool/sha256sum artifact becomes invalidated
#define PROG "sha256sum"
#define USAGE \
"\
Usage: " PROG " [-?hbctw] [PATH...]\n\
-h help\n\
-c check mode\n\
-b binary mode\n\
-t textual mode\n\
-w warning mode\n"
#define ROTR(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define EP1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SIG0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3))
#define SIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10))
struct Sha256Ctx {
uint8_t data[64];
uint32_t datalen;
uint64_t bitlen;
uint32_t state[8];
};
static const uint32_t kSha256Tab[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, //
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, //
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, //
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, //
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, //
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, //
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, //
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, //
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, //
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, //
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, //
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, //
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, //
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, //
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, //
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, //
};
static bool g_warn;
static char g_mode;
static bool g_check;
static int g_mismatches;
static void Sha256Transform(uint32_t state[8], const uint8_t data[64]) {
unsigned i;
uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64];
for (i = 0; i < 16; ++i, data += 4) {
m[i] = (uint32_t)data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
}
for (; i < 64; ++i) {
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
}
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e, f, g) + kSha256Tab[i] + m[i];
t2 = EP0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
}
static void Sha256Init(struct Sha256Ctx *ctx) {
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
static void Sha256Update(struct Sha256Ctx *ctx, const uint8_t *data,
long size) {
long i;
for (i = 0; i < size; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
Sha256Transform(ctx->state, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
static void Sha256Final(struct Sha256Ctx *ctx, uint8_t *hash) {
long i;
i = ctx->datalen;
ctx->data[i++] = 0x80;
if (ctx->datalen < 56) {
memset(ctx->data + i, 0, 56 - i);
} else {
memset(ctx->data + i, 0, 64 - i);
Sha256Transform(ctx->state, ctx->data);
memset(ctx->data, 0, 56);
}
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
Sha256Transform(ctx->state, ctx->data);
for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0xff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0xff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0xff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0xff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0xff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0xff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0xff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0xff;
}
}
static char *FormatUint32(char *p, uint32_t x) {
char t;
size_t i, a, b;
i = 0;
do {
p[i++] = x % 10 + '0';
x = x / 10;
} while (x > 0);
p[i] = '\0';
if (i) {
for (a = 0, b = i - 1; a < b; ++a, --b) {
t = p[a];
p[a] = p[b];
p[b] = t;
}
}
return p + i;
}
static char *FormatInt32(char *p, int32_t x) {
if (x < 0) *p++ = '-', x = -(uint32_t)x;
return FormatUint32(p, x);
}
static size_t StrCat(char *dst, const char *src, size_t dsize) {
size_t m, n = dsize;
const char *p = dst;
const char *q = src;
while (n-- != 0 && *dst != '\0') dst++;
m = dst - p;
n = dsize - m;
if (n-- == 0) {
return m + strlen(src);
}
while (*src != '\0') {
if (n != 0) {
*dst++ = *src;
n--;
}
src++;
}
*dst = '\0';
return m + (src - q);
}
static void GetOpts(int argc, char *argv[]) {
int opt;
g_mode = ' ';
while ((opt = getopt(argc, argv, "?hbctw")) != -1) {
switch (opt) {
case 'w':
g_warn = true;
break;
case 'c':
g_check = true;
break;
case 't':
g_mode = ' ';
break;
case 'b':
g_mode = '*';
break;
case 'h':
case '?':
(void)write(1, USAGE, sizeof(USAGE) - 1);
exit(0);
default:
(void)write(2, USAGE, sizeof(USAGE) - 1);
exit(64);
}
}
}
static void Write(int fd, const char *s, ...) {
va_list va;
char buf[512];
buf[0] = 0;
va_start(va, s);
do {
StrCat(buf, s, sizeof(buf));
} while ((s = va_arg(va, const char *)));
va_end(va);
(void)write(fd, buf, strlen(buf));
}
static bool IsModeCharacter(char c) {
switch (c) {
case ' ':
case '*':
return true;
default:
return false;
}
}
static bool IsSupportedPath(const char *path) {
size_t i;
for (i = 0;; ++i) {
switch (path[i]) {
case 0:
if (i) return true;
// fallthrough
case '\r':
case '\n':
case '\\':
Write(2, PROG, ": ", path, ": unsupported path\n", NULL);
return false;
default:
break;
}
}
}
static bool GetDigest(const char *path, FILE *f, uint8_t digest[32]) {
size_t got;
uint8_t buf[512];
struct Sha256Ctx ctx;
Sha256Init(&ctx);
while ((got = fread(buf, 1, sizeof(buf), f))) {
Sha256Update(&ctx, buf, got);
}
if (ferror(f)) {
Write(2, PROG, ": ", path, ": ", strerror(errno), "\n", NULL);
return false;
}
Sha256Final(&ctx, digest);
return true;
}
static char *CopyHex(char *s, const void *p, size_t n) {
const char *d, *e;
for (d = (const char *)p, e = d + n; d < e; ++d) {
*s++ = "0123456789abcdef"[(*d >> 4) & 15];
*s++ = "0123456789abcdef"[(*d >> 0) & 15];
}
*s = 0;
return s;
}
static bool ProduceDigest(const char *path, FILE *f) {
char hexdigest[65];
char mode[2] = {g_mode};
unsigned char digest[32];
if (!IsSupportedPath(path)) return false;
if (!GetDigest(path, f, digest)) return false;
CopyHex(hexdigest, digest, 32);
Write(1, hexdigest, " ", mode, path, "\n", NULL);
return true;
}
static char *Chomp(char *line) {
size_t i;
if (line) {
for (i = strlen(line); i--;) {
if (line[i] == '\r' || line[i] == '\n') {
line[i] = '\0';
} else {
break;
}
}
}
return line;
}
static int HexToInt(int c) {
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('a' <= c && c <= 'f') {
return c - 'a' + 10;
} else if ('A' <= c && c <= 'F') {
return c - 'A' + 10;
} else {
return -1;
}
}
static bool CheckDigests(const char *path, FILE *f) {
FILE *f2;
bool k = true;
int a, b, i, line;
const char *path2, *status;
uint8_t wantdigest[32], gotdigest[32];
char buf[64 + 2 + PATH_MAX + 1 + 1], *p;
for (line = 0; fgets(buf, sizeof(buf), f); ++line) {
if (!*Chomp(buf)) continue;
for (p = buf, i = 0; i < 32; ++i) {
if ((a = HexToInt(*p++ & 255)) == -1) goto InvalidLine;
if ((b = HexToInt(*p++ & 255)) == -1) goto InvalidLine;
wantdigest[i] = a << 4 | b;
}
if (*p++ != ' ') goto InvalidLine;
if (!IsModeCharacter(*p++)) goto InvalidLine;
path2 = p;
if (!*path2) goto InvalidLine;
if (!IsSupportedPath(path2)) continue;
if ((f2 = fopen(path2, "rb"))) {
if (GetDigest(path2, f2, gotdigest)) {
if (!memcmp(wantdigest, gotdigest, 32)) {
status = "OK";
} else {
status = "FAILED";
++g_mismatches;
k = false;
}
Write(1, path2, ": ", status, "\n", NULL);
} else {
k = false;
}
fclose(f2);
} else {
Write(2, PROG, ": ", path2, ": ", strerror(errno), "\n", NULL);
k = false;
}
continue;
InvalidLine:
if (g_warn) {
char linestr[12];
FormatInt32(linestr, line + 1);
Write(2, PROG, ": ", path, ":", linestr, ": ",
"improperly formatted checksum line", "\n", NULL);
}
}
if (ferror(f)) {
Write(2, PROG, ": ", path, ": ", strerror(errno), "\n", NULL);
k = false;
}
return k;
}
static bool Process(const char *path, FILE *f) {
if (g_check) {
return CheckDigests(path, f);
} else {
return ProduceDigest(path, f);
}
}
int main(int argc, char *argv[]) {
int i;
FILE *f;
bool k = true;
GetOpts(argc, argv);
if (optind == argc) {
f = stdin;
k &= Process("-", f);
} else {
for (i = optind; i < argc; ++i) {
if ((f = fopen(argv[i], "rb"))) {
k &= Process(argv[i], f);
fclose(f);
} else {
Write(2, PROG, ": ", argv[i], ": ", strerror(errno), "\n", NULL);
k = false;
}
}
}
if (g_mismatches) {
char ibuf[12];
FormatInt32(ibuf, g_mismatches);
Write(2, PROG, ": WARNING: ", ibuf, " computed checksum did NOT match\n",
NULL);
}
return !k;
}

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
.PHONY: o/$(MODE)/dsp .PHONY: o/$(MODE)/dsp
o/$(MODE)/dsp: o/$(MODE)/dsp/core \ o/$(MODE)/dsp: o/$(MODE)/dsp/core \

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
PKGS += DSP_BMP PKGS += DSP_BMP

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
PKGS += DSP_CORE PKGS += DSP_CORE

View file

@ -9,8 +9,9 @@ int mulaw(int);
int unmulaw(int); int unmulaw(int);
void *double2byte(long, const void *, double, double) vallocesque; void *double2byte(long, const void *, double, double) vallocesque;
void *byte2double(long, const void *, double, double) vallocesque; void *byte2double(long, const void *, double, double) vallocesque;
void *dct(float[8][8], float, float, float, float, float); void *dct(float[restrict hasatleast 8][8], unsigned,
void *dctjpeg(float[8][8]); float, float, float, float, float);
void *dctjpeg(float[restrict hasatleast 8][8], unsigned);
double det3(const double[3][3]) nosideeffect; double det3(const double[3][3]) nosideeffect;
void *inv3(double[restrict 3][3], const double[restrict 3][3], double); void *inv3(double[restrict 3][3], const double[restrict 3][3], double);
void *matmul3(double[restrict 3][3], const double[3][3], const double[3][3]); void *matmul3(double[restrict 3][3], const double[3][3], const double[3][3]);

View file

@ -18,40 +18,40 @@
*/ */
#include "dsp/core/core.h" #include "dsp/core/core.h"
#define DCT(A, B, C, D, E, F, G, H, T, C0, C1, C2, C3, C4) \ #define DCT(A, B, C, D, E, F, G, H, T, C0, C1, C2, C3, C4) \
do { \ do { \
T z1, z2, z3, z4, z5, z11, z13; \ T z1, z2, z3, z4, z5, z11, z13; \
T t0, t1, t2, t3, t4, t5, t6, t7, t10, t11, t12, t13; \ T t0, t1, t2, t3, t4, t5, t6, t7, t10, t11, t12, t13; \
t0 = A + H; \ t0 = A + H; \
t7 = A - H; \ t7 = A - H; \
t1 = B + G; \ t1 = B + G; \
t6 = B - G; \ t6 = B - G; \
t2 = C + F; \ t2 = C + F; \
t5 = C - F; \ t5 = C - F; \
t3 = D + E; \ t3 = D + E; \
t4 = D - E; \ t4 = D - E; \
t10 = t0 + t3; \ t10 = t0 + t3; \
t13 = t0 - t3; \ t13 = t0 - t3; \
t11 = t1 + t2; \ t11 = t1 + t2; \
t12 = t1 - t2; \ t12 = t1 - t2; \
A = t10 + t11; \ A = t10 + t11; \
E = t10 - t11; \ E = t10 - t11; \
z1 = (t12 + t13) * C0; \ z1 = (t12 + t13) * C0; \
C = t13 + z1; \ C = t13 + z1; \
G = t13 - z1; \ G = t13 - z1; \
t10 = t4 + t5; \ t10 = t4 + t5; \
t11 = t5 + t6; \ t11 = t5 + t6; \
t12 = t6 + t7; \ t12 = t6 + t7; \
z5 = (t10 - t12) * C1; \ z5 = (t10 - t12) * C1; \
z2 = t10 * C2 + z5; \ z2 = t10 * C2 + z5; \
z4 = t12 * C3 + z5; \ z4 = t12 * C3 + z5; \
z3 = t11 * C4; \ z3 = t11 * C4; \
z11 = t7 + z3; \ z11 = t7 + z3; \
z13 = t7 - z3; \ z13 = t7 - z3; \
F = z13 + z2; \ F = z13 + z2; \
D = z13 - z2; \ D = z13 - z2; \
B = z11 + z4; \ B = z11 + z4; \
H = z11 - z4; \ H = z11 - z4; \
} while (0) } while (0)
/** /**
@ -65,20 +65,21 @@
* *
* @cost ~100ns * @cost ~100ns
*/ */
void *dct(float M[8][8], float c0, float c1, float c2, float c3, float c4) { void *dct(float M[restrict hasatleast 8][8], unsigned stride,
float c0, float c1, float c2, float c3, float c4) {
unsigned y, x; unsigned y, x;
for (y = 0; y < 8; ++y) { for (y = 0; y < stride * 8; y += stride) {
DCT(M[y][0], M[y][1], M[y][2], M[y][3], M[y][4], M[y][5], M[y][6], M[y][7], DCT(M[y][0], M[y][1], M[y][2], M[y][3], M[y][4], M[y][5], M[y][6], M[y][7],
float, c0, c1, c2, c3, c4); float, c0, c1, c2, c3, c4);
} }
for (x = 0; x < 8; ++x) { for (x = 0; x < stride * 8; x += stride) {
DCT(M[0][x], M[1][x], M[2][x], M[3][x], M[4][x], M[5][x], M[6][x], M[7][x], DCT(M[0][x], M[1][x], M[2][x], M[3][x], M[4][x], M[5][x], M[6][x], M[7][x],
float, c0, c1, c2, c3, c4); float, c0, c1, c2, c3, c4);
} }
return M; return M;
} }
void *dctjpeg(float M[8][8]) { void *dctjpeg(float M[restrict hasatleast 8][8], unsigned stride) {
return dct(M, .707106781f, .382683433f, .541196100f, 1.306562965f, return dct(M, stride, .707106781f, .382683433f, .541196100f, 1.306562965f,
.707106781f); .707106781f);
} }

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
PKGS += DSP_MPEG PKGS += DSP_MPEG

View file

@ -3,8 +3,6 @@
#include "dsp/mpeg/mpeg.h" #include "dsp/mpeg/mpeg.h"
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
struct FILE;
enum plm_buffer_mode { enum plm_buffer_mode {
PLM_BUFFER_MODE_FILE, PLM_BUFFER_MODE_FILE,
PLM_BUFFER_MODE_FIXED_MEM, PLM_BUFFER_MODE_FIXED_MEM,
@ -17,7 +15,7 @@ typedef struct plm_buffer_t {
unsigned length; unsigned length;
int free_when_done; int free_when_done;
int close_when_done; int close_when_done;
struct FILE *fh; FILE *fh;
plm_buffer_load_callback load_callback; plm_buffer_load_callback load_callback;
void *load_callback_user_data; void *load_callback_user_data;
unsigned char *bytes; unsigned char *bytes;

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2020 Justine Alexandra Roberts Tunney

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│
vi: set noet ft=c ts=4 sw=4 fenc=utf-8 :vi vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi
PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer
Dominic Szablewski - https://phoboslab.org │ Dominic Szablewski - https://phoboslab.org │

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│
vi: set noet ft=c ts=4 sw=4 fenc=utf-8 :vi vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi
PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer
Dominic Szablewski - https://phoboslab.org │ Dominic Szablewski - https://phoboslab.org │

View file

@ -1,9 +1,8 @@
#ifndef COSMOPOLITAN_DSP_MPEG_MPEG_H_ #ifndef COSMOPOLITAN_DSP_MPEG_MPEG_H_
#define COSMOPOLITAN_DSP_MPEG_MPEG_H_ #define COSMOPOLITAN_DSP_MPEG_MPEG_H_
#include "libc/stdio/stdio.h"
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
struct FILE;
typedef struct plm_t plm_t; typedef struct plm_t plm_t;
typedef struct plm_buffer_t plm_buffer_t; typedef struct plm_buffer_t plm_buffer_t;
typedef struct plm_demux_t plm_demux_t; typedef struct plm_demux_t plm_demux_t;
@ -112,7 +111,7 @@ plm_t *plm_create_with_filename(const char *filename);
* to let plmpeg call fclose() on the handle when plm_destroy() is * to let plmpeg call fclose() on the handle when plm_destroy() is
* called. * called.
*/ */
plm_t *plm_create_with_file(struct FILE *fh, int close_when_done); plm_t *plm_create_with_file(FILE *fh, int close_when_done);
/** /**
* Create a plmpeg instance with pointer to memory as source. This assumes the * Create a plmpeg instance with pointer to memory as source. This assumes the
@ -257,7 +256,7 @@ plm_buffer_t *plm_buffer_create_with_filename(const char *filename);
* to let plmpeg call fclose() on the handle when plm_destroy() is * to let plmpeg call fclose() on the handle when plm_destroy() is
* called. * called.
*/ */
plm_buffer_t *plm_buffer_create_with_file(struct FILE *fh, int close_when_done); plm_buffer_t *plm_buffer_create_with_file(FILE *fh, int close_when_done);
/** /**
* Create a buffer instance with a pointer to memory as source. This assumes * Create a buffer instance with a pointer to memory as source. This assumes

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│
vi: set noet ft=c ts=4 sw=4 fenc=utf-8 :vi vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi
PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer
Dominic Szablewski - https://phoboslab.org │ Dominic Szablewski - https://phoboslab.org │

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│
vi: set noet ft=c ts=4 sw=4 fenc=utf-8 :vi vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi
PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer
Dominic Szablewski - https://phoboslab.org │ Dominic Szablewski - https://phoboslab.org │

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
PKGS += DSP_SCALE PKGS += DSP_SCALE

View file

@ -27,7 +27,7 @@
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/math.h" #include "libc/math.h"
#include "libc/mem/gc.internal.h" #include "libc/mem/gc.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
PKGS += DSP_TTY PKGS += DSP_TTY

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2020 Justine Alexandra Roberts Tunney

View file

@ -18,7 +18,7 @@
*/ */
#include "dsp/tty/tty.h" #include "dsp/tty/tty.h"
#include "libc/mem/arraylist2.internal.h" #include "libc/mem/arraylist2.internal.h"
#include "libc/mem/gc.internal.h" #include "libc/mem/gc.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/x/x.h" #include "libc/x/x.h"

View file

@ -5,7 +5,6 @@
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
struct FILE;
struct termios; struct termios;
struct TtyIdent { struct TtyIdent {

View file

@ -25,7 +25,7 @@
#include "libc/calls/ucontext.h" #include "libc/calls/ucontext.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/gc.internal.h" #include "libc/mem/gc.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/fileno.h"

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2020 Justine Alexandra Roberts Tunney

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2020 Justine Alexandra Roberts Tunney

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
PKGS += EXAMPLES PKGS += EXAMPLES
@ -44,7 +44,6 @@ EXAMPLES_DIRECTDEPS = \
DSP_TTY \ DSP_TTY \
LIBC_CALLS \ LIBC_CALLS \
LIBC_DLOPEN \ LIBC_DLOPEN \
LIBC_DNS \
LIBC_FMT \ LIBC_FMT \
LIBC_INTRIN \ LIBC_INTRIN \
LIBC_IRQ \ LIBC_IRQ \
@ -86,7 +85,6 @@ EXAMPLES_DIRECTDEPS = \
THIRD_PARTY_MUSL \ THIRD_PARTY_MUSL \
THIRD_PARTY_NSYNC \ THIRD_PARTY_NSYNC \
THIRD_PARTY_NSYNC_MEM \ THIRD_PARTY_NSYNC_MEM \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_SED \ THIRD_PARTY_SED \
THIRD_PARTY_STB \ THIRD_PARTY_STB \
THIRD_PARTY_TR \ THIRD_PARTY_TR \
@ -154,7 +152,6 @@ o/$(MODE)/examples/picol.com.dbg: \
$(APE_NO_MODIFY_SELF) $(APE_NO_MODIFY_SELF)
@$(APELINK) @$(APELINK)
o/$(MODE)/examples/nesemu1.o: private QUOTA += -M512m
o/$(MODE)/usr/share/dict/words.zip.o: private ZIPOBJ_FLAGS += -C2 o/$(MODE)/usr/share/dict/words.zip.o: private ZIPOBJ_FLAGS += -C2
$(EXAMPLES_OBJS): examples/BUILD.mk $(EXAMPLES_OBJS): examples/BUILD.mk

23
examples/crashreport2.cc Normal file
View file

@ -0,0 +1,23 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/math.h"
#include "libc/runtime/runtime.h"
void crash(long x0, long x1, long x2, //
double v0, double v1, double v2) {
__builtin_trap();
}
void (*pCrash)(long, long, long, double, double, double) = crash;
int main(int argc, char *argv[]) {
ShowCrashReports();
pCrash(1, 2, 3, NAN, NAN, NAN);
}

View file

@ -2,9 +2,9 @@
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
printf("%s\n", argv[0]); fprintf(stderr, "%s (%s)\n", argv[0], GetProgramExecutableName());
for (char **p = environ; *p; ++p) { for (char **p = environ; *p; ++p) {
printf(" %s\n", *p); printf("%s\n", *p);
} }
return 0; return 0;
} }

View file

@ -285,7 +285,7 @@ int main(int argc, char *argv[]) {
// print all the ips that 0.0.0.0 would bind // print all the ips that 0.0.0.0 would bind
// Cosmo's GetHostIps() API is much easier than ioctl(SIOCGIFCONF) // Cosmo's GetHostIps() API is much easier than ioctl(SIOCGIFCONF)
uint32_t *hostips; uint32_t *hostips;
for (hostips = _gc(GetHostIps()), i = 0; hostips[i]; ++i) { for (hostips = gc(GetHostIps()), i = 0; hostips[i]; ++i) {
kprintf("listening on http://%hhu.%hhu.%hhu.%hhu:%hu\n", hostips[i] >> 24, kprintf("listening on http://%hhu.%hhu.%hhu.%hhu:%hu\n", hostips[i] >> 24,
hostips[i] >> 16, hostips[i] >> 8, hostips[i], PORT); hostips[i] >> 16, hostips[i] >> 8, hostips[i], PORT);
} }
@ -339,7 +339,7 @@ int main(int argc, char *argv[]) {
unassert(!pthread_attr_setguardsize(&attr, pagesz)); unassert(!pthread_attr_setguardsize(&attr, pagesz));
unassert(!pthread_attr_setsigmask_np(&attr, &block)); unassert(!pthread_attr_setsigmask_np(&attr, &block));
unassert(!pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0)); unassert(!pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0));
pthread_t *th = _gc(calloc(threads, sizeof(pthread_t))); pthread_t *th = gc(calloc(threads, sizeof(pthread_t)));
for (i = 0; i < threads; ++i) { for (i = 0; i < threads; ++i) {
int rc; int rc;
++a_workers; ++a_workers;

View file

@ -50,7 +50,7 @@ void List(const char *path) {
if (strcmp(path, ".") == 0) { if (strcmp(path, ".") == 0) {
vpath = ""; vpath = "";
} else if (!endswith(path, "/")) { } else if (!endswith(path, "/")) {
vpath = _gc(xasprintf("%s/", path)); vpath = gc(xasprintf("%s/", path));
} else { } else {
vpath = path; vpath = path;
} }

View file

@ -8,7 +8,6 @@
*/ */
#endif #endif
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/dns/dns.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
@ -26,6 +25,7 @@
#include "libc/sysv/consts/sock.h" #include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/sol.h" #include "libc/sysv/consts/sol.h"
#include "third_party/getopt/getopt.internal.h" #include "third_party/getopt/getopt.internal.h"
#include "third_party/musl/netdb.h"
/** /**
* @fileoverview netcat clone * @fileoverview netcat clone
@ -60,9 +60,7 @@ int main(int argc, char *argv[]) {
halfclose = false; halfclose = false;
break; break;
case 'h': case 'h':
fputs("Usage: ", stdout); tinyprint(1, "Usage: ", argv[0], " [-hH] IP PORT\n", NULL);
fputs(argv[0], stdout);
fputs(" [-hH] IP PORT\n", stdout);
exit(0); exit(0);
default: default:
fprintf(stderr, "bad option %d\n", opt); fprintf(stderr, "bad option %d\n", opt);
@ -76,17 +74,9 @@ int main(int argc, char *argv[]) {
host = argv[optind + 0]; host = argv[optind + 0];
port = argv[optind + 1]; port = argv[optind + 1];
switch ((rc = getaddrinfo(host, port, &hint, &ai))) { if ((rc = getaddrinfo(host, port, &hint, &ai))) {
case EAI_SUCCESS: tinyprint(2, host, ": ", gai_strerror(rc), "\n", NULL);
break; exit(1);
case EAI_SYSTEM:
perror("getaddrinfo");
exit(1);
default:
fputs("EAI_", stderr);
fputs(gai_strerror(rc), stderr);
fputs("\n", stderr);
exit(1);
} }
if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1) { if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1) {
@ -95,12 +85,12 @@ int main(int argc, char *argv[]) {
} }
if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == -1) { if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == -1) {
perror("setsockopt(SO_LINGER)"); perror("SO_LINGER");
exit(1); exit(1);
} }
if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
perror("connect"); perror(host);
exit(1); exit(1);
} }

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Copyright (c) 2010, 2012 David E. O'Brien Copyright (c) 2010, 2012 David E. O'Brien
Copyright (c) 1980, 1992, 1993 Copyright (c) 1980, 1992, 1993

View file

@ -80,10 +80,10 @@ void PrintFileMetadata(const char *pathname, struct stat *st) {
DescribeFileType(st->st_mode), "owner id", st->st_uid, "group id", DescribeFileType(st->st_mode), "owner id", st->st_uid, "group id",
st->st_gid, "flags", st->st_flags, "gen", st->st_gen, st->st_gid, "flags", st->st_flags, "gen", st->st_gen,
"device id (if special)", st->st_rdev, "block size", st->st_blksize, "device id (if special)", st->st_rdev, "block size", st->st_blksize,
"access time", _gc(xiso8601(&st->st_atim)), "modified time", "access time", gc(xiso8601(&st->st_atim)), "modified time",
_gc(xiso8601(&st->st_mtim)), "c[omplicated]time", gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
_gc(xiso8601(&st->st_ctim)), "birthtime", gc(xiso8601(&st->st_ctim)), "birthtime",
_gc(xiso8601(&st->st_birthtim))); gc(xiso8601(&st->st_birthtim)));
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {

View file

@ -128,7 +128,7 @@
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/alg.h" #include "libc/mem/alg.h"
#include "libc/mem/alloca.h" #include "libc/mem/alloca.h"
#include "libc/mem/gc.internal.h" #include "libc/mem/gc.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/paths.h" #include "libc/paths.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -157,14 +157,14 @@
/* /*
* The follow should be set to reflect the type of system you have: * The follow should be set to reflect the type of system you have:
* JOBS -> 1 if you have Berkeley job control, 0 otherwise. * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
* SHORTNAMES -> 1 if your linker cannot handle long names. * SHORTNAMES -> 1 if your linker cannot handle long names.
* define BSD if you are running 4.2 BSD or later. * define BSD if you are running 4.2 BSD or later.
* define SYSV if you are running under System V. * define SYSV if you are running under System V.
* define DEBUG=1 to compile in debugging ('set -o debug' to turn on) * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
* define DEBUG=2 to compile in and turn on debugging. * define DEBUG=2 to compile in and turn on debugging.
* define DO_SHAREDVFORK to indicate that vfork(2) shares its address * define DO_SHAREDVFORK to indicate that vfork(2) shares its address
* with its parent. * with its parent.
* *
* When debugging is on, debugging info will be written to ./trace and * When debugging is on, debugging info will be written to ./trace and
* a quit signal will generate a core dump. * a quit signal will generate a core dump.
@ -6604,10 +6604,10 @@ static struct job *growjobtab(void) {
* own process group. Jp is a job structure that the job is to be added to. * own process group. Jp is a job structure that the job is to be added to.
* N is the command that will be evaluated by the child. Both jp and n may * N is the command that will be evaluated by the child. Both jp and n may
* be NULL. The mode parameter can be one of the following: * be NULL. The mode parameter can be one of the following:
* FORK_FG - Fork off a foreground process. * FORK_FG - Fork off a foreground process.
* FORK_BG - Fork off a background process. * FORK_BG - Fork off a background process.
* FORK_NOJOB - Like FORK_FG, but don't give the process its own * FORK_NOJOB - Like FORK_FG, but don't give the process its own
* process group even if job control is on. * process group even if job control is on.
* *
* When job control is turned off, background processes have their standard * When job control is turned off, background processes have their standard
* input redirected to /dev/null (except for the second and later processes * input redirected to /dev/null (except for the second and later processes
@ -8403,10 +8403,10 @@ static void nlnoprompt(void) {
/* /*
* Read the next input token. * Read the next input token.
* If the token is a word, we set backquotelist to the list of cmds in * If the token is a word, we set backquotelist to the list of cmds in
* backquotes. We set quoteflag to true if any part of the word was * backquotes. We set quoteflag to true if any part of the word was
* quoted. * quoted.
* If the token is TREDIR, then we set redirnode to a structure containing * If the token is TREDIR, then we set redirnode to a structure containing
* the redirection. * the redirection.
* *
* [Change comment: here documents and internal procedures] * [Change comment: here documents and internal procedures]
* [Readtoken shouldn't have any arguments. Perhaps we should make the * [Readtoken shouldn't have any arguments. Perhaps we should make the
@ -9767,7 +9767,7 @@ out:
/* /*
* Print SysV echo(1) style escape string * Print SysV echo(1) style escape string
* Halts processing string if a \c escape is encountered. * Halts processing string if a \c escape is encountered.
*/ */
static int conv_escape_str(char *str, char **sp) { static int conv_escape_str(char *str, char **sp) {
int c; int c;
@ -9941,10 +9941,10 @@ static int echocmd(int argc, char **argv) {
*/ */
/* test(1) accepts the following grammar: /* test(1) accepts the following grammar:
oexpr ::= aexpr | aexpr "-o" oexpr ; oexpr ::= aexpr | aexpr "-o" oexpr ;
aexpr ::= nexpr | nexpr "-a" aexpr ; aexpr ::= nexpr | nexpr "-a" aexpr ;
nexpr ::= primary | "!" primary nexpr ::= primary | "!" primary
primary ::= unary-operator operand primary ::= unary-operator operand
| operand binary-operator operand | operand binary-operator operand
| operand | operand
| "(" oexpr ")" | "(" oexpr ")"

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Copyright (c) 1980, 1993 Copyright (c) 1980, 1993
The Regents of the University of California. All rights reserved. The Regents of the University of California. All rights reserved.
@ -30,12 +30,13 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/weirdtypes.h" #include "libc/calls/weirdtypes.h"
#include "libc/dns/dns.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/log/bsd.h" #include "libc/log/bsd.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/pollfd.h" #include "libc/sock/struct/pollfd.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/af.h" #include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ex.h" #include "libc/sysv/consts/ex.h"
@ -44,6 +45,7 @@
#include "libc/sysv/consts/poll.h" #include "libc/sysv/consts/poll.h"
#include "libc/sysv/consts/sock.h" #include "libc/sysv/consts/sock.h"
#include "third_party/getopt/getopt.internal.h" #include "third_party/getopt/getopt.internal.h"
#include "third_party/musl/netdb.h"
// clang-format off // clang-format off
asm(".ident\t\"\\n\\n\ asm(".ident\t\"\\n\\n\

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
PKGS += LIBC PKGS += LIBC
@ -142,6 +142,9 @@ libc/isystem/nsync_once.h \
libc/isystem/nsync_time.h \ libc/isystem/nsync_time.h \
libc/isystem/nsync_waiter.h \ libc/isystem/nsync_waiter.h \
libc/isystem/numeric \ libc/isystem/numeric \
libc/isystem/omp-tools.h \
libc/isystem/omp.h \
libc/isystem/ompx.h \
libc/isystem/optional \ libc/isystem/optional \
libc/isystem/ostream \ libc/isystem/ostream \
libc/isystem/paths.h \ libc/isystem/paths.h \
@ -164,6 +167,7 @@ libc/isystem/semaphore.h \
libc/isystem/set \ libc/isystem/set \
libc/isystem/setjmp.h \ libc/isystem/setjmp.h \
libc/isystem/sgxintrin.h \ libc/isystem/sgxintrin.h \
libc/isystem/shadow.h \
libc/isystem/shared_mutex \ libc/isystem/shared_mutex \
libc/isystem/signal.h \ libc/isystem/signal.h \
libc/isystem/smmintrin.h \ libc/isystem/smmintrin.h \
@ -250,6 +254,7 @@ libc/isystem/uio.h \
libc/isystem/unistd.h \ libc/isystem/unistd.h \
libc/isystem/unordered_map \ libc/isystem/unordered_map \
libc/isystem/unordered_set \ libc/isystem/unordered_set \
libc/isystem/unwind.h \
libc/isystem/utility \ libc/isystem/utility \
libc/isystem/utime.h \ libc/isystem/utime.h \
libc/isystem/utmp.h \ libc/isystem/utmp.h \
@ -272,11 +277,12 @@ LIBC_INCS = $(filter %.inc,$(LIBC_FILES))
LIBC_CHECKS = $(LIBC_HDRS_H:%=o/$(MODE)/%.ok) LIBC_CHECKS = $(LIBC_HDRS_H:%=o/$(MODE)/%.ok)
LIBC_FILES := $(wildcard libc/*) LIBC_FILES := $(wildcard libc/*)
o/$(MODE)/libc/isystem/ompx.h.ok: private CPPFLAGS += -Wno-unknown-pragmas
.PHONY: o/$(MODE)/libc .PHONY: o/$(MODE)/libc
o/$(MODE)/libc: o/$(MODE)/libc/calls \ o/$(MODE)/libc: o/$(MODE)/libc/calls \
o/$(MODE)/libc/crt \ o/$(MODE)/libc/crt \
o/$(MODE)/libc/dlopen \ o/$(MODE)/libc/dlopen \
o/$(MODE)/libc/dns \
o/$(MODE)/libc/elf \ o/$(MODE)/libc/elf \
o/$(MODE)/libc/fmt \ o/$(MODE)/libc/fmt \
o/$(MODE)/libc/intrin \ o/$(MODE)/libc/intrin \

View file

@ -14,8 +14,8 @@
#define _ASSERT_H #define _ASSERT_H
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
void __assert_fail(const char *, const char *, int); void __assert_fail(const char *, const char *, int) libcesque;
void unassert(const char *, const char *, int); void unassert(const char *, const char *, int) libcesque;
#ifdef NDEBUG #ifdef NDEBUG
#define assert(x) ((void)0) #define assert(x) ((void)0)

View file

@ -1,5 +1,5 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ #── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
# #
# SYNOPSIS # SYNOPSIS
# #

View file

@ -72,184 +72,184 @@ COSMOPOLITAN_C_START_
typedef int sig_atomic_t; typedef int sig_atomic_t;
bool32 isatty(int); bool32 isatty(int) libcesque;
char *getcwd(char *, size_t); char *getcwd(char *, size_t) dontthrow;
char *realpath(const char *, char *) __wur; char *realpath(const char *, char *) libcesque __wur;
char *ttyname(int); char *ttyname(int) libcesque;
int access(const char *, int) dontthrow; int access(const char *, int) libcesque;
int chdir(const char *); int chdir(const char *) libcesque;
int chmod(const char *, unsigned); int chmod(const char *, unsigned) libcesque;
int chown(const char *, unsigned, unsigned); int chown(const char *, unsigned, unsigned) libcesque;
int chroot(const char *); int chroot(const char *) libcesque;
int close(int); int close(int) libcesque;
int close_range(unsigned, unsigned, unsigned); int close_range(unsigned, unsigned, unsigned) libcesque;
int closefrom(int); int closefrom(int) libcesque;
int creat(const char *, unsigned); int creat(const char *, unsigned) libcesque;
int dup(int); int dup(int) libcesque;
int dup2(int, int); int dup2(int, int) libcesque;
int dup3(int, int, int); int dup3(int, int, int) libcesque;
int execl(const char *, const char *, ...) nullterminated(); int execl(const char *, const char *, ...) nullterminated() libcesque;
int execle(const char *, const char *, ...) nullterminated((1)); int execle(const char *, const char *, ...) nullterminated((1)) libcesque;
int execlp(const char *, const char *, ...) nullterminated(); int execlp(const char *, const char *, ...) nullterminated() libcesque;
int execv(const char *, char *const[]); int execv(const char *, char *const[]) libcesque;
int execve(const char *, char *const[], char *const[]); int execve(const char *, char *const[], char *const[]) libcesque;
int execvp(const char *, char *const[]); int execvp(const char *, char *const[]) libcesque;
int faccessat(int, const char *, int, int); int faccessat(int, const char *, int, int) libcesque;
int fchdir(int); int fchdir(int) libcesque;
int fchmod(int, unsigned) dontthrow; int fchmod(int, unsigned) libcesque;
int fchmodat(int, const char *, unsigned, int); int fchmodat(int, const char *, unsigned, int) libcesque;
int fchown(int, unsigned, unsigned); int fchown(int, unsigned, unsigned) libcesque;
int fchownat(int, const char *, unsigned, unsigned, int); int fchownat(int, const char *, unsigned, unsigned, int) libcesque;
int fcntl(int, int, ...); int fcntl(int, int, ...) libcesque;
int fdatasync(int); int fdatasync(int) libcesque;
int fexecve(int, char *const[], char *const[]); int fexecve(int, char *const[], char *const[]) libcesque;
int flock(int, int); int flock(int, int) libcesque;
int fork(void); int fork(void) libcesque;
int fsync(int); int fsync(int) libcesque;
int ftruncate(int, int64_t); int ftruncate(int, int64_t) libcesque;
int getdomainname(char *, size_t); int getdomainname(char *, size_t) libcesque;
int getgroups(int, unsigned[]); int getgroups(int, unsigned[]) libcesque;
int gethostname(char *, size_t); int gethostname(char *, size_t) libcesque;
int getloadavg(double *, int); int getloadavg(double *, int) libcesque;
int getpgid(int) libcesque; int getpgid(int) libcesque;
int getpgrp(void) nosideeffect; int getpgrp(void) libcesque nosideeffect;
int getpid(void) nosideeffect libcesque; int getpid(void) libcesque nosideeffect;
int getppid(void); int getppid(void) libcesque;
int getpriority(int, unsigned); int getpriority(int, unsigned) libcesque;
int getsid(int) nosideeffect libcesque; int getsid(int) nosideeffect libcesque;
int ioctl(int, unsigned long, ...); int ioctl(int, unsigned long, ...) libcesque;
int issetugid(void); int issetugid(void) libcesque;
int kill(int, int); int kill(int, int) libcesque;
int killpg(int, int); int killpg(int, int) libcesque;
int lchmod(const char *, unsigned); int lchmod(const char *, unsigned) libcesque;
int lchown(const char *, unsigned, unsigned); int lchown(const char *, unsigned, unsigned) libcesque;
int link(const char *, const char *) dontthrow; int link(const char *, const char *) libcesque;
int linkat(int, const char *, int, const char *, int); int linkat(int, const char *, int, const char *, int) libcesque;
int mincore(void *, size_t, unsigned char *); int mincore(void *, size_t, unsigned char *) libcesque;
int mkdir(const char *, unsigned); int mkdir(const char *, unsigned) libcesque;
int mkdirat(int, const char *, unsigned); int mkdirat(int, const char *, unsigned) libcesque;
int mknod(const char *, unsigned, uint64_t); int mknod(const char *, unsigned, uint64_t) libcesque;
int nice(int); int nice(int) libcesque;
int open(const char *, int, ...); int open(const char *, int, ...) libcesque;
int openat(int, const char *, int, ...); int openat(int, const char *, int, ...) libcesque;
int pause(void); int pause(void) libcesque;
int pipe(int[hasatleast 2]); int pipe(int[hasatleast 2]) libcesque;
int pipe2(int[hasatleast 2], int); int pipe2(int[hasatleast 2], int) libcesque;
int posix_fadvise(int, int64_t, int64_t, int); int posix_fadvise(int, int64_t, int64_t, int) libcesque;
int posix_madvise(void *, uint64_t, int); int posix_madvise(void *, uint64_t, int) libcesque;
int raise(int); int raise(int) libcesque;
int reboot(int); int reboot(int) libcesque;
int remove(const char *); int remove(const char *) libcesque;
int rename(const char *, const char *); int rename(const char *, const char *) libcesque;
int renameat(int, const char *, int, const char *); int renameat(int, const char *, int, const char *) libcesque;
int rmdir(const char *); int rmdir(const char *) libcesque;
int sched_yield(void); int sched_yield(void) libcesque;
int setegid(unsigned); int setegid(unsigned) libcesque;
int seteuid(unsigned); int seteuid(unsigned) libcesque;
int setfsgid(unsigned); int setfsgid(unsigned) libcesque;
int setfsuid(unsigned); int setfsuid(unsigned) libcesque;
int setgid(unsigned); int setgid(unsigned) libcesque;
int setgroups(size_t, const unsigned[]); int setgroups(size_t, const unsigned[]) libcesque;
int setpgid(int, int); int setpgid(int, int) libcesque;
int setpgrp(void); int setpgrp(void) libcesque;
int setpriority(int, unsigned, int); int setpriority(int, unsigned, int) libcesque;
int setregid(unsigned, unsigned); int setregid(unsigned, unsigned) libcesque;
int setreuid(unsigned, unsigned); int setreuid(unsigned, unsigned) libcesque;
int setsid(void); int setsid(void) libcesque;
int setuid(unsigned); int setuid(unsigned) libcesque;
int shm_open(const char *, int, unsigned); int shm_open(const char *, int, unsigned) libcesque;
int shm_unlink(const char *); int shm_unlink(const char *) libcesque;
int sigignore(int); int sigignore(int) libcesque;
int siginterrupt(int, int); int siginterrupt(int, int) libcesque;
int symlink(const char *, const char *); int symlink(const char *, const char *) libcesque;
int symlinkat(const char *, int, const char *); int symlinkat(const char *, int, const char *) libcesque;
int tcgetpgrp(int); int tcgetpgrp(int) libcesque;
int tcsetpgrp(int, int); int tcsetpgrp(int, int) libcesque;
int truncate(const char *, int64_t); int truncate(const char *, int64_t) libcesque;
int ttyname_r(int, char *, size_t); int ttyname_r(int, char *, size_t) libcesque;
int unlink(const char *); int unlink(const char *) libcesque;
int unlinkat(int, const char *, int); int unlinkat(int, const char *, int) libcesque;
int usleep(uint64_t); int usleep(uint64_t) libcesque;
int vfork(void) returnstwice; int vfork(void) libcesque returnstwice;
int wait(int *); int wait(int *) libcesque;
int waitpid(int, int *, int); int waitpid(int, int *, int) libcesque;
int64_t clock(void); int64_t clock(void) libcesque;
int64_t time(int64_t *); int64_t time(int64_t *) libcesque;
ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned); ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned) libcesque;
ssize_t lseek(int, int64_t, int); ssize_t lseek(int, int64_t, int) libcesque;
ssize_t pread(int, void *, size_t, int64_t); ssize_t pread(int, void *, size_t, int64_t) libcesque;
ssize_t pwrite(int, const void *, size_t, int64_t); ssize_t pwrite(int, const void *, size_t, int64_t) libcesque;
ssize_t read(int, void *, size_t); ssize_t read(int, void *, size_t) libcesque;
ssize_t readlink(const char *, char *, size_t); ssize_t readlink(const char *, char *, size_t) libcesque;
ssize_t readlinkat(int, const char *, char *, size_t); ssize_t readlinkat(int, const char *, char *, size_t) libcesque;
ssize_t write(int, const void *, size_t); ssize_t write(int, const void *, size_t) libcesque;
unsigned alarm(unsigned); unsigned alarm(unsigned) libcesque;
unsigned getegid(void) nosideeffect; unsigned getegid(void) libcesque nosideeffect;
unsigned geteuid(void) nosideeffect; unsigned geteuid(void) libcesque nosideeffect;
unsigned getgid(void) nosideeffect; unsigned getgid(void) libcesque nosideeffect;
unsigned getuid(void) libcesque; unsigned getuid(void) libcesque;
unsigned sleep(unsigned); unsigned sleep(unsigned) libcesque;
unsigned ualarm(unsigned, unsigned); unsigned ualarm(unsigned, unsigned) libcesque;
unsigned umask(unsigned); unsigned umask(unsigned) libcesque;
void sync(void); void sync(void) libcesque;
#if defined(_COSMO_SOURCE) || defined(_GNU_SOURCE) #if defined(_COSMO_SOURCE) || defined(_GNU_SOURCE)
int syncfs(int); int syncfs(int) libcesque;
int prctl(int, ...); int prctl(int, ...) libcesque;
int gettid(void) libcesque; int gettid(void) libcesque;
int setresgid(unsigned, unsigned, unsigned); int setresgid(unsigned, unsigned, unsigned) libcesque;
int setresuid(unsigned, unsigned, unsigned); int setresuid(unsigned, unsigned, unsigned) libcesque;
int getresgid(unsigned *, unsigned *, unsigned *); int getresgid(unsigned *, unsigned *, unsigned *) libcesque;
int getresuid(unsigned *, unsigned *, unsigned *); int getresuid(unsigned *, unsigned *, unsigned *) libcesque;
char *get_current_dir_name(void) __wur; char *get_current_dir_name(void) libcesque __wur;
ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned); ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned) libcesque;
int memfd_create(const char *, unsigned int); int memfd_create(const char *, unsigned int) libcesque;
int execvpe(const char *, char *const[], char *const[]); int execvpe(const char *, char *const[], char *const[]) libcesque;
int euidaccess(const char *, int); int euidaccess(const char *, int) libcesque;
int eaccess(const char *, int); int eaccess(const char *, int) libcesque;
int madvise(void *, uint64_t, int); int madvise(void *, uint64_t, int) libcesque;
#endif #endif
#ifdef _COSMO_SOURCE #ifdef _COSMO_SOURCE
bool32 fdexists(int); bool32 fdexists(int) libcesque;
bool32 fileexists(const char *); bool32 fileexists(const char *) libcesque;
bool32 ischardev(int); bool32 ischardev(int) libcesque;
bool32 isdirectory(const char *); bool32 isdirectory(const char *) libcesque;
bool32 isexecutable(const char *); bool32 isexecutable(const char *) libcesque;
bool32 isregularfile(const char *); bool32 isregularfile(const char *) libcesque;
bool32 issymlink(const char *); bool32 issymlink(const char *) libcesque;
char *commandv(const char *, char *, size_t); char *commandv(const char *, char *, size_t) libcesque;
int __getcwd(char *, size_t); int __getcwd(char *, size_t) libcesque;
int clone(void *, void *, size_t, int, void *, void *, void *, void *); int clone(void *, void *, size_t, int, void *, void *, void *, void *);
int fadvise(int, uint64_t, uint64_t, int); int fadvise(int, uint64_t, uint64_t, int) libcesque;
int makedirs(const char *, unsigned); int makedirs(const char *, unsigned) libcesque;
int pivot_root(const char *, const char *); int pivot_root(const char *, const char *) libcesque;
int pledge(const char *, const char *); int pledge(const char *, const char *) libcesque;
int seccomp(unsigned, unsigned, void *); int seccomp(unsigned, unsigned, void *) libcesque;
int sys_iopl(int); int sys_iopl(int) libcesque;
int sys_ioprio_get(int, int); int sys_ioprio_get(int, int) libcesque;
int sys_ioprio_set(int, int, int); int sys_ioprio_set(int, int, int) libcesque;
int sys_mlock(const void *, size_t); int sys_mlock(const void *, size_t) libcesque;
int sys_mlock2(const void *, size_t, int); int sys_mlock2(const void *, size_t, int) libcesque;
int sys_mlockall(int); int sys_mlockall(int) libcesque;
int sys_munlock(const void *, size_t); int sys_munlock(const void *, size_t) libcesque;
int sys_munlockall(void); int sys_munlockall(void) libcesque;
int sys_personality(uint64_t); int sys_personality(uint64_t) libcesque;
int sys_ptrace(int, ...); int sys_ptrace(int, ...) libcesque;
int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t); int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
int tmpfd(void); int tmpfd(void) libcesque;
int touch(const char *, unsigned); int touch(const char *, unsigned) libcesque;
int unveil(const char *, const char *); int unveil(const char *, const char *) libcesque;
long ptrace(int, ...); long ptrace(int, ...) libcesque;
ssize_t copyfd(int, int, size_t); ssize_t copyfd(int, int, size_t) libcesque;
ssize_t readansi(int, char *, size_t); ssize_t readansi(int, char *, size_t) libcesque;
ssize_t tinyprint(int, const char *, ...) nullterminated(); ssize_t tinyprint(int, const char *, ...) libcesque nullterminated();
void shm_path_np(const char *, char[hasatleast 78]); void shm_path_np(const char *, char[hasatleast 78]) libcesque;
#endif /* _COSMO_SOURCE */ #endif /* _COSMO_SOURCE */
int __wifstopped(int) pureconst; int __wifstopped(int) libcesque pureconst;
int __wifcontinued(int) pureconst; int __wifcontinued(int) libcesque pureconst;
int __wifsignaled(int) pureconst; int __wifsignaled(int) libcesque pureconst;
#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
#define lseek64 lseek #define lseek64 lseek

View file

@ -16,10 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/state.internal.h" #include "libc/calls/state.internal.h"
#include "libc/calls/struct/fd.internal.h" #include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
@ -49,13 +51,8 @@ static int close_impl(int fd) {
} }
if (__isfdkind(fd, kFdZip)) { if (__isfdkind(fd, kFdZip)) {
if (!__vforked && _weaken(__zipos_close)) { unassert(_weaken(__zipos_close));
return _weaken(__zipos_close)(fd); return _weaken(__zipos_close)(fd);
}
if (!IsWindows() && !IsMetal()) {
sys_close(fd);
}
return 0;
} }
if (!IsWindows() && !IsMetal()) { if (!IsWindows() && !IsMetal()) {
@ -95,8 +92,18 @@ static int close_impl(int fd) {
* @vforksafe * @vforksafe
*/ */
int close(int fd) { int close(int fd) {
int rc = close_impl(fd); int rc;
if (!__vforked) __releasefd(fd); if (__isfdkind(fd, kFdZip)) { // XXX IsWindows()?
BLOCK_SIGNALS;
__fds_lock();
rc = close_impl(fd);
if (!__vforked) __releasefd(fd);
__fds_unlock();
ALLOW_SIGNALS;
} else {
rc = close_impl(fd);
if (!__vforked) __releasefd(fd);
}
STRACE("close(%d) → %d% m", fd, rc); STRACE("close(%d) → %d% m", fd, rc);
return rc; return rc;
} }

View file

@ -66,4 +66,4 @@ int fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
return rc; return rc;
} }
__strong_reference(fadvise, fadvise64); __weak_reference(fadvise, fadvise64);

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc Musl Libc

View file

@ -26,11 +26,11 @@
#include "libc/elf/def.h" #include "libc/elf/def.h"
#include "libc/elf/tinyelf.internal.h" #include "libc/elf/tinyelf.internal.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/serialize.h"
#include "libc/intrin/directmap.internal.h" #include "libc/intrin/directmap.internal.h"
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/serialize.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/map.h" #include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
@ -80,8 +80,9 @@ static bool IsMyDebugBinary(const char *path) {
// contains the same number of bytes of code as our .com executable // contains the same number of bytes of code as our .com executable
// which is currently running in memory. // which is currently running in memory.
if ((size = lseek(fd, 0, SEEK_END)) != -1 && if ((size = lseek(fd, 0, SEEK_END)) != -1 &&
(dm = sys_mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)).addr != (dm = sys_mmap((void *)0x12345000000, size, PROT_READ, MAP_SHARED, fd,
MAP_FAILED) { 0))
.addr != MAP_FAILED) {
if (READ32LE((char *)dm.addr) == READ32LE("\177ELF") && if (READ32LE((char *)dm.addr) == READ32LE("\177ELF") &&
((Elf64_Ehdr *)dm.addr)->e_machine == GetElfMachine() && ((Elf64_Ehdr *)dm.addr)->e_machine == GetElfMachine() &&
GetElfSymbolValue(dm.addr, "_etext", &value)) { GetElfSymbolValue(dm.addr, "_etext", &value)) {

View file

@ -60,4 +60,4 @@ int fstat(int fd, struct stat *st) {
return rc; return rc;
} }
__strong_reference(fstat, fstat64); __weak_reference(fstat, fstat64);

Some files were not shown because too many files have changed in this diff Show more