mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 17:19:47 -10:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f2bf3895e | ||
|
|
dbb8d66f22 |
No files matched your search
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
mode: ["", tiny, rel, tinylinux, optlinux]
|
||||
mode: ["", tiny, opt, rel]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
||||
Vendored
+4
-3
@@ -36,13 +36,13 @@
|
||||
"textwindows=",
|
||||
"privileged=",
|
||||
"compatfn=",
|
||||
"dontinstrument=",
|
||||
"noinstrument=",
|
||||
"nodebuginfo=",
|
||||
"interruptfn=",
|
||||
"optimizespeed=",
|
||||
"forcealignargpointer=",
|
||||
"dontasan=",
|
||||
"dontubsan=",
|
||||
"noasan=",
|
||||
"noubsan=",
|
||||
"donothing=",
|
||||
"nosideeffect=",
|
||||
"unreachable=",,
|
||||
@@ -78,6 +78,7 @@
|
||||
"-Wa,-W",
|
||||
"-Wa,-I.",
|
||||
"-Wa,--noexecstack",
|
||||
"-Wa,--nocompress-debug-sections",
|
||||
"-Og",
|
||||
"-g",
|
||||
"-gdescribe-dies",
|
||||
|
||||
@@ -60,12 +60,13 @@
|
||||
# build/config.mk
|
||||
|
||||
SHELL = build/bootstrap/cocmd.com
|
||||
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win10
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
.SUFFIXES:
|
||||
.DELETE_ON_ERROR:
|
||||
.FEATURES: output-sync
|
||||
.PHONY: all o bins check test depend tags aarch64 clean
|
||||
.PHONY: all o bins check test depend tags
|
||||
|
||||
ifneq ($(m),)
|
||||
ifeq ($(MODE),)
|
||||
@@ -86,15 +87,7 @@ o/$(MODE): \
|
||||
o/$(MODE)/examples \
|
||||
o/$(MODE)/third_party
|
||||
|
||||
ifneq ($(LANDLOCKMAKE_VERSION),)
|
||||
ifeq ($(wildcard /usr/bin/ape),)
|
||||
$(error please run ape/apeinstall.sh if you intend to use landlock make)
|
||||
endif
|
||||
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
|
||||
.STRICT = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
.PLEDGE = stdio rpath wpath cpath fattr proc
|
||||
.UNVEIL = \
|
||||
libc/integral \
|
||||
@@ -102,10 +95,8 @@ endif
|
||||
rwc:/dev/shm \
|
||||
rx:build/bootstrap \
|
||||
rx:o/third_party/gcc \
|
||||
r:build/portcosmo.h \
|
||||
/proc/stat \
|
||||
rw:/dev/null \
|
||||
rw:/dev/full \
|
||||
w:o/stack.log \
|
||||
/etc/hosts \
|
||||
~/.runit.psk \
|
||||
@@ -119,13 +110,15 @@ include build/functions.mk #─┐
|
||||
include build/definitions.mk # ├──META
|
||||
include build/config.mk # │ You can build
|
||||
include build/rules.mk # │ You can topologically order
|
||||
include build/online.mk #─┘
|
||||
include build/online.mk # │
|
||||
include libc/stubs/stubs.mk #─┘
|
||||
include libc/nexgen32e/nexgen32e.mk #─┐
|
||||
include libc/sysv/sysv.mk # ├──SYSTEM SUPPORT
|
||||
include libc/nt/nt.mk # │ You can do math
|
||||
include libc/intrin/intrin.mk # │ You can use the stack
|
||||
include third_party/compiler_rt/compiler_rt.mk # │ You can manipulate arrays
|
||||
include libc/tinymath/tinymath.mk # │ You can issue raw system calls
|
||||
include libc/linux/linux.mk # │ You can manipulate arrays
|
||||
include third_party/compiler_rt/compiler_rt.mk # │ You can issue raw system calls
|
||||
include libc/tinymath/tinymath.mk # │
|
||||
include libc/str/str.mk # │
|
||||
include third_party/xed/xed.mk # │
|
||||
include third_party/puff/puff.mk # │
|
||||
@@ -136,6 +129,7 @@ include ape/ape.mk # │
|
||||
include libc/fmt/fmt.mk # │
|
||||
include libc/vga/vga.mk #─┘
|
||||
include libc/calls/calls.mk #─┐
|
||||
include third_party/getopt/getopt.mk # │
|
||||
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
|
||||
include libc/crt/crt.mk # │ You can issue system calls
|
||||
include tool/hello/hello.mk # │
|
||||
@@ -146,21 +140,22 @@ include third_party/gdtoa/gdtoa.mk # ├──DYNAMIC RUNTIME
|
||||
include third_party/nsync/mem/mem.mk # │ You can now use stdio
|
||||
include libc/thread/thread.mk # │ You can finally call malloc()
|
||||
include libc/zipos/zipos.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include libc/time/time.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include third_party/libcxx/libcxx.mk # │
|
||||
include net/net.mk # │
|
||||
include third_party/vqsort/vqsort.mk # │
|
||||
include libc/log/log.mk # │
|
||||
include third_party/getopt/getopt.mk # │
|
||||
include third_party/ggml/ggml.mk # │
|
||||
include third_party/bzip2/bzip2.mk # │
|
||||
include dsp/core/core.mk # │
|
||||
include third_party/musl/musl.mk # │
|
||||
include libc/x/x.mk # │
|
||||
include third_party/stb/stb.mk # │
|
||||
include dsp/scale/scale.mk # │
|
||||
include dsp/mpeg/mpeg.mk # │
|
||||
include dsp/dsp.mk # │
|
||||
include third_party/zlib/gz/gz.mk # │
|
||||
include third_party/musl/musl.mk # │
|
||||
include third_party/intel/intel.mk # │
|
||||
include third_party/aarch64/aarch64.mk # │
|
||||
include libc/libc.mk #─┘
|
||||
@@ -169,9 +164,6 @@ include dsp/tty/tty.mk # ├──ONLINE RUNTIME
|
||||
include libc/dns/dns.mk # │ You can communicate with the network
|
||||
include net/http/http.mk # │
|
||||
include third_party/mbedtls/mbedtls.mk # │
|
||||
include third_party/libcxx/libcxx.mk # │
|
||||
include third_party/ggml/ggml.mk # │
|
||||
include third_party/radpajama/radpajama.mk # │
|
||||
include net/https/https.mk # │
|
||||
include third_party/regex/regex.mk #─┘
|
||||
include third_party/tidy/tidy.mk
|
||||
@@ -186,7 +178,6 @@ include third_party/maxmind/maxmind.mk
|
||||
include net/finger/finger.mk
|
||||
include third_party/double-conversion/test/test.mk
|
||||
include third_party/lua/lua.mk
|
||||
include third_party/zstd/zstd.mk
|
||||
include third_party/tr/tr.mk
|
||||
include third_party/sed/sed.mk
|
||||
include third_party/awk/awk.mk
|
||||
@@ -201,15 +192,15 @@ include third_party/mbedtls/test/test.mk
|
||||
include third_party/quickjs/quickjs.mk
|
||||
include third_party/lz4cli/lz4cli.mk
|
||||
include third_party/zip/zip.mk
|
||||
include third_party/xxhash/xxhash.mk
|
||||
include third_party/unzip/unzip.mk
|
||||
include tool/build/lib/buildlib.mk
|
||||
include third_party/chibicc/chibicc.mk
|
||||
include third_party/chibicc/test/test.mk
|
||||
include third_party/python/python.mk
|
||||
include tool/build/emucrt/emucrt.mk
|
||||
include tool/build/emubin/emubin.mk
|
||||
include tool/build/build.mk
|
||||
include tool/curl/curl.mk
|
||||
include tool/ape/ape.mk
|
||||
include third_party/qemu/qemu.mk
|
||||
include examples/examples.mk
|
||||
include examples/pyapp/pyapp.mk
|
||||
@@ -221,6 +212,7 @@ include tool/lambda/lambda.mk
|
||||
include tool/plinko/lib/lib.mk
|
||||
include tool/plinko/plinko.mk
|
||||
include test/tool/plinko/test.mk
|
||||
include tool/hash/hash.mk
|
||||
include tool/net/net.mk
|
||||
include tool/viz/viz.mk
|
||||
include tool/tool.mk
|
||||
@@ -281,14 +273,14 @@ tags: TAGS HTAGS
|
||||
o/$(MODE)/.x:
|
||||
@$(COMPILE) -AMKDIR -tT$@ $(MKDIR) $(@D)
|
||||
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x)))) $(SRCS)
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@,$(SRCS))
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x)))) $(HDRS) $(INCS)
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@,$(HDRS) $(INCS))
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x)))) $(INCS) $(INCS)
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
|
||||
$(file >$@,$(INCS))
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
|
||||
$(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt
|
||||
@$(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt
|
||||
|
||||
o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||
@@ -301,7 +293,7 @@ TAGS: o/$(MODE)/srcs-old.txt $(SRCS) #o/$(MODE)/third_party/ctags/ctags.com
|
||||
@o/$(MODE)/third_party/ctags/ctags.com $(TAGSFLAGS) -L $< -o $@
|
||||
|
||||
HTAGS: private .UNSANDBOXED = 1
|
||||
HTAGS: o/$(MODE)/hdrs-old.txt $(filter-out third_party/libcxx/%,$(HDRS)) #o/$(MODE)/third_party/ctags/ctags.com
|
||||
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS) #o/$(MODE)/third_party/ctags/ctags.com
|
||||
@$(RM) $@
|
||||
@build/htags o/$(MODE)/third_party/ctags/ctags.com -L $< -o $@
|
||||
|
||||
@@ -313,7 +305,6 @@ loc: o/$(MODE)/tool/build/summy.com
|
||||
# PLEASE: MAINTAIN TOPOLOGICAL ORDER
|
||||
# FROM HIGHEST LEVEL TO LOWEST LEVEL
|
||||
COSMOPOLITAN_OBJECTS = \
|
||||
TOOL_ARGS \
|
||||
NET_HTTP \
|
||||
LIBC_DNS \
|
||||
LIBC_SOCK \
|
||||
@@ -386,7 +377,6 @@ COSMOPOLITAN_HEADERS = \
|
||||
LIBC_ZIPOS \
|
||||
LIBC_VGA \
|
||||
NET_HTTP \
|
||||
TOOL_ARGS \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
@@ -402,8 +392,7 @@ o/cosmopolitan.h: \
|
||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)) \
|
||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_INCS))
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
|
||||
@$(ECHO) '#define COSMO' >$@
|
||||
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >>$@
|
||||
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >$@
|
||||
|
||||
o/cosmopolitan.html: private .UNSANDBOXED = 1
|
||||
o/cosmopolitan.html: \
|
||||
@@ -425,7 +414,6 @@ $(SRCS): \
|
||||
libc/integral/lp64.inc
|
||||
|
||||
.PHONY: toolchain
|
||||
ifeq ($(ARCH), x86_64)
|
||||
toolchain: o/cosmopolitan.h \
|
||||
o/$(MODE)/ape/public/ape.lds \
|
||||
o/$(MODE)/libc/crt/crt.o \
|
||||
@@ -433,25 +421,7 @@ toolchain: o/cosmopolitan.h \
|
||||
o/$(MODE)/ape/ape-copy-self.o \
|
||||
o/$(MODE)/ape/ape-no-modify-self.o \
|
||||
o/$(MODE)/cosmopolitan.a \
|
||||
o/$(MODE)/third_party/libcxx/libcxx.a \
|
||||
o/$(MODE)/tool/build/fixupobj.com \
|
||||
o/$(MODE)/tool/build/zipcopy.com
|
||||
else
|
||||
toolchain: o/$(MODE)/ape/aarch64.lds \
|
||||
o/$(MODE)/libc/crt/crt.o \
|
||||
o/$(MODE)/cosmopolitan.a \
|
||||
o/$(MODE)/third_party/libcxx/libcxx.a \
|
||||
o/$(MODE)/tool/build/fixupobj.com \
|
||||
o/$(MODE)/tool/build/zipcopy.com
|
||||
endif
|
||||
|
||||
aarch64: private .INTERNET = true
|
||||
aarch64: private .UNSANDBOXED = true
|
||||
aarch64:
|
||||
$(MAKE) m=aarch64
|
||||
|
||||
clean:
|
||||
$(RM) -r o
|
||||
o/$(MODE)/third_party/libcxx/libcxx.a
|
||||
|
||||
# UNSPECIFIED PREREQUISITES TUTORIAL
|
||||
#
|
||||
|
||||
@@ -19,243 +19,8 @@ libc](https://justine.lol/cosmopolitan/index.html) website. We also have
|
||||
|
||||
## Getting Started
|
||||
|
||||
It's recommended that Cosmopolitan be installed to `/opt/cosmo` and
|
||||
`/opt/cosmos` on your computer. The first has the monorepo. The second
|
||||
contains your non-monorepo artifacts.
|
||||
|
||||
```sh
|
||||
sudo mkdir -p /opt
|
||||
sudo chmod 1777 /opt
|
||||
git clone https://github.com/jart/cosmopolitan /opt/cosmo
|
||||
cd /opt/cosmo
|
||||
make -j8 toolchain
|
||||
ape/apeinstall.sh # optional
|
||||
mkdir -p /opt/cosmos/bin
|
||||
export PATH="/opt/cosmos/bin:$PATH"
|
||||
echo 'PATH="/opt/cosmos/bin:$PATH"' >>~/.profile
|
||||
sudo ln -sf /opt/cosmo/tool/scripts/cosmocc /opt/cosmos/bin/cosmocc
|
||||
sudo ln -sf /opt/cosmo/tool/scripts/cosmoc++ /opt/cosmos/bin/cosmoc++
|
||||
```
|
||||
|
||||
You've now successfully installed your very own cosmos. Now let's build
|
||||
an example program, which demonstrates the crash reporting feature:
|
||||
|
||||
```c
|
||||
// hello.c
|
||||
#include <stdio.h>
|
||||
#include <cosmo.h>
|
||||
|
||||
int main() {
|
||||
ShowCrashReports();
|
||||
printf("hello world\n");
|
||||
__builtin_trap();
|
||||
}
|
||||
```
|
||||
|
||||
To compile the program, you can run the `cosmocc` command. It's
|
||||
important to give it an output path that ends with `.com` so the output
|
||||
format will be Actually Portable Executable. When this happens, a
|
||||
concomitant debug binary is created automatically too.
|
||||
|
||||
```sh
|
||||
cosmocc -o hello.com hello.c
|
||||
./hello.com
|
||||
./hello.com.dbg
|
||||
```
|
||||
|
||||
You can use the `cosmocc` toolchain to build conventional open source
|
||||
projects which use autotools. This strategy normally works:
|
||||
|
||||
```sh
|
||||
export CC=cosmocc
|
||||
export CXX=cosmoc++
|
||||
./configure --prefix=/opt/cosmos
|
||||
make -j
|
||||
make install
|
||||
```
|
||||
|
||||
The Cosmopolitan Libc runtime links some heavyweight troubleshooting
|
||||
features by default, which are very useful for developers and admins.
|
||||
Here's how you can log system calls:
|
||||
|
||||
```sh
|
||||
./hello.com --strace
|
||||
```
|
||||
|
||||
Here's how you can get a much more verbose log of function calls:
|
||||
|
||||
```sh
|
||||
./hello.com --ftrace
|
||||
```
|
||||
|
||||
If you want to cut out the bloat and instead make your executables as
|
||||
tiny as possible, then the monorepo supports numerous build modes. You
|
||||
can select one of the predefined ones by looking at
|
||||
[build/config.mk](build/config.mk). One of the most popular modes is
|
||||
`MODE=tiny`. It can be used with the `cosmocc` toolchain as follows:
|
||||
|
||||
```sh
|
||||
cd /opt/cosmo
|
||||
make -j8 MODE=tiny toolchain
|
||||
```
|
||||
|
||||
Now that we have our toolchain, let's write a program that links less
|
||||
surface area than the program above. The executable that this program
|
||||
produces will run on platforms like Linux, Windows, MacOS, etc., even
|
||||
though it's directly using POSIX APIs, which Cosmopolitan polyfills.
|
||||
|
||||
```c
|
||||
// hello2.c
|
||||
#include <unistd.h>
|
||||
int main() {
|
||||
write(1, "hello world\n", 12);
|
||||
}
|
||||
```
|
||||
|
||||
Now let's compile our tiny actually portable executable, which should be
|
||||
on the order of 20kb in size.
|
||||
|
||||
```sh
|
||||
export MODE=tiny
|
||||
cosmocc -Os -o hello2.com hello2.c
|
||||
./hello2.com
|
||||
```
|
||||
|
||||
Let's say you only care about Linux and would rather have simpler tinier
|
||||
binaries, similar to what Musl Libc would produce. In that case, try
|
||||
using the `MODE=tinylinux` build mode, which can produce binaries more
|
||||
on the order of 4kb.
|
||||
|
||||
```sh
|
||||
export MODE=tinylinux
|
||||
(cd /opt/cosmo; make -j8 toolchain)
|
||||
cosmocc -Os -o hello2.com hello2.c
|
||||
./hello2.com # <-- actually an ELF executable
|
||||
```
|
||||
|
||||
## ARM
|
||||
|
||||
Cosmo supports cross-compiling binaries for machines with ARM
|
||||
microprocessors. There are two options available for doing this.
|
||||
|
||||
The first option is to embed the [blink virtual
|
||||
machine](https://github.com/jart/blink) by adding the following to the
|
||||
top of your main.c file:
|
||||
|
||||
```c
|
||||
__static_yoink("blink_linux_aarch64"); // for raspberry pi
|
||||
__static_yoink("blink_xnu_aarch64"); // is apple silicon
|
||||
```
|
||||
|
||||
The benefit is you'll have single file executables that'll run on both
|
||||
x86_64 and arm64 platforms. The tradeoff is Blink's JIT is slower than
|
||||
running natively, but tends to go fast enough, unless you're doing
|
||||
scientific computing (e.g. running LLMs with
|
||||
`o//third_party/ggml/llama.com`).
|
||||
|
||||
Therefore, the second option is to cross compile aarch64 executables,
|
||||
by using build modes like the following:
|
||||
|
||||
```sh
|
||||
make -j8 m=aarch64 o/aarch64/third_party/ggml/llama.com
|
||||
make -j8 m=aarch64-tiny o/aarch64-tiny/third_party/ggml/llama.com
|
||||
```
|
||||
|
||||
That'll produce ELF executables that run natively on two operating
|
||||
systems: Linux Arm64 (e.g. Raspberry Pi) and MacOS Arm64 (i.e. Apple
|
||||
Silicon), thus giving you full performance. The catch is you have to
|
||||
compile these executables on an x86_64-linux machine. The second catch
|
||||
is that MacOS needs a little bit of help understanding the ELF format.
|
||||
To solve that, we provide a tiny APE loader you can use on M1 machines.
|
||||
|
||||
```sh
|
||||
scp ape/ape-m1.c macintosh:
|
||||
scp o/aarch64/third_party/ggml/llama.com macintosh:
|
||||
ssh macintosh
|
||||
xcode-install
|
||||
cc -o ape ape-m1.c
|
||||
sudo cp ape /usr/local/bin/ape
|
||||
```
|
||||
|
||||
You can run your ELF AARCH64 executable on Apple Silicon as follows:
|
||||
|
||||
```sh
|
||||
ape ./llama.com
|
||||
```
|
||||
|
||||
## Source Builds
|
||||
|
||||
Cosmopolitan can be compiled from source on any Linux distro. First, you
|
||||
need to download or clone the repository.
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
|
||||
tar xf cosmopolitan.tar.gz # see releases page
|
||||
cd cosmopolitan
|
||||
```
|
||||
|
||||
This will build the entire repository and run all the tests:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com
|
||||
o//examples/hello.com
|
||||
find o -name \*.com | xargs ls -rShal | less
|
||||
```
|
||||
|
||||
If you get an error running make.com then it's probably because you have
|
||||
WINE installed to `binfmt_misc`. You can fix that by installing the the
|
||||
APE loader as an interpreter. It'll improve build performance too!
|
||||
|
||||
```sh
|
||||
ape/apeinstall.sh
|
||||
```
|
||||
|
||||
Since the Cosmopolitan repository is very large, you might only want to
|
||||
build a particular thing. Cosmopolitan's build config does a good job at
|
||||
having minimal deterministic builds. For example, if you wanted to build
|
||||
only hello.com then you could do that as follows:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com o//examples/hello.com
|
||||
```
|
||||
|
||||
Sometimes it's desirable to build a subset of targets, without having to
|
||||
list out each individual one. You can do that by asking make to build a
|
||||
directory name. For example, if you wanted to build only the targets and
|
||||
subtargets of the chibicc package including its tests, you would say:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com o//third_party/chibicc
|
||||
o//third_party/chibicc/chibicc.com --help
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com m=tiny
|
||||
```
|
||||
|
||||
Here's some other build modes you can try:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com m=dbg # asan + ubsan + debug
|
||||
build/bootstrap/make.com m=asan # production memory safety
|
||||
build/bootstrap/make.com m=opt # -march=native optimizations
|
||||
build/bootstrap/make.com m=rel # traditional release binaries
|
||||
build/bootstrap/make.com m=optlinux # optimal linux-only performance
|
||||
build/bootstrap/make.com m=fastbuild # build 28% faster w/o debugging
|
||||
build/bootstrap/make.com m=tinylinux # tiniest linux-only 4kb binaries
|
||||
```
|
||||
|
||||
For further details, see [//build/config.mk](build/config.mk).
|
||||
|
||||
## Cosmopolitan Amalgamation
|
||||
|
||||
Another way to use Cosmopolitan is via our amalgamated release, where
|
||||
we've combined everything into a single static archive and a single
|
||||
header file. If you're doing your development work on Linux or BSD then
|
||||
you need just five files to get started. Here's what you do on Linux:
|
||||
If you're doing your development work on Linux or BSD then you need just
|
||||
five files to get started. Here's what you do on Linux:
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-2.2.zip
|
||||
@@ -264,7 +29,6 @@ printf 'main() { printf("hello world\\n"); }\n' >hello.c
|
||||
gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
|
||||
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs -gdwarf-4 \
|
||||
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds -Wl,--gc-sections \
|
||||
-Wl,-z,common-page-size=0x1000 -Wl,-z,max-page-size=0x1000 \
|
||||
-include cosmopolitan.h crt.o ape-no-modify-self.o cosmopolitan.a
|
||||
objcopy -S -O binary hello.com.dbg hello.com
|
||||
```
|
||||
@@ -348,6 +112,106 @@ from 60kb in size to about 16kb. There's also a prebuilt amalgamation
|
||||
online <https://justine.lol/cosmopolitan/cosmopolitan-tiny.zip> hosted
|
||||
on our download page <https://justine.lol/cosmopolitan/download.html>.
|
||||
|
||||
### MacOS
|
||||
|
||||
If you're developing on MacOS you can install the GNU compiler
|
||||
collection for x86_64-elf via homebrew:
|
||||
|
||||
```sh
|
||||
brew install x86_64-elf-gcc
|
||||
```
|
||||
|
||||
Then in the above scripts just replace `gcc` and `objcopy` with
|
||||
`x86_64-elf-gcc` and `x86_64-elf-objcopy` to compile your APE binary.
|
||||
|
||||
### Windows
|
||||
|
||||
If you're developing on Windows then you need to download an
|
||||
x86_64-pc-linux-gnu toolchain beforehand. See the [Compiling on
|
||||
Windows](https://justine.lol/cosmopolitan/windows-compiling.html)
|
||||
tutorial. It's needed because the ELF object format is what makes
|
||||
universal binaries possible.
|
||||
|
||||
Cosmopolitan officially only builds on Linux. However, one highly
|
||||
experimental (and currently broken) thing you could try, is building the
|
||||
entire cosmo repository from source using the cross9 toolchain.
|
||||
|
||||
```
|
||||
mkdir -p o/third_party
|
||||
rm -rf o/third_party/gcc
|
||||
wget https://justine.lol/linux-compiler-on-windows/cross9.zip
|
||||
unzip cross9.zip
|
||||
mv cross9 o/third_party/gcc
|
||||
build/bootstrap/make.com
|
||||
```
|
||||
|
||||
## Source Builds
|
||||
|
||||
Cosmopolitan can be compiled from source on any Linux distro. First, you
|
||||
need to download or clone the repository.
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
|
||||
tar xf cosmopolitan.tar.gz # see releases page
|
||||
cd cosmopolitan
|
||||
```
|
||||
|
||||
This will build the entire repository and run all the tests:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com
|
||||
o//examples/hello.com
|
||||
find o -name \*.com | xargs ls -rShal | less
|
||||
```
|
||||
|
||||
If you get an error running make.com then it's probably because you have
|
||||
WINE installed to `binfmt_misc`. You can fix that by installing the the
|
||||
APE loader as an interpreter. It'll improve build performance too!
|
||||
|
||||
```sh
|
||||
ape/apeinstall.sh
|
||||
```
|
||||
|
||||
Since the Cosmopolitan repository is very large, you might only want to
|
||||
build a particular thing. Cosmopolitan's build config does a good job at
|
||||
having minimal deterministic builds. For example, if you wanted to build
|
||||
only hello.com then you could do that as follows:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com o//examples/hello.com
|
||||
```
|
||||
|
||||
Sometimes it's desirable to build a subset of targets, without having to
|
||||
list out each individual one. You can do that by asking make to build a
|
||||
directory name. For example, if you wanted to build only the targets and
|
||||
subtargets of the chibicc package including its tests, you would say:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com o//third_party/chibicc
|
||||
o//third_party/chibicc/chibicc.com --help
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com m=tiny
|
||||
```
|
||||
|
||||
Here's some other build modes you can try:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com m=dbg # asan + ubsan + debug
|
||||
build/bootstrap/make.com m=asan # production memory safety
|
||||
build/bootstrap/make.com m=opt # -march=native optimizations
|
||||
build/bootstrap/make.com m=rel # traditional release binaries
|
||||
build/bootstrap/make.com m=optlinux # optimal linux-only performance
|
||||
build/bootstrap/make.com m=fastbuild # build 28% faster w/o debugging
|
||||
build/bootstrap/make.com m=tinylinux # tiniest linux-only 4kb binaries
|
||||
```
|
||||
|
||||
For further details, see [//build/config.mk](build/config.mk).
|
||||
|
||||
## GDB
|
||||
|
||||
Here's the recommended `~/.gdbinit` config:
|
||||
@@ -375,45 +239,10 @@ src
|
||||
You normally run the `.com.dbg` file under gdb. If you need to debug the
|
||||
`.com` file itself, then you can load the debug symbols independently as
|
||||
|
||||
```sh
|
||||
```
|
||||
gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
|
||||
```
|
||||
|
||||
## Alternative Development Environments
|
||||
|
||||
### MacOS
|
||||
|
||||
If you're developing on MacOS you can install the GNU compiler
|
||||
collection for x86_64-elf via homebrew:
|
||||
|
||||
```sh
|
||||
brew install x86_64-elf-gcc
|
||||
```
|
||||
|
||||
Then in the above scripts just replace `gcc` and `objcopy` with
|
||||
`x86_64-elf-gcc` and `x86_64-elf-objcopy` to compile your APE binary.
|
||||
|
||||
### Windows
|
||||
|
||||
If you're developing on Windows then you need to download an
|
||||
x86_64-pc-linux-gnu toolchain beforehand. See the [Compiling on
|
||||
Windows](https://justine.lol/cosmopolitan/windows-compiling.html)
|
||||
tutorial. It's needed because the ELF object format is what makes
|
||||
universal binaries possible.
|
||||
|
||||
Cosmopolitan officially only builds on Linux. However, one highly
|
||||
experimental (and currently broken) thing you could try, is building the
|
||||
entire cosmo repository from source using the cross9 toolchain.
|
||||
|
||||
```sh
|
||||
mkdir -p o/third_party
|
||||
rm -rf o/third_party/gcc
|
||||
wget https://justine.lol/linux-compiler-on-windows/cross9.zip
|
||||
unzip cross9.zip
|
||||
mv cross9 o/third_party/gcc
|
||||
build/bootstrap/make.com
|
||||
```
|
||||
|
||||
## Discord Chatroom
|
||||
|
||||
The Cosmopolitan development team collaborates on the Redbean Discord
|
||||
@@ -428,7 +257,7 @@ server. You're welcome to join us! <https://discord.gg/FwAVVu7eJ4>
|
||||
| Linux | 2.6.18 | 2007 |
|
||||
| Windows | 8 [1] | 2012 |
|
||||
| Mac OS X | 15.6 | 2018 |
|
||||
| OpenBSD | 7 | 2021 |
|
||||
| OpenBSD | 6.4 | 2018 |
|
||||
| FreeBSD | 13 | 2020 |
|
||||
| NetBSD | 9.2 | 2021 |
|
||||
|
||||
|
||||
-290
@@ -1,290 +0,0 @@
|
||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH(aarch64)
|
||||
OUTPUT_FORMAT("elf64-littleaarch64",
|
||||
"elf64-bigaarch64",
|
||||
"elf64-littleaarch64")
|
||||
|
||||
SECTIONS {
|
||||
|
||||
. = SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL);
|
||||
__executable_start = .;
|
||||
. += SIZEOF_HEADERS;
|
||||
|
||||
.interp : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash : { *(.hash) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
.rela.data.rel.ro : { *(.rela.data.rel.ro .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*) }
|
||||
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
.rela.ifunc : { *(.rela.ifunc) }
|
||||
|
||||
.rela.plt : {
|
||||
*(.rela.plt)
|
||||
__rela_iplt_start = .;
|
||||
*(.rela.iplt)
|
||||
__rela_iplt_end = .;
|
||||
}
|
||||
|
||||
.init : {
|
||||
*(.start)
|
||||
KEEP(*(.initprologue))
|
||||
KEEP(*(SORT_NONE(.init)))
|
||||
KEEP(*(.initepilogue))
|
||||
} =0x1f2003d5
|
||||
|
||||
.plt : ALIGN(16) {
|
||||
*(.plt)
|
||||
*(.iplt)
|
||||
}
|
||||
|
||||
.text : {
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.antiquity .text.antiquity.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text.modernity .text.modernity.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
*(.gnu.warning)
|
||||
} =0x1f2003d5
|
||||
|
||||
.fini : {
|
||||
KEEP(*(SORT_NONE(.fini)))
|
||||
} =0x1f2003d5
|
||||
|
||||
. += CONSTANT(COMMONPAGESIZE);
|
||||
|
||||
.privileged : {
|
||||
__privileged_start = .;
|
||||
*(.privileged*)
|
||||
} =0x1f2003d6
|
||||
|
||||
.rodata : {
|
||||
KEEP(*(.rodata.pytab.0));
|
||||
KEEP(*(.rodata.pytab.1));
|
||||
KEEP(*(.rodata.pytab.2));
|
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.ubsan.types)
|
||||
*(.ubsan.data)
|
||||
}
|
||||
|
||||
.comment : {
|
||||
__comment_start = .;
|
||||
KEEP(*(.comment))
|
||||
BYTE(0);
|
||||
}
|
||||
|
||||
.eh_frame_hdr : {
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame_entry .eh_frame_entry.*)
|
||||
}
|
||||
|
||||
.eh_frame : ONLY_IF_RO {
|
||||
KEEP(*(.eh_frame))
|
||||
*(.eh_frame.*)
|
||||
}
|
||||
|
||||
.gcc_except_table : ONLY_IF_RO {
|
||||
*(.gcc_except_table .gcc_except_table.*)
|
||||
}
|
||||
|
||||
.gnu_extab : ONLY_IF_RO {
|
||||
*(.gnu_extab*)
|
||||
}
|
||||
|
||||
.exception_ranges : ONLY_IF_RO {
|
||||
*(.exception_ranges*)
|
||||
}
|
||||
|
||||
__etext = .;
|
||||
_etext = .;
|
||||
PROVIDE(etext = .);
|
||||
|
||||
. += CONSTANT(COMMONPAGESIZE);
|
||||
. = DATA_SEGMENT_ALIGN(CONSTANT(COMMONPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||
|
||||
.eh_frame : ONLY_IF_RW {
|
||||
KEEP(*(.eh_frame))
|
||||
*(.eh_frame.*)
|
||||
}
|
||||
|
||||
.gnu_extab : ONLY_IF_RW {
|
||||
*(.gnu_extab)
|
||||
}
|
||||
|
||||
.gcc_except_table : ONLY_IF_RW {
|
||||
*(.gcc_except_table .gcc_except_table.*)
|
||||
}
|
||||
|
||||
.exception_ranges : ONLY_IF_RW {
|
||||
*(.exception_ranges*)
|
||||
}
|
||||
|
||||
.tdata : {
|
||||
_tdata_start = .;
|
||||
__tdata_start = .;
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
_tdata_end = .;
|
||||
}
|
||||
|
||||
.tbss : {
|
||||
_tbss_start = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
_tbss_end = .;
|
||||
}
|
||||
|
||||
.init_array : {
|
||||
__init_array_start = .;
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
__init_array_end = .;
|
||||
}
|
||||
|
||||
.fini_array : {
|
||||
__fini_array_start = .;
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(.fini_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
__fini_array_end = .;
|
||||
}
|
||||
|
||||
.data.rel.ro : {
|
||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||
*(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*)
|
||||
*(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*)
|
||||
}
|
||||
|
||||
.dynamic : {
|
||||
*(.dynamic)
|
||||
}
|
||||
|
||||
.got : {
|
||||
*(.got)
|
||||
*(.igot)
|
||||
}
|
||||
|
||||
. = DATA_SEGMENT_RELRO_END(24, .);
|
||||
|
||||
.got.plt : {
|
||||
*(.got.plt)
|
||||
*(.igot.plt)
|
||||
}
|
||||
|
||||
.data : {
|
||||
__data_start = .;
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
|
||||
_edata = .;
|
||||
PROVIDE(edata = .);
|
||||
|
||||
. = .;
|
||||
__bss_start = .;
|
||||
__bss_start__ = .;
|
||||
|
||||
.bss : {
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
}
|
||||
|
||||
_bss_end__ = .;
|
||||
__bss_end__ = .;
|
||||
. = ALIGN(64 / 8);
|
||||
. = SEGMENT_START("ldata-segment", .);
|
||||
. = ALIGN(64 / 8);
|
||||
__end__ = .;
|
||||
_end = .;
|
||||
PROVIDE(end = .);
|
||||
|
||||
. = DATA_SEGMENT_END(.);
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.ARM.attributes 0 : { KEEP(*(.ARM.attributes)) KEEP(*(.gnu.attributes)) }
|
||||
.note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) }
|
||||
|
||||
.zip 0 : {
|
||||
KEEP(*(.zip.file))
|
||||
__zip_cdir_start = .;
|
||||
KEEP(*(.zip.cdir))
|
||||
__zip_cdir_size = . - __zip_cdir_start;
|
||||
KEEP(*(.zip.eocd))
|
||||
}
|
||||
|
||||
/DISCARD/ : {
|
||||
*(__patchable_function_entries)
|
||||
*(.GCC.command.line)
|
||||
*(.note.GNU-stack)
|
||||
*(.gnu_debuglink)
|
||||
*(.text.windows)
|
||||
*(.gnu.lto_*)
|
||||
*(.eh_frame)
|
||||
*(.idata.*)
|
||||
*(.head)
|
||||
}
|
||||
}
|
||||
|
||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : APE_STACKSIZE;
|
||||
ape_stack_memsz2 = ape_stack_memsz * 2;
|
||||
_tls_size = _tbss_end - _tdata_start;
|
||||
_tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
|
||||
|
||||
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||
-944
@@ -1,944 +0,0 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/uio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define pagesz 16384
|
||||
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
||||
#define SYSLIB_VERSION 1
|
||||
|
||||
struct Syslib {
|
||||
int magic;
|
||||
int version;
|
||||
long (*fork)(void);
|
||||
long (*pipe)(int[2]);
|
||||
long (*clock_gettime)(int, struct timespec *);
|
||||
long (*nanosleep)(const struct timespec *, struct timespec *);
|
||||
long (*mmap)(void *, size_t, int, int, int, off_t);
|
||||
int (*pthread_jit_write_protect_supported_np)(void);
|
||||
void (*pthread_jit_write_protect_np)(int);
|
||||
void (*sys_icache_invalidate)(void *, size_t);
|
||||
int (*pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *),
|
||||
void *);
|
||||
void (*pthread_exit)(void *);
|
||||
int (*pthread_kill)(pthread_t, int);
|
||||
int (*pthread_sigmask)(int, const sigset_t *restrict, sigset_t *restrict);
|
||||
int (*pthread_setname_np)(const char *);
|
||||
dispatch_semaphore_t (*dispatch_semaphore_create)(long);
|
||||
long (*dispatch_semaphore_signal)(dispatch_semaphore_t);
|
||||
long (*dispatch_semaphore_wait)(dispatch_semaphore_t, dispatch_time_t);
|
||||
dispatch_time_t (*dispatch_walltime)(const struct timespec *, int64_t);
|
||||
};
|
||||
|
||||
#define ELFCLASS32 1
|
||||
#define ELFDATA2LSB 1
|
||||
#define EM_AARCH64 183
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define PF_X 1
|
||||
#define PF_W 2
|
||||
#define PF_R 4
|
||||
#define AT_PHDR 3
|
||||
#define AT_PHENT 4
|
||||
#define AT_PHNUM 5
|
||||
#define AT_PAGESZ 6
|
||||
#define AT_BASE 7
|
||||
#define AT_ENTRY 9
|
||||
#define AT_UID 11
|
||||
#define AT_EUID 12
|
||||
#define AT_GID 13
|
||||
#define AT_EGID 14
|
||||
#define AT_HWCAP 16
|
||||
#define AT_HWCAP2 16
|
||||
#define AT_SECURE 23
|
||||
#define AT_RANDOM 25
|
||||
#define AT_EXECFN 31
|
||||
|
||||
#define STACK_SIZE (8ul * 1024 * 1024)
|
||||
#define STACK_ALIGN (sizeof(long) * 2)
|
||||
#define AUXV_BYTES (sizeof(long) * 2 * 15)
|
||||
|
||||
// from the xnu codebase
|
||||
#define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul
|
||||
#define _COMM_PAGE_APRR_SUPPORT (_COMM_PAGE_START_ADDRESS + 0x10C)
|
||||
#define _COMM_PAGE_APRR_WRITE_ENABLE (_COMM_PAGE_START_ADDRESS + 0x110)
|
||||
#define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118)
|
||||
|
||||
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
||||
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
||||
|
||||
#define READ32(S) \
|
||||
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
||||
(unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000)
|
||||
|
||||
#define READ64(S) \
|
||||
((unsigned long)(255 & (S)[7]) << 070 | \
|
||||
(unsigned long)(255 & (S)[6]) << 060 | \
|
||||
(unsigned long)(255 & (S)[5]) << 050 | \
|
||||
(unsigned long)(255 & (S)[4]) << 040 | \
|
||||
(unsigned long)(255 & (S)[3]) << 030 | \
|
||||
(unsigned long)(255 & (S)[2]) << 020 | \
|
||||
(unsigned long)(255 & (S)[1]) << 010 | \
|
||||
(unsigned long)(255 & (S)[0]) << 000)
|
||||
|
||||
struct ElfEhdr {
|
||||
unsigned char e_ident[16];
|
||||
unsigned short e_type;
|
||||
unsigned short e_machine;
|
||||
unsigned e_version;
|
||||
unsigned long e_entry;
|
||||
unsigned long e_phoff;
|
||||
unsigned long e_shoff;
|
||||
unsigned e_flags;
|
||||
unsigned short e_ehsize;
|
||||
unsigned short e_phentsize;
|
||||
unsigned short e_phnum;
|
||||
unsigned short e_shentsize;
|
||||
unsigned short e_shnum;
|
||||
unsigned short e_shstrndx;
|
||||
};
|
||||
|
||||
struct ElfPhdr {
|
||||
unsigned p_type;
|
||||
unsigned p_flags;
|
||||
unsigned long p_offset;
|
||||
unsigned long p_vaddr;
|
||||
unsigned long p_paddr;
|
||||
unsigned long p_filesz;
|
||||
unsigned long p_memsz;
|
||||
unsigned long p_align;
|
||||
};
|
||||
|
||||
union ElfEhdrBuf {
|
||||
struct ElfEhdr ehdr;
|
||||
char buf[8192];
|
||||
};
|
||||
|
||||
union ElfPhdrBuf {
|
||||
struct ElfPhdr phdr;
|
||||
char buf[4096];
|
||||
};
|
||||
|
||||
struct PathSearcher {
|
||||
unsigned long namelen;
|
||||
const char *name;
|
||||
const char *syspath;
|
||||
char path[1024];
|
||||
};
|
||||
|
||||
struct ApeLoader {
|
||||
union ElfEhdrBuf ehdr;
|
||||
struct PathSearcher ps;
|
||||
// this memory shall be discarded by the guest
|
||||
//////////////////////////////////////////////
|
||||
// this memory shall be known to guest program
|
||||
union {
|
||||
char argblock[ARG_MAX];
|
||||
long numblock[ARG_MAX / sizeof(long)];
|
||||
};
|
||||
union ElfPhdrBuf phdr;
|
||||
struct Syslib lib;
|
||||
char rando[16];
|
||||
};
|
||||
|
||||
static int ToLower(int c) {
|
||||
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
static unsigned long StrLen(const char *s) {
|
||||
unsigned long n = 0;
|
||||
while (*s++) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static int StrCmp(const char *l, const char *r) {
|
||||
unsigned long i = 0;
|
||||
while (l[i] == r[i] && r[i]) ++i;
|
||||
return (l[i] & 255) - (r[i] & 255);
|
||||
}
|
||||
|
||||
static const char *BaseName(const char *s) {
|
||||
int c;
|
||||
const char *b = "";
|
||||
if (s) {
|
||||
while ((c = *s++)) {
|
||||
if (c == '/') {
|
||||
b = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static void Bzero(void *a, unsigned long n) {
|
||||
long z;
|
||||
char *p, *e;
|
||||
p = (char *)a;
|
||||
e = p + n;
|
||||
z = 0;
|
||||
while (p + sizeof(z) <= e) {
|
||||
__builtin_memcpy(p, &z, sizeof(z));
|
||||
p += sizeof(z);
|
||||
}
|
||||
while (p < e) {
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *MemChr(const char *s, unsigned char c, unsigned long n) {
|
||||
for (; n; --n, ++s) {
|
||||
if ((*s & 255) == c) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *MemMove(void *a, const void *b, unsigned long n) {
|
||||
long w;
|
||||
char *d;
|
||||
const char *s;
|
||||
unsigned long i;
|
||||
d = (char *)a;
|
||||
s = (const char *)b;
|
||||
if (d > s) {
|
||||
while (n >= sizeof(w)) {
|
||||
n -= sizeof(w);
|
||||
__builtin_memcpy(&w, s + n, sizeof(n));
|
||||
__builtin_memcpy(d + n, &w, sizeof(n));
|
||||
}
|
||||
while (n--) {
|
||||
d[n] = s[n];
|
||||
}
|
||||
} else {
|
||||
i = 0;
|
||||
while (i + sizeof(w) <= n) {
|
||||
__builtin_memcpy(&w, s + i, sizeof(i));
|
||||
__builtin_memcpy(d + i, &w, sizeof(i));
|
||||
i += sizeof(w);
|
||||
}
|
||||
for (; i < n; ++i) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static char *GetEnv(char **p, const char *s) {
|
||||
unsigned long i, j;
|
||||
if (p) {
|
||||
for (i = 0; p[i]; ++i) {
|
||||
for (j = 0;; ++j) {
|
||||
if (!s[j]) {
|
||||
if (p[i][j] == '=') {
|
||||
return p[i] + j + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (s[j] != p[i][j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *Utoa(char p[21], unsigned long x) {
|
||||
char t;
|
||||
unsigned long 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 *Itoa(char p[21], long x) {
|
||||
if (x < 0) *p++ = '-', x = -(unsigned long)x;
|
||||
return Utoa(p, x);
|
||||
}
|
||||
|
||||
static void Emit(const char *s) {
|
||||
write(2, s, StrLen(s));
|
||||
}
|
||||
|
||||
static long Print(int fd, const char *s, ...) {
|
||||
int c;
|
||||
unsigned n;
|
||||
char b[512];
|
||||
__builtin_va_list va;
|
||||
__builtin_va_start(va, s);
|
||||
for (n = 0; s; s = __builtin_va_arg(va, const char *)) {
|
||||
while ((c = *s++)) {
|
||||
if (n < sizeof(b)) {
|
||||
b[n++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
__builtin_va_end(va);
|
||||
return write(fd, b, n);
|
||||
}
|
||||
|
||||
static void Perror(const char *thing, long rc, const char *reason) {
|
||||
char ibuf[21];
|
||||
ibuf[0] = 0;
|
||||
if (rc) Itoa(ibuf, -rc);
|
||||
Print(2, "ape error: ", thing, ": ", reason, rc ? " failed w/ errno " : "",
|
||||
ibuf, "\n", 0l);
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) static void Pexit(const char *c, int failed,
|
||||
const char *s) {
|
||||
Perror(c, failed, s);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
static char EndsWithIgnoreCase(const char *p, unsigned long n, const char *s) {
|
||||
unsigned long i, m;
|
||||
if (n >= (m = StrLen(s))) {
|
||||
for (i = n - m; i < n; ++i) {
|
||||
if (ToLower(p[i]) != *s++) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char IsComPath(struct PathSearcher *ps) {
|
||||
return EndsWithIgnoreCase(ps->name, ps->namelen, ".com") ||
|
||||
EndsWithIgnoreCase(ps->name, ps->namelen, ".exe") ||
|
||||
EndsWithIgnoreCase(ps->name, ps->namelen, ".com.dbg");
|
||||
}
|
||||
|
||||
static char AccessCommand(struct PathSearcher *ps, const char *suffix,
|
||||
unsigned long pathlen) {
|
||||
unsigned long suffixlen;
|
||||
suffixlen = StrLen(suffix);
|
||||
if (pathlen + 1 + ps->namelen + suffixlen + 1 > sizeof(ps->path)) return 0;
|
||||
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
||||
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
||||
MemMove(ps->path + pathlen + ps->namelen, suffix, suffixlen + 1);
|
||||
return !access(ps->path, X_OK);
|
||||
}
|
||||
|
||||
static char SearchPath(struct PathSearcher *ps, const char *suffix) {
|
||||
const char *p;
|
||||
unsigned long i;
|
||||
for (p = ps->syspath;;) {
|
||||
for (i = 0; p[i] && p[i] != ':'; ++i) {
|
||||
if (i < sizeof(ps->path)) {
|
||||
ps->path[i] = p[i];
|
||||
}
|
||||
}
|
||||
if (AccessCommand(ps, suffix, i)) {
|
||||
return 1;
|
||||
} else if (p[i] == ':') {
|
||||
p += i + 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char FindCommand(struct PathSearcher *ps, const char *suffix) {
|
||||
if (MemChr(ps->name, '/', ps->namelen)) {
|
||||
ps->path[0] = 0;
|
||||
return AccessCommand(ps, suffix, 0);
|
||||
}
|
||||
return SearchPath(ps, suffix);
|
||||
}
|
||||
|
||||
static char *Commandv(struct PathSearcher *ps, const char *name,
|
||||
const char *syspath) {
|
||||
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 (FindCommand(ps, "") || (!IsComPath(ps) && FindCommand(ps, ".com"))) {
|
||||
return ps->path;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void pthread_jit_write_protect_np_workaround(int enabled) {
|
||||
int count_start = 8192;
|
||||
volatile int count = count_start;
|
||||
unsigned long *addr, *other, val, val2, reread = -1;
|
||||
addr = (unsigned long *)(!enabled ? _COMM_PAGE_APRR_WRITE_ENABLE
|
||||
: _COMM_PAGE_APRR_WRITE_DISABLE);
|
||||
other = (unsigned long *)(enabled ? _COMM_PAGE_APRR_WRITE_ENABLE
|
||||
: _COMM_PAGE_APRR_WRITE_DISABLE);
|
||||
switch (*(volatile unsigned char *)_COMM_PAGE_APRR_SUPPORT) {
|
||||
case 1:
|
||||
do {
|
||||
val = *addr;
|
||||
reread = -1;
|
||||
asm volatile("msr\tS3_4_c15_c2_7,%0\n"
|
||||
"isb\tsy\n"
|
||||
: /* no outputs */
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
val2 = *addr;
|
||||
asm volatile("mrs\t%0,S3_4_c15_c2_7\n"
|
||||
: "=r"(reread)
|
||||
: /* no inputs */
|
||||
: "memory");
|
||||
if (val2 == reread) {
|
||||
return;
|
||||
}
|
||||
usleep(10);
|
||||
} while (count-- > 0);
|
||||
break;
|
||||
case 3:
|
||||
do {
|
||||
val = *addr;
|
||||
reread = -1;
|
||||
asm volatile("msr\tS3_6_c15_c1_5,%0\n"
|
||||
"isb\tsy\n"
|
||||
: /* no outputs */
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
val2 = *addr;
|
||||
asm volatile("mrs\t%0,S3_6_c15_c1_5\n"
|
||||
: "=r"(reread)
|
||||
: /* no inputs */
|
||||
: "memory");
|
||||
if (val2 == reread) {
|
||||
return;
|
||||
}
|
||||
usleep(10);
|
||||
} while (count-- > 0);
|
||||
break;
|
||||
default:
|
||||
pthread_jit_write_protect_np(enabled);
|
||||
return;
|
||||
}
|
||||
Pexit("ape", 0, "failed to set jit write protection");
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
||||
long *sp, struct ElfEhdr *e,
|
||||
struct ElfPhdr *p,
|
||||
struct Syslib *lib) {
|
||||
long rc;
|
||||
int prot;
|
||||
int flags;
|
||||
int found_entry;
|
||||
unsigned long dynbase;
|
||||
unsigned long virtmin, virtmax;
|
||||
unsigned long a, b, c, d, i, j;
|
||||
|
||||
/* validate elf */
|
||||
found_entry = 0;
|
||||
virtmin = virtmax = 0;
|
||||
for (i = 0; i < e->e_phnum; ++i) {
|
||||
if (p[i].p_type != PT_LOAD) {
|
||||
continue;
|
||||
}
|
||||
if (p[i].p_filesz > p[i].p_memsz) {
|
||||
Pexit(exe, 0, "ELF p_filesz exceeds p_memsz");
|
||||
}
|
||||
if ((p[i].p_flags & (PF_W | PF_X)) == (PF_W | PF_X)) {
|
||||
Pexit(exe, 0, "Apple Silicon doesn't allow RWX memory");
|
||||
}
|
||||
if ((p[i].p_vaddr & (pagesz - 1)) != (p[i].p_offset & (pagesz - 1))) {
|
||||
Pexit(exe, 0, "ELF p_vaddr incongruent w/ p_offset modulo 16384");
|
||||
}
|
||||
if (p[i].p_vaddr + p[i].p_memsz < p[i].p_vaddr ||
|
||||
p[i].p_vaddr + p[i].p_memsz + (pagesz - 1) < p[i].p_vaddr) {
|
||||
Pexit(exe, 0, "ELF p_vaddr + p_memsz overflow");
|
||||
}
|
||||
if (p[i].p_offset + p[i].p_filesz < p[i].p_offset ||
|
||||
p[i].p_offset + p[i].p_filesz + (pagesz - 1) < p[i].p_offset) {
|
||||
Pexit(exe, 0, "ELF p_offset + p_filesz overflow");
|
||||
}
|
||||
a = p[i].p_vaddr & -pagesz;
|
||||
b = (p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz;
|
||||
for (j = i + 1; j < e->e_phnum; ++j) {
|
||||
if (p[j].p_type != PT_LOAD) continue;
|
||||
c = p[j].p_vaddr & -pagesz;
|
||||
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
|
||||
if (MAX(a, c) < MIN(b, d)) {
|
||||
Pexit(exe, 0, "ELF segments overlap each others virtual memory");
|
||||
}
|
||||
}
|
||||
if (p[i].p_flags & PF_X) {
|
||||
if (p[i].p_vaddr <= e->e_entry &&
|
||||
e->e_entry < p[i].p_vaddr + p[i].p_memsz) {
|
||||
found_entry = 1;
|
||||
}
|
||||
}
|
||||
if (p[i].p_vaddr < virtmin) {
|
||||
virtmin = p[i].p_vaddr;
|
||||
}
|
||||
if (p[i].p_vaddr + p[i].p_memsz > virtmax) {
|
||||
virtmax = p[i].p_vaddr + p[i].p_memsz;
|
||||
}
|
||||
}
|
||||
if (!found_entry) {
|
||||
Pexit(exe, 0, "ELF entrypoint not found in PT_LOAD with PF_X");
|
||||
}
|
||||
|
||||
/* choose loading address for dynamic elf executables
|
||||
that maintains relative distances between segments */
|
||||
if (e->e_type == ET_DYN) {
|
||||
rc = (long)mmap(0, virtmax - virtmin, PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (rc < 0) Pexit(exe, rc, "pie mmap");
|
||||
dynbase = rc;
|
||||
if (dynbase & (pagesz - 1)) {
|
||||
Pexit(exe, 0, "OS mmap incongruent w/ AT_PAGESZ");
|
||||
}
|
||||
if (dynbase + virtmin < dynbase) {
|
||||
Pexit(exe, 0, "ELF dynamic base overflow");
|
||||
}
|
||||
} else {
|
||||
dynbase = 0;
|
||||
}
|
||||
|
||||
/* load elf */
|
||||
for (i = 0; i < e->e_phnum; ++i) {
|
||||
if (p[i].p_type != PT_LOAD) continue;
|
||||
if (!p[i].p_memsz) continue;
|
||||
|
||||
/* configure mapping */
|
||||
prot = 0;
|
||||
flags = MAP_FIXED | MAP_PRIVATE;
|
||||
if (p[i].p_flags & PF_R) prot |= PROT_READ;
|
||||
if (p[i].p_flags & PF_W) prot |= PROT_WRITE;
|
||||
if (p[i].p_flags & PF_X) prot |= PROT_EXEC;
|
||||
|
||||
/* load from file */
|
||||
if (p[i].p_filesz) {
|
||||
void *addr;
|
||||
int prot1, prot2;
|
||||
unsigned long size;
|
||||
prot1 = prot;
|
||||
prot2 = prot;
|
||||
a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */
|
||||
b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */
|
||||
c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */
|
||||
if (b > c) b = c;
|
||||
if (c > b && (~prot1 & PROT_WRITE)) {
|
||||
prot1 = PROT_READ | PROT_WRITE;
|
||||
}
|
||||
addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz));
|
||||
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
|
||||
rc = (long)mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz);
|
||||
if (rc < 0) Pexit(exe, rc, "prog mmap");
|
||||
if (c > b) Bzero((void *)(dynbase + a), b - a);
|
||||
if (prot2 != prot1) {
|
||||
rc = mprotect(addr, size, prot2);
|
||||
if (rc < 0) Pexit(exe, rc, "prog mprotect");
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate extra bss */
|
||||
a = p[i].p_vaddr + p[i].p_filesz;
|
||||
a = (a + (pagesz - 1)) & -pagesz;
|
||||
b = p[i].p_vaddr + p[i].p_memsz;
|
||||
if (b > a) {
|
||||
flags |= MAP_ANONYMOUS;
|
||||
rc = (long)mmap((void *)(dynbase + a), b - a, prot, flags, -1, 0);
|
||||
if (rc < 0) Pexit(exe, rc, "bss mmap");
|
||||
}
|
||||
}
|
||||
|
||||
/* finish up */
|
||||
close(fd);
|
||||
|
||||
register long *x0 asm("x0") = sp;
|
||||
register struct Syslib *x15 asm("x15") = lib;
|
||||
register long x16 asm("x16") = e->e_entry;
|
||||
asm volatile("mov\tx1,#0\n\t"
|
||||
"mov\tx2,#0\n\t"
|
||||
"mov\tx3,#0\n\t"
|
||||
"mov\tx4,#0\n\t"
|
||||
"mov\tx5,#0\n\t"
|
||||
"mov\tx6,#0\n\t"
|
||||
"mov\tx7,#0\n\t"
|
||||
"mov\tx8,#0\n\t"
|
||||
"mov\tx9,#0\n\t"
|
||||
"mov\tx10,#0\n\t"
|
||||
"mov\tx11,#0\n\t"
|
||||
"mov\tx12,#0\n\t"
|
||||
"mov\tx13,#0\n\t"
|
||||
"mov\tx14,#0\n\t"
|
||||
"mov\tx17,#0\n\t"
|
||||
"mov\tx19,#0\n\t"
|
||||
"mov\tx20,#0\n\t"
|
||||
"mov\tx21,#0\n\t"
|
||||
"mov\tx22,#0\n\t"
|
||||
"mov\tx23,#0\n\t"
|
||||
"mov\tx24,#0\n\t"
|
||||
"mov\tx25,#0\n\t"
|
||||
"mov\tx26,#0\n\t"
|
||||
"mov\tx27,#0\n\t"
|
||||
"mov\tx28,#0\n\t"
|
||||
"mov\tx29,#0\n\t"
|
||||
"mov\tx30,#0\n\t"
|
||||
"mov\tsp,x0\n\t"
|
||||
"mov\tx0,#0\n\t"
|
||||
"br\tx16"
|
||||
: /* no outputs */
|
||||
: "r"(x0), "r"(x15), "r"(x16)
|
||||
: "memory");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static const char *TryElf(struct ApeLoader *M, const char *exe, int fd,
|
||||
long *sp, long *bp, char *execfn) {
|
||||
long i, rc;
|
||||
unsigned size;
|
||||
struct ElfEhdr *e;
|
||||
struct ElfPhdr *p;
|
||||
|
||||
/* validate elf header */
|
||||
e = &M->ehdr.ehdr;
|
||||
if (READ32(M->ehdr.buf) != READ32("\177ELF")) {
|
||||
return "didn't embed ELF magic";
|
||||
}
|
||||
if (e->e_ident[EI_CLASS] == ELFCLASS32) {
|
||||
return "32-bit ELF isn't supported";
|
||||
}
|
||||
if (e->e_type != ET_EXEC && e->e_type != ET_DYN) {
|
||||
return "ELF not ET_EXEC or ET_DYN";
|
||||
}
|
||||
if (e->e_machine != EM_AARCH64) {
|
||||
return "couldn't find ELF header with ARM64 machine type";
|
||||
}
|
||||
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
|
||||
Pexit(exe, 0, "e_phentsize is wrong");
|
||||
}
|
||||
size = e->e_phnum;
|
||||
if ((size *= sizeof(struct ElfPhdr)) > sizeof(M->phdr.buf)) {
|
||||
Pexit(exe, 0, "too many ELF program headers");
|
||||
}
|
||||
|
||||
/* read program headers */
|
||||
rc = pread(fd, M->phdr.buf, size, M->ehdr.ehdr.e_phoff);
|
||||
if (rc < 0) return "failed to read ELF program headers";
|
||||
if (rc != size) return "truncated read of ELF program headers";
|
||||
|
||||
/* bail on recoverable program header errors */
|
||||
p = &M->phdr.phdr;
|
||||
for (i = 0; i < e->e_phnum; ++i) {
|
||||
if (p[i].p_type == PT_INTERP) {
|
||||
return "ELF has PT_INTERP which isn't supported";
|
||||
}
|
||||
if (p[i].p_type == PT_DYNAMIC) {
|
||||
return "ELF has PT_DYNAMIC which isn't supported";
|
||||
}
|
||||
}
|
||||
|
||||
/* remove empty program headers */
|
||||
for (i = 0; i < e->e_phnum;) {
|
||||
if (p[i].p_type == PT_LOAD && !p[i].p_memsz) {
|
||||
if (i + 1 < e->e_phnum) {
|
||||
MemMove(p + i, p + i + 1,
|
||||
(e->e_phnum - (i + 1)) * sizeof(struct ElfPhdr));
|
||||
}
|
||||
--e->e_phnum;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* merge adjacent loads that are contiguous with equal protection,
|
||||
* which prevents our program header overlap check from needlessly
|
||||
* failing later on; it also shaves away a microsecond of latency,
|
||||
* since every program header requires invoking at least 1 syscall
|
||||
*/
|
||||
for (i = 0; i + 1 < e->e_phnum;) {
|
||||
if (p[i].p_type == PT_LOAD && p[i + 1].p_type == PT_LOAD &&
|
||||
((p[i].p_flags & (PF_R | PF_W | PF_X)) ==
|
||||
(p[i + 1].p_flags & (PF_R | PF_W | PF_X))) &&
|
||||
((p[i].p_offset + p[i].p_filesz + (pagesz - 1)) & -pagesz) -
|
||||
(p[i + 1].p_offset & -pagesz) <=
|
||||
pagesz &&
|
||||
((p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz) -
|
||||
(p[i + 1].p_vaddr & -pagesz) <=
|
||||
pagesz) {
|
||||
p[i].p_memsz = (p[i + 1].p_vaddr + p[i + 1].p_memsz) - p[i].p_vaddr;
|
||||
p[i].p_filesz = (p[i + 1].p_offset + p[i + 1].p_filesz) - p[i].p_offset;
|
||||
if (i + 2 < e->e_phnum) {
|
||||
MemMove(p + i + 1, p + i + 2,
|
||||
(e->e_phnum - (i + 2)) * sizeof(struct ElfPhdr));
|
||||
}
|
||||
--e->e_phnum;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/* simulate linux auxiliary values */
|
||||
long auxv[][2] = {
|
||||
{AT_PHDR, (long)&M->phdr.phdr}, //
|
||||
{AT_PHENT, M->ehdr.ehdr.e_phentsize}, //
|
||||
{AT_PHNUM, M->ehdr.ehdr.e_phnum}, //
|
||||
{AT_ENTRY, M->ehdr.ehdr.e_entry}, //
|
||||
{AT_PAGESZ, pagesz}, //
|
||||
{AT_UID, getuid()}, //
|
||||
{AT_EUID, geteuid()}, //
|
||||
{AT_GID, getgid()}, //
|
||||
{AT_EGID, getegid()}, //
|
||||
{AT_HWCAP, 0xffb3ffffu}, //
|
||||
{AT_HWCAP2, 0x181}, //
|
||||
{AT_SECURE, issetugid()}, //
|
||||
{AT_RANDOM, (long)M->rando}, //
|
||||
{AT_EXECFN, (long)execfn}, //
|
||||
{0, 0}, //
|
||||
};
|
||||
_Static_assert(sizeof(auxv) == AUXV_BYTES,
|
||||
"Please update the AUXV_BYTES constant");
|
||||
MemMove(bp, auxv, sizeof(auxv));
|
||||
|
||||
/* we're now ready to load */
|
||||
Spawn(exe, fd, sp, e, p, &M->lib);
|
||||
}
|
||||
|
||||
__attribute__((__noinline__)) static long sysret(long rc) {
|
||||
return rc == -1 ? -errno : rc;
|
||||
}
|
||||
|
||||
static long sys_fork(void) {
|
||||
return sysret(fork());
|
||||
}
|
||||
|
||||
static long sys_pipe(int pfds[2]) {
|
||||
return sysret(pipe(pfds));
|
||||
}
|
||||
|
||||
static long sys_clock_gettime(int clock, struct timespec *ts) {
|
||||
return sysret(clock_gettime(clock, ts));
|
||||
}
|
||||
|
||||
static long sys_nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
return sysret(nanosleep(req, rem));
|
||||
}
|
||||
|
||||
static long sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
|
||||
off_t off) {
|
||||
return sysret((long)mmap(addr, size, prot, flags, fd, off));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
long z;
|
||||
void *map;
|
||||
long *sp, *bp, *ip;
|
||||
int c, i, n, fd, rc;
|
||||
struct ApeLoader *M;
|
||||
unsigned char rando[24];
|
||||
char *p, *pe, *tp, *exe, *prog, *execfn;
|
||||
|
||||
// generate some hard random data
|
||||
if (getentropy(rando, sizeof(rando))) {
|
||||
Pexit(argv[0], -1, "getentropy");
|
||||
}
|
||||
|
||||
// make the stack look like a linux one
|
||||
map = mmap((void *)(0x7f0000000000 | (long)rando[23] << 32), STACK_SIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (map == MAP_FAILED) {
|
||||
Pexit(argv[0], -1, "stack mmap");
|
||||
}
|
||||
|
||||
// put argument block at top of allocated stack
|
||||
z = (long)map;
|
||||
z += STACK_SIZE - sizeof(struct ApeLoader);
|
||||
z &= -_Alignof(struct ApeLoader);
|
||||
M = (struct ApeLoader *)z;
|
||||
|
||||
// expose screwy apple libs
|
||||
M->lib.magic = SYSLIB_MAGIC;
|
||||
M->lib.version = SYSLIB_VERSION;
|
||||
M->lib.fork = sys_fork;
|
||||
M->lib.pipe = sys_pipe;
|
||||
M->lib.clock_gettime = sys_clock_gettime;
|
||||
M->lib.nanosleep = sys_nanosleep;
|
||||
M->lib.mmap = sys_mmap;
|
||||
M->lib.pthread_jit_write_protect_supported_np =
|
||||
pthread_jit_write_protect_supported_np;
|
||||
M->lib.pthread_jit_write_protect_np = pthread_jit_write_protect_np_workaround;
|
||||
M->lib.pthread_create = pthread_create;
|
||||
M->lib.pthread_exit = pthread_exit;
|
||||
M->lib.pthread_kill = pthread_kill;
|
||||
M->lib.pthread_sigmask = pthread_sigmask;
|
||||
M->lib.pthread_setname_np = pthread_setname_np;
|
||||
M->lib.dispatch_semaphore_create = dispatch_semaphore_create;
|
||||
M->lib.dispatch_semaphore_signal = dispatch_semaphore_signal;
|
||||
M->lib.dispatch_semaphore_wait = dispatch_semaphore_wait;
|
||||
M->lib.dispatch_walltime = dispatch_walltime;
|
||||
|
||||
// copy system provided argument block
|
||||
bp = M->numblock;
|
||||
tp = M->argblock + sizeof(M->argblock);
|
||||
*bp++ = argc;
|
||||
for (i = 0; i < argc; ++i) {
|
||||
tp -= (n = StrLen(argv[i]) + 1);
|
||||
MemMove(tp, argv[i], n);
|
||||
*bp++ = (long)tp;
|
||||
}
|
||||
*bp++ = 0;
|
||||
for (i = 0; envp[i]; ++i) {
|
||||
tp -= (n = StrLen(envp[i]) + 1);
|
||||
MemMove(tp, envp[i], n);
|
||||
*bp++ = (long)tp;
|
||||
}
|
||||
*bp++ = 0;
|
||||
|
||||
// get arguments that point into our block
|
||||
sp = M->numblock;
|
||||
argc = *sp;
|
||||
argv = (char **)(sp + 1);
|
||||
envp = (char **)(sp + 1 + argc + 1);
|
||||
|
||||
// xnu stores getauxval(at_execfn) in getenv("_")
|
||||
execfn = argc > 0 ? argv[0] : 0;
|
||||
for (i = 0; envp[i]; ++i) {
|
||||
if (envp[i][0] == '_' && envp[i][1] == '=') {
|
||||
execfn = envp[i] + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// interpret command line arguments
|
||||
if (argc >= 3 && !StrCmp(argv[1], "-")) {
|
||||
// if the first argument is a hyphen then we give the user the
|
||||
// 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
|
||||
// it's specified by ANSI X3.159-1988.
|
||||
prog = (char *)sp[3];
|
||||
argc = sp[3] = sp[0] - 3;
|
||||
argv = (char **)((sp += 3) + 1);
|
||||
} else if (argc < 2) {
|
||||
Emit("usage: ape PROG [ARGV1,ARGV2,...]\n"
|
||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
||||
"actually portable executable loader silicon 1.5\n"
|
||||
"copyright 2023 justine alexandra roberts tunney\n"
|
||||
"https://justine.lol/ape.html\n");
|
||||
_exit(1);
|
||||
} else {
|
||||
prog = (char *)sp[2];
|
||||
argc = sp[1] = sp[0] - 1;
|
||||
argv = (char **)((sp += 1) + 1);
|
||||
}
|
||||
|
||||
// search for executable
|
||||
if (!(exe = Commandv(&M->ps, prog, GetEnv(envp, "PATH")))) {
|
||||
Pexit(prog, 0, "not found (maybe chmod +x)");
|
||||
} else if ((fd = openat(AT_FDCWD, exe, O_RDONLY)) < 0) {
|
||||
Pexit(exe, -1, "open");
|
||||
} else if ((rc = read(fd, M->ehdr.buf, sizeof(M->ehdr.buf))) < 0) {
|
||||
Pexit(exe, -1, "read");
|
||||
} else if ((unsigned long)rc < sizeof(M->ehdr.ehdr)) {
|
||||
Pexit(exe, 0, "too small");
|
||||
}
|
||||
pe = M->ehdr.buf + rc;
|
||||
|
||||
// resolve argv[0] to reflect path search
|
||||
if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
||||
!StrCmp(BaseName(prog), argv[0])) {
|
||||
tp -= (n = StrLen(exe) + 1);
|
||||
MemMove(tp, exe, n);
|
||||
argv[0] = tp;
|
||||
}
|
||||
|
||||
// squeeze and align the argument block
|
||||
ip = (long *)(((long)tp - AUXV_BYTES) & -sizeof(long));
|
||||
ip -= (n = bp - sp);
|
||||
ip = (long *)((long)ip & -STACK_ALIGN);
|
||||
MemMove(ip, sp, n * sizeof(long));
|
||||
bp = ip + n;
|
||||
sp = ip;
|
||||
|
||||
// relocate the guest's random numbers
|
||||
MemMove(M->rando, rando, sizeof(M->rando));
|
||||
Bzero(rando, sizeof(rando));
|
||||
|
||||
// ape intended behavior
|
||||
// 1. if file is an elf executable, it'll be used as-is
|
||||
// 2. if ape, will scan shell script for elf printf statements
|
||||
// 3. shell script may have multiple lines producing elf headers
|
||||
// 4. all elf printf lines must exist in the first 8192 bytes of file
|
||||
// 5. elf program headers may appear anywhere in the binary
|
||||
if (READ64(M->ehdr.buf) == READ64("MZqFpD='") ||
|
||||
READ64(M->ehdr.buf) == READ64("jartsr='") ||
|
||||
READ64(M->ehdr.buf) == READ64("APEDBG='")) {
|
||||
for (p = M->ehdr.buf; p < pe; ++p) {
|
||||
if (READ64(p) != READ64("printf '")) {
|
||||
continue;
|
||||
}
|
||||
for (i = 0, p += 8; p + 3 < pe && (c = *p++) != '\'';) {
|
||||
if (c == '\\') {
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c = *p++ - '0';
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c *= 8;
|
||||
c += *p++ - '0';
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c *= 8;
|
||||
c += *p++ - '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
M->ehdr.buf[i++] = c;
|
||||
if (i >= sizeof(M->ehdr.buf)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= sizeof(M->ehdr.ehdr)) {
|
||||
TryElf(M, exe, fd, sp, bp, execfn);
|
||||
}
|
||||
}
|
||||
}
|
||||
Pexit(exe, 0, TryElf(M, exe, fd, sp, bp, execfn));
|
||||
}
|
||||
@@ -43,7 +43,6 @@
|
||||
#include "libc/nt/pedef.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "ape/ape.internal.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
#define USE_SYMBOL_HACK 1
|
||||
@@ -224,7 +223,7 @@ stub: mov $0x40,%dl // *literally* dos
|
||||
3: .byte 0xbd,0,0 // a.k.a. mov imm,%bp
|
||||
jmp pc // real mode, is real
|
||||
jmp _start // surprise it's unix
|
||||
.endfn stub,globl
|
||||
.endfn stub
|
||||
|
||||
/*─────────────────────────────────────────────────────────────────────────────╗
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
|
||||
@@ -599,40 +598,40 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||
// modify the binary to follow the local system's convention.
|
||||
// There isn't a one-size-fits-all approach for this, thus we
|
||||
// present two choices.
|
||||
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||
// Try to use system-wide APE loader.
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && "
|
||||
.ascii "type ape >/dev/null 2>&1 && "
|
||||
.ascii "exec ape \"$o\" \"$@\"\n"
|
||||
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||
// Try to use a system-wide APE loader.
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && "
|
||||
.ascii "type ape >/dev/null 2>&1 && "
|
||||
.ascii "exec ape \"$o\" \"$@\"\n"
|
||||
#ifdef APE_LOADER
|
||||
// There is no system-wide APE loader, but there is one
|
||||
// embedded inside the APE. So if the system is not MacOs,
|
||||
// extract the loader into a temp folder, and use it to
|
||||
// load the APE without modifying it.
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.5\"\n"
|
||||
.ascii "[ -x \"$t\" ] || {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" &&\n"
|
||||
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
|
||||
.shstub ape_loader_dd_skip,2
|
||||
.ascii " count="
|
||||
.shstub ape_loader_dd_count,2
|
||||
.ascii " bs=64 2>/dev/null\n"
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape\"\n"
|
||||
.ascii "[ -x \"$t\" ] || {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" &&\n"
|
||||
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
|
||||
.shstub ape_loader_dd_skip,2
|
||||
.ascii " count="
|
||||
.shstub ape_loader_dd_count,2
|
||||
.ascii " bs=64 2>/dev/null\n"
|
||||
#if SupportsXnu()
|
||||
.ascii "[ -d /Applications ] && "
|
||||
.ascii "dd if=\"$t.$$\""
|
||||
.ascii " of=\"$t.$$\""
|
||||
.ascii " skip=5"
|
||||
.ascii " count=8"
|
||||
.ascii " bs=64"
|
||||
.ascii " conv=notrunc"
|
||||
.ascii " 2>/dev/null\n"
|
||||
.ascii "[ -d /Applications ] && "
|
||||
.ascii "dd if=\"$t.$$\""
|
||||
.ascii " of=\"$t.$$\""
|
||||
.ascii " skip=6"
|
||||
.ascii " count=10"
|
||||
.ascii " bs=64"
|
||||
.ascii " conv=notrunc"
|
||||
.ascii " 2>/dev/null\n"
|
||||
#endif /* SupportsXnu() */
|
||||
.ascii "chmod 755 \"$t.$$\"\n"
|
||||
.ascii "mv -f \"$t.$$\" \"$t\"\n"
|
||||
.ascii "}\n"
|
||||
.ascii "exec \"$t\" \"$o\" \"$@\"\n"
|
||||
.ascii "chmod 755 \"$t.$$\"\n"
|
||||
.ascii "mv -f \"$t.$$\" \"$t\"\n"
|
||||
.ascii "}\n"
|
||||
.ascii "exec \"$t\" \"$o\" \"$@\"\n"
|
||||
.ascii "}\n"
|
||||
#endif /* APE_LOADER */
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
// The default behavior is: to overwrite the header in place.
|
||||
@@ -642,91 +641,155 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||
// The alternative behavior is to copy to $TMPDIR or $HOME or
|
||||
// the current directory. We like TMPDIR because it's part of
|
||||
// the IEEE POSIX standard whereas alternatives (XDG) aren't.
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/$0\"\n"
|
||||
.ascii "[ x\"$1\" != x--assimilate ] || [ ! -e \"$t\" ] && {\n"
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" 2>/dev/null\n"
|
||||
.ascii "cp -f \"$o\" \"$t.$$\" &&\n"
|
||||
.ascii "mv -f \"$t.$$\" \"$t\" || exit 120\n"
|
||||
.ascii "o=\"$t\"\n"
|
||||
.ascii "}\n"
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "exec 7<> \"$o\" || exit 121\n"
|
||||
.ascii "printf '"
|
||||
.ascii "\\177ELF" // 0x0: ⌂ELF
|
||||
.ascii "\\2" // 4: long mode
|
||||
.ascii "\\1" // 5: little endian
|
||||
.ascii "\\1" // 6: elf v1.o
|
||||
.ascii "\\011" // 7: FreeBSD
|
||||
.ascii "\\0" // 8: os/abi ver.
|
||||
.ascii "\\0\\0\\0" // 9: padding 3/7
|
||||
.ascii "\\0\\0\\0\\0" // padding 4/7
|
||||
.ascii "\\2\\0" // 10: εxεcµταblε
|
||||
.ascii "\\076\\0" // 12: NexGen32e
|
||||
.ascii "\\1\\0\\0\\0" // 14: elf v1.o
|
||||
.shstub ape_elf_entry,8 // 18: e_entry
|
||||
.shstub ape_elf_phoff,8 // 20: e_phoff
|
||||
.shstub ape_elf_shoff,8 // 28: e_shoff
|
||||
.ascii "\\0\\0\\0\\0" // 30: e_flags
|
||||
.ascii "\\100\\0" // 34: e_ehsize
|
||||
.ascii "\\070\\0" // 36: e_phentsize
|
||||
.shstub ape_elf_phnum,2 // 38: e_phnum
|
||||
.ascii "\\0\\0" // 3a: e_shentsize
|
||||
.shstub ape_elf_shnum,2 // 3c: e_shnum
|
||||
.shstub ape_elf_shstrndx,2 // 3e: e_shstrndx
|
||||
.ascii "' >&7\n"
|
||||
.ascii "exec 7<&-\n"
|
||||
#if SupportsXnu()
|
||||
.ascii "[ -d /Applications ] && "
|
||||
.ascii "dd if=\"$o\""
|
||||
.ascii " of=\"$o\""
|
||||
.ascii " bs=8"
|
||||
.ascii " skip="
|
||||
.shstub ape_macho_dd_skip,2
|
||||
.ascii " count="
|
||||
.shstub ape_macho_dd_count,2
|
||||
.ascii " conv=notrunc 2>/dev/null\n"
|
||||
#endif /* XNU */
|
||||
.ascii "[ x\"$1\" = x--assimilate ] && exit 0\n"
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
.ascii "exec \"$0\" \"$@\"\n" // try to preserve argv[0]
|
||||
#else
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/$0\"\n"
|
||||
.ascii "[ x\"$1\" != x--assimilate ] || [ ! -e \"$t\" ] && {\n"
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" 2>/dev/null\n"
|
||||
.ascii "cp -f \"$o\" \"$t.$$\" &&\n"
|
||||
.ascii "mv -f \"$t.$$\" \"$t\" || exit 120\n"
|
||||
.ascii "o=\"$t\"\n"
|
||||
.ascii "}\n"
|
||||
.ascii "o=\"$t\"\n"
|
||||
.ascii "exec \"$o\" \"$@\"\n"
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "exit $?\n"
|
||||
.ascii "fi\n" // x86_64
|
||||
// ...
|
||||
// decentralized section (.apesh)
|
||||
// ...
|
||||
.ascii "exec 7<> \"$o\" || exit 121\n"
|
||||
.ascii "printf '"
|
||||
.ascii "\\177ELF" // 0x0: ⌂ELF
|
||||
.ascii "\\2" // 4: long mode
|
||||
.ascii "\\1" // 5: little endian
|
||||
.ascii "\\1" // 6: elf v1.o
|
||||
.ascii "\\011" // 7: FreeBSD
|
||||
.ascii "\\0" // 8: os/abi ver.
|
||||
.ascii "\\0\\0\\0" // 9: padding 3/7
|
||||
.ascii "\\0\\0\\0\\0" // padding 4/7
|
||||
.ascii "\\2\\0" // 10: εxεcµταblε
|
||||
.ascii "\\076\\0" // 12: NexGen32e
|
||||
.ascii "\\1\\0\\0\\0" // 14: elf v1.o
|
||||
.shstub ape_elf_entry,8 // 18: e_entry
|
||||
.shstub ape_elf_phoff,8 // 20: e_phoff
|
||||
.shstub ape_elf_shoff,8 // 28: e_shoff
|
||||
.ascii "\\0\\0\\0\\0" // 30: e_flags
|
||||
.ascii "\\100\\0" // 34: e_ehsize
|
||||
.ascii "\\070\\0" // 36: e_phentsize
|
||||
.shstub ape_elf_phnum,2 // 38: e_phnum
|
||||
.ascii "\\0\\0" // 3a: e_shentsize
|
||||
.shstub ape_elf_shnum,2 // 3c: e_shnum
|
||||
.shstub ape_elf_shstrndx,2 // 3e: e_shstrndx
|
||||
.ascii "' >&7\n"
|
||||
.ascii "exec 7<&-\n"
|
||||
#if SupportsXnu()
|
||||
.ascii "[ -d /Applications ] && "
|
||||
.ascii "dd if=\"$o\""
|
||||
.ascii " of=\"$o\""
|
||||
.ascii " bs=8"
|
||||
.ascii " skip="
|
||||
.shstub ape_macho_dd_skip,2
|
||||
.ascii " count="
|
||||
.shstub ape_macho_dd_count,2
|
||||
.ascii " conv=notrunc 2>/dev/null\n"
|
||||
#endif /* XNU */
|
||||
.ascii "[ x\"$1\" = x--assimilate ] && exit 0\n"
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
.ascii "exec \"$0\" \"$@\"\n" // try to preserve argv[0]
|
||||
#else
|
||||
.ascii "}\n"
|
||||
.ascii "o=\"$t\"\n"
|
||||
.ascii "exec \"$o\" \"$@\"\n"
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "exit $?\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
.ascii "PHDRS='' <<'@'\n"
|
||||
.endobj apesh
|
||||
|
||||
#if !IsTiny()
|
||||
// elf program headers get inserted here
|
||||
// because they need to be in the first 4096 bytes
|
||||
.section .emushprologue,"a",@progbits
|
||||
.section .emush,"a",@progbits
|
||||
emush: .ascii "\n@\n#'\"\n"
|
||||
.ascii "s=\"$(uname -s)\"\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"
|
||||
.ascii "e=\"${TMPDIR:-${HOME:-.}}/.ape-blink-0.9.2\"\n"
|
||||
|
||||
// Blink for Apple Silicon, e.g. M1 Macbook
|
||||
.ascii "if [ \"$s\" = Darwin ] && [ \"$m\" = arm64 ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-darwin-arm64 to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_darwin_arm64_b9
|
||||
.byte blink_darwin_arm64_b8
|
||||
.byte blink_darwin_arm64_b7
|
||||
.byte blink_darwin_arm64_b6
|
||||
.byte blink_darwin_arm64_b5
|
||||
.byte blink_darwin_arm64_b4
|
||||
.byte blink_darwin_arm64_b3
|
||||
.byte blink_darwin_arm64_b2
|
||||
.byte blink_darwin_arm64_b1
|
||||
.byte blink_darwin_arm64_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_darwin_arm64_size_b9
|
||||
.byte blink_darwin_arm64_size_b8
|
||||
.byte blink_darwin_arm64_size_b7
|
||||
.byte blink_darwin_arm64_size_b6
|
||||
.byte blink_darwin_arm64_size_b5
|
||||
.byte blink_darwin_arm64_size_b4
|
||||
.byte blink_darwin_arm64_size_b3
|
||||
.byte blink_darwin_arm64_size_b2
|
||||
.byte blink_darwin_arm64_size_b1
|
||||
.byte blink_darwin_arm64_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Aarch64 Linux, e.g. Raspberry Pi
|
||||
.ascii "if [ \"$s\" = Linux ]; then\n"
|
||||
.ascii "if [ \"$m\" = aarch64 ] || [ \"$m\" = arm64 ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-aarch64 to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_aarch64_b9
|
||||
.byte blink_aarch64_b8
|
||||
.byte blink_aarch64_b7
|
||||
.byte blink_aarch64_b6
|
||||
.byte blink_aarch64_b5
|
||||
.byte blink_aarch64_b4
|
||||
.byte blink_aarch64_b3
|
||||
.byte blink_aarch64_b2
|
||||
.byte blink_aarch64_b1
|
||||
.byte blink_aarch64_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_aarch64_size_b9
|
||||
.byte blink_aarch64_size_b8
|
||||
.byte blink_aarch64_size_b7
|
||||
.byte blink_aarch64_size_b6
|
||||
.byte blink_aarch64_size_b5
|
||||
.byte blink_aarch64_size_b4
|
||||
.byte blink_aarch64_size_b3
|
||||
.byte blink_aarch64_size_b2
|
||||
.byte blink_aarch64_size_b1
|
||||
.byte blink_aarch64_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
.ascii "echo unsupported architecture >&2\n"
|
||||
.rept 16
|
||||
.ascii "exit 127\n"
|
||||
.endr
|
||||
|
||||
.ascii "exit 1\n"
|
||||
.previous
|
||||
.endobj emush
|
||||
#endif /* !IsTiny() */
|
||||
|
||||
#ifdef APE_LOADER
|
||||
.section .ape.loader,"a",@progbits
|
||||
@@ -747,15 +810,6 @@ ape_loader_end:
|
||||
|
||||
.long PT_LOAD
|
||||
.long PF_R|PF_X
|
||||
.stub ape_cod_offset,quad
|
||||
.stub ape_cod_vaddr,quad
|
||||
.stub ape_cod_paddr,quad
|
||||
.stub ape_cod_filesz,quad
|
||||
.stub ape_cod_memsz,quad
|
||||
.stub ape_cod_align,quad
|
||||
|
||||
.long PT_LOAD
|
||||
.long PF_R
|
||||
.stub ape_rom_offset,quad
|
||||
.stub ape_rom_vaddr,quad
|
||||
.stub ape_rom_paddr,quad
|
||||
@@ -794,38 +848,24 @@ ape_loader_end:
|
||||
.stub ape_stack_vaddr,quad // is mmap()'d with MAP_FIXED
|
||||
.stub ape_stack_paddr,quad // ignored
|
||||
.stub ape_stack_filesz,quad // ignored
|
||||
.stub ape_stack_memsz2,quad // is mmap(size) argument
|
||||
.stub ape_stack_memsz,quad // is mmap(size) argument
|
||||
.stub ape_stack_align,quad // must be 16+
|
||||
|
||||
#if SupportsOpenbsd() || SupportsNetbsd()
|
||||
.long PT_NOTE
|
||||
.long PF_R
|
||||
.stub ape_note_offset,quad
|
||||
.quad 0
|
||||
.quad 0
|
||||
.stub ape_note_vaddr,quad
|
||||
.stub ape_note_paddr,quad
|
||||
.stub ape_note_filesz,quad
|
||||
.stub ape_note_memsz,quad
|
||||
.quad 4
|
||||
.stub ape_note_align,quad
|
||||
#endif
|
||||
.previous
|
||||
#endif /* SupportsSystemv() || SupportsMetal() */
|
||||
|
||||
.section .note.ape.ident,"a",@progbits
|
||||
.balign 4
|
||||
ape.ident:
|
||||
.long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "APE"
|
||||
2: .balign 4
|
||||
3: .long 105000000
|
||||
4: .size ape.ident,.-ape.ident
|
||||
.type ape.ident,@object
|
||||
.previous
|
||||
|
||||
#if SupportsOpenbsd()
|
||||
.section .note.openbsd.ident,"a",@progbits
|
||||
.balign 4
|
||||
openbsd.ident:
|
||||
.long 2f-1f
|
||||
.long 4f-3f
|
||||
@@ -840,7 +880,6 @@ openbsd.ident:
|
||||
|
||||
#if SupportsNetbsd()
|
||||
.section .note.netbsd.ident,"a",@progbits
|
||||
.balign 4
|
||||
netbsd.ident:
|
||||
.long 2f-1f
|
||||
.long 4f-3f
|
||||
@@ -893,8 +932,8 @@ ape_macho:
|
||||
.long MAC_CPU_NEXGEN32E
|
||||
.long MAC_CPU_NEXGEN32E_ALL
|
||||
.long MAC_EXECUTE
|
||||
.long 6 // number of load commands
|
||||
.long 70f-10f // size of all load commands
|
||||
.long 5 // number of load commands
|
||||
.long 60f-10f // size of all load commands
|
||||
.long MAC_NOUNDEFS // flags
|
||||
.long 0 // reserved
|
||||
10: .long MAC_LC_SEGMENT_64
|
||||
@@ -905,27 +944,26 @@ ape_macho:
|
||||
20: .long MAC_LC_SEGMENT_64
|
||||
.long 30f-20b
|
||||
.ascin "__TEXT",16
|
||||
.stub ape_cod_vaddr,quad
|
||||
.stub ape_cod_memsz,quad
|
||||
.stub ape_cod_offset,quad
|
||||
.stub ape_cod_filesz,quad
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE // maxprot
|
||||
.long PROT_EXEC|PROT_READ // initprot
|
||||
.long 0 // segment section count
|
||||
.long 0 // flags
|
||||
30: .long MAC_LC_SEGMENT_64
|
||||
.long 40f-30b
|
||||
.ascin "__RODATA",16
|
||||
.stub ape_rom_vaddr,quad
|
||||
.stub ape_rom_memsz,quad
|
||||
.stub ape_rom_offset,quad
|
||||
.stub ape_rom_filesz,quad
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE // maxprot
|
||||
.long PROT_READ // initprot
|
||||
.long 0 // segment section count
|
||||
.long PROT_EXEC|PROT_READ // initprot
|
||||
.long 1 // segment section count
|
||||
.long 0 // flags
|
||||
40: .long MAC_LC_SEGMENT_64
|
||||
.long 50f-40b
|
||||
210: .ascin "__text",16 // section name (.text)
|
||||
.ascin "__TEXT",16
|
||||
.stub ape_text_vaddr,quad
|
||||
.stub ape_text_memsz,quad
|
||||
.stub ape_text_offset,long
|
||||
.long 12 // align 2**12 = 4096
|
||||
.long 0 // reloc table offset
|
||||
.long 0 // relocation count
|
||||
.long MAC_S_ATTR_SOME_INSTRUCTIONS // section type & attributes
|
||||
.long 0,0,0 // reserved
|
||||
30: .long MAC_LC_SEGMENT_64
|
||||
.long 40f-30b
|
||||
.ascin "__DATA",16
|
||||
.stub ape_ram_vaddr,quad
|
||||
.stub ape_ram_memsz,quad
|
||||
@@ -933,19 +971,39 @@ ape_macho:
|
||||
.stub ape_ram_filesz,quad
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE // maxprot
|
||||
.long PROT_READ|PROT_WRITE // initprot
|
||||
.long 0 // segment section count
|
||||
.long 2 // segment section count
|
||||
.long 0 // flags
|
||||
50: .long MAC_LC_UUID
|
||||
.long 60f-50b
|
||||
310: .ascin "__data",16 // section name (.data)
|
||||
.ascin "__DATA",16
|
||||
.stub ape_data_vaddr,quad
|
||||
.stub ape_data_memsz,quad
|
||||
.stub ape_data_offset,long
|
||||
.long 12 // align 2**12 = 4096
|
||||
.long 0 // reloc table offset
|
||||
.long 0 // relocation count
|
||||
.long 0 // section type & attributes
|
||||
.long 0,0,0 // reserved
|
||||
320: .ascin "__bss",16 // section name (.bss)
|
||||
.ascin "__DATA",16
|
||||
.stub ape_bss_vaddr,quad // virtual address
|
||||
.stub ape_bss_memsz,quad // memory size
|
||||
.long 0 // file offset
|
||||
.long 12 // align 2**12 = 4096
|
||||
.long 0 // reloc table offset
|
||||
.long 0 // relocation count
|
||||
.long MAC_S_ZEROFILL // section type & attributes
|
||||
.long 0,0,0 // reserved
|
||||
40: .long MAC_LC_UUID
|
||||
.long 50f-40b
|
||||
.stub ape_uuid1,quad
|
||||
.stub ape_uuid2,quad
|
||||
60: .long MAC_LC_UNIXTHREAD
|
||||
.long 70f-60b // cmdsize
|
||||
50: .long MAC_LC_UNIXTHREAD
|
||||
.long 60f-50b // cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E // flavaflav
|
||||
.long (620f-610f)/4 // count
|
||||
610: .quad 0 // rax
|
||||
.quad 0 // rbx
|
||||
.quad 0 // rcx
|
||||
.long (520f-510f)/4 // count
|
||||
510: .quad 0 // rax
|
||||
.quad IMAGE_BASE_VIRTUAL // rbx
|
||||
.quad _HOSTXNU // rcx
|
||||
.quad 0 // rdx
|
||||
.quad 0 // rdi
|
||||
.quad 0 // rsi
|
||||
@@ -959,13 +1017,13 @@ ape_macho:
|
||||
.quad 0 // r13
|
||||
.quad 0 // r14
|
||||
.quad 0 // r15
|
||||
.quad _apple // rip
|
||||
.quad _start // rip
|
||||
.quad 0 // rflags
|
||||
.quad 0 // cs
|
||||
.quad 0 // fs
|
||||
.quad 0 // gs
|
||||
620:
|
||||
70:
|
||||
520:
|
||||
60:
|
||||
|
||||
.endobj ape_macho,globl,hidden
|
||||
.previous /* .macho */
|
||||
@@ -1067,8 +1125,8 @@ ape_pe: .ascin "PE",4
|
||||
.long RVA(ape_pe_entry) // EntryPoint
|
||||
.long 0 // BaseOfCode
|
||||
.quad ape_pe_base // ImageBase
|
||||
.long ape_pe_sectionalignment // SectionAlignment
|
||||
.long ape_pe_filealignment // FileAlignment
|
||||
.long 4096 // SectionAlignment
|
||||
.long 4096 // FileAlignment
|
||||
.short v_ntversion // MajorOperatingSystemVersion
|
||||
.short 0 // MinorOperatingSystemVersion
|
||||
.short 0 // MajorImageVersion
|
||||
@@ -1077,7 +1135,7 @@ ape_pe: .ascin "PE",4
|
||||
.short 0 // MinorSubsystemVersion
|
||||
.long 0 // Win32VersionValue
|
||||
.long RVA(_end) // SizeOfImage
|
||||
.long ape_pe_sizeofheaders // SizeOfHeaders
|
||||
.long RVA(_ehead) // SizeOfHeaders
|
||||
.long 0 // Checksum
|
||||
.short v_ntsubsystem // Subsystem: 0=Neutral,2=GUI,3=Console
|
||||
.stub v_ntdllchar,short // DllCharacteristics
|
||||
@@ -1086,10 +1144,25 @@ ape_pe: .ascin "PE",4
|
||||
.quad 0 // HeapReserve
|
||||
.quad 0 // HeapCommit
|
||||
.long 0 // LoaderFlags
|
||||
.long 2 // NumberOfDirectoryEntries
|
||||
.long 16 // NumberOfDirectoryEntries
|
||||
.long 0,0 // ExportsDirectory
|
||||
.stub ape_idata,long // ImportsDirectory
|
||||
.stub ape_idata_idtsize,long // ImportsDirectorySize
|
||||
.long 0,0 // ResourcesDirectory
|
||||
.long 0,0 // ExceptionsDirectory
|
||||
.long 0,0 // SecurityDirectory
|
||||
.long 0,0 // BaseRelocationTable
|
||||
.long 0,0 // DebugDirectory
|
||||
.long 0,0 // DescriptionString
|
||||
.long 0,0 // MachineSpecific
|
||||
.long 0,0 // ThreadLocalStorage
|
||||
.long 0,0 // LoadConfigurationDirectory
|
||||
.long 0,0 // BoundImportDirectory
|
||||
.stub ape_idata,long // ImportAddressDirectory
|
||||
.stub ape_idata_iatsize,long // ImportAddressDirectorySize
|
||||
.long 0,0 // DelayImportDescriptor
|
||||
.long 0,0 // ComPlusRuntimeHeader
|
||||
.long 0,0 // Reserved
|
||||
.endobj ape_pe,globl
|
||||
.previous
|
||||
|
||||
@@ -1718,7 +1791,7 @@ ape_grub_entry:
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § cosmopolitan libc runtime runtime ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
kernel: movabs $ape_stack_vaddr,%rsp
|
||||
add $ape_stack_memsz2,%rsp
|
||||
add $ape_stack_memsz,%rsp
|
||||
movl $0,0x7b000 // unmap null 2mb
|
||||
#if USE_SYMBOL_HACK
|
||||
.byte 0x0f,0x1f,0207 // nop rdi binbase
|
||||
@@ -1776,6 +1849,7 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
.ldsvar v_ape_realbytes
|
||||
.ldsvar v_ape_highsectors
|
||||
.ldsvar ape_idata_ro
|
||||
.ldsvar ape_pad_rodata
|
||||
.ldsvar ape_piro
|
||||
.ldsvar ape_piro_end
|
||||
.type ape_macho_end,@object
|
||||
@@ -1789,10 +1863,10 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
.type __test_end,@object
|
||||
|
||||
.section .commentprologue,"a",@progbits
|
||||
.globl __comment_start
|
||||
.type __comment_start,@object
|
||||
.hidden __comment_start
|
||||
__comment_start:/*
|
||||
.globl kLegalNotices
|
||||
.type kLegalNotices,@object
|
||||
.hidden kLegalNotices
|
||||
kLegalNotices:/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
@@ -1819,6 +1893,12 @@ ape_pad_text:
|
||||
ape_pad_privileged:
|
||||
.previous
|
||||
|
||||
.section .ape.pad.rodata,"a",@progbits
|
||||
.type ape_pad_rodata,@object
|
||||
.hidden ape_pad_rodata
|
||||
ape_pad_rodata:
|
||||
.previous
|
||||
|
||||
.section .ape.pad.data,"a",@progbits
|
||||
.type ape_pad_data,@object
|
||||
.hidden ape_pad_data
|
||||
@@ -1861,9 +1941,27 @@ __bss_start:
|
||||
__bss_end:
|
||||
.previous
|
||||
|
||||
.section .fstls,"awT",@nobits
|
||||
.align TLS_ALIGNMENT
|
||||
#if !IsTiny()
|
||||
#ifdef APE_IS_SHELL_SCRIPT
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_aarch64_size
|
||||
blink_aarch64:
|
||||
.incbin "ape/blink-aarch64.gz"
|
||||
.endobj blink_aarch64,globl
|
||||
blink_aarch64_size = . - blink_aarch64
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_darwin_arm64_size
|
||||
blink_darwin_arm64:
|
||||
.incbin "ape/blink-darwin-arm64.gz"
|
||||
.endobj blink_darwin_arm64,globl
|
||||
blink_darwin_arm64_size = . - blink_darwin_arm64
|
||||
.previous
|
||||
|
||||
#endif /* APE_IS_SHELL_SCRIPT */
|
||||
#endif /* !IsTiny() */
|
||||
|
||||
.end
|
||||
|
||||
+204
-197
@@ -182,9 +182,7 @@
|
||||
#include "libc/nt/pedef.internal.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "ape/ape.internal.h"
|
||||
|
||||
/* uncomment if .com.dbg won't execute on your kernel (will break .com file) */
|
||||
/* #define APE_FIX_COM_DBG */
|
||||
#include "libc/zip.h"
|
||||
|
||||
#ifdef __x86__
|
||||
#define CODE_GRANULE 1
|
||||
@@ -192,24 +190,14 @@
|
||||
#define CODE_GRANULE 4
|
||||
#endif
|
||||
|
||||
#ifdef APE_FIX_COM_DBG
|
||||
#define SKEW SIZEOF_HEADERS
|
||||
#else
|
||||
#define SKEW 0
|
||||
#endif
|
||||
|
||||
#if IMAGE_BASE_VIRTUAL > 0xffffffff
|
||||
#error "please use 32-bit addresses for image data"
|
||||
#endif
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS {
|
||||
Head PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Cod PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Rom PT_LOAD FLAGS(PF_R);
|
||||
Tls PT_TLS FLAGS(PF_W|PF_R);
|
||||
Rom PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Ram PT_LOAD FLAGS(PF_W|PF_R);
|
||||
Tls PT_TLS FLAGS(PF_W|PF_R);
|
||||
Bss PT_LOAD FLAGS(PF_W|PF_R);
|
||||
stack PT_GNU_STACK FLAGS(PF_W|PF_R);
|
||||
}
|
||||
|
||||
@@ -220,49 +208,44 @@ SECTIONS {
|
||||
/*BEGIN: linux addressability guarantee */
|
||||
/*BEGIN: bsd addressability guarantee */
|
||||
|
||||
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) + SKEW : AT(IMAGE_BASE_REAL) {
|
||||
__executable_start = .;
|
||||
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : AT(IMAGE_BASE_REAL) {
|
||||
HIDDEN(_base = .);
|
||||
|
||||
/* Real Mode */
|
||||
KEEP(*(.head))
|
||||
KEEP(*(.apesh))
|
||||
KEEP(*(.head2))
|
||||
KEEP(*(.text.head))
|
||||
|
||||
/* Executable & Linkable Format */
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
ape_phdrs = .;
|
||||
HIDDEN(ape_phdrs = .);
|
||||
KEEP(*(.elf.phdrs))
|
||||
ape_phdrs_end = .;
|
||||
HIDDEN(ape_phdrs_end = .);
|
||||
|
||||
KEEP(*(.emushprologue))
|
||||
KEEP(*(.emush))
|
||||
KEEP(*(.emushepilogue))
|
||||
|
||||
/* OpenBSD */
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
ape_note = .;
|
||||
HIDDEN(ape_note = .);
|
||||
KEEP(*(.note.openbsd.ident))
|
||||
KEEP(*(.note.netbsd.ident))
|
||||
ape_note_end = .;
|
||||
HIDDEN(ape_note_end = .);
|
||||
|
||||
/* Portable Executable */
|
||||
KEEP(*(.pe.header))
|
||||
ape_pe_sections = .;
|
||||
HIDDEN(ape_pe_sections = .);
|
||||
KEEP(*(.pe.sections))
|
||||
ape_pe_sections_end = .;
|
||||
HIDDEN(ape_pe_sections_end = .);
|
||||
|
||||
/* Mach-O */
|
||||
KEEP(*(.macho))
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
ape_macho_end = .;
|
||||
|
||||
/* APE loader */
|
||||
KEEP(*(.ape.loader))
|
||||
. = ALIGN(CODE_GRANULE);
|
||||
HIDDEN(ape_macho_end = .);
|
||||
|
||||
KEEP(*(.ape.pad.head))
|
||||
. = ALIGN(SupportsWindows() || SupportsMetal() ? CONSTANT(COMMONPAGESIZE) : 16);
|
||||
_ehead = .;
|
||||
. = ALIGN(SupportsWindows() || SupportsMetal() ? PAGESIZE : 16);
|
||||
HIDDEN(_ehead = .);
|
||||
} :Head
|
||||
|
||||
/*BEGIN: nt addressability guarantee */
|
||||
@@ -272,7 +255,10 @@ SECTIONS {
|
||||
/* Code that needs to be addressable in Real Mode */
|
||||
*(.text.real)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.real.*)))
|
||||
_ereal = .;
|
||||
/* Code we want earlier in the binary w/o modifications */
|
||||
KEEP(*(.ape.loader))
|
||||
. = ALIGN(CODE_GRANULE);
|
||||
HIDDEN(_ereal = .);
|
||||
/*END: realmode addressability guarantee */
|
||||
/*BEGIN: morphable code */
|
||||
. += CODE_GRANULE;
|
||||
@@ -305,6 +291,7 @@ SECTIONS {
|
||||
KEEP(*(.keep.text))
|
||||
*(.text .stub .text.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.*)))
|
||||
*(.subrs)
|
||||
|
||||
KEEP(*(.ape.pad.test));
|
||||
*(.test.unlikely)
|
||||
@@ -312,20 +299,16 @@ SECTIONS {
|
||||
|
||||
/* Privileged code invulnerable to magic */
|
||||
KEEP(*(.ape.pad.privileged));
|
||||
. = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 1);
|
||||
. = ALIGN(__privileged_end > __privileged_start ? PAGESIZE : 1);
|
||||
/*END: morphable code */
|
||||
__privileged_start = .;
|
||||
HIDDEN(__privileged_start = .);
|
||||
*(.privileged)
|
||||
__privileged_end = .;
|
||||
|
||||
KEEP(*(.ape.pad.text))
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
/*END: Read Only Data (only needed for initialization) */
|
||||
} :Cod
|
||||
HIDDEN(__privileged_end = .);
|
||||
. += . > 0 ? CODE_GRANULE : 0;
|
||||
|
||||
/*BEGIN: Read Only Data */
|
||||
|
||||
.rodata . : {
|
||||
KEEP(*(.ape.pad.rodata));
|
||||
KEEP(*(.rodata.pytab.0));
|
||||
KEEP(*(.rodata.pytab.1));
|
||||
KEEP(*(.rodata.pytab.2));
|
||||
@@ -334,6 +317,10 @@ SECTIONS {
|
||||
*(.ubsan.types)
|
||||
*(.ubsan.data)
|
||||
|
||||
/* Unit Test & Fixture Registry */
|
||||
|
||||
/*BEGIN: Read only data that needn't be mapped after initialization */
|
||||
|
||||
/* Legal Notices */
|
||||
#if !defined(IM_FEELING_NAUGHTY) || defined(EMBED_NOTICES)
|
||||
KEEP(*(.commentprologue))
|
||||
@@ -341,30 +328,25 @@ SECTIONS {
|
||||
KEEP(*(.commentepilogue))
|
||||
#endif
|
||||
|
||||
/*BEGIN: read-only data that's only needed for initialization */
|
||||
|
||||
#if SupportsWindows()
|
||||
/* Windows DLL Import Directory */
|
||||
KEEP(*(.idata.ro));
|
||||
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
|
||||
#endif
|
||||
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
__init_array_start = .;
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP(*(.ctors))
|
||||
KEEP(*(.init_array))
|
||||
KEEP(*(.preinit_array))
|
||||
__init_array_end = .;
|
||||
PROVIDE_HIDDEN(__init_array_end = .);
|
||||
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
__fini_array_start = .;
|
||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(.fini_array))
|
||||
KEEP(*(.dtors))
|
||||
__fini_array_end = .;
|
||||
PROVIDE_HIDDEN(__fini_array_end = .);
|
||||
|
||||
/* Encoded Data Structures w/ Linear Initialization Order */
|
||||
KEEP(*(.initroprologue))
|
||||
@@ -372,8 +354,11 @@ SECTIONS {
|
||||
KEEP(*(.initroepilogue))
|
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
||||
|
||||
/*END: read-only data that's only needed for initialization */
|
||||
|
||||
KEEP(*(.ape.pad.text))
|
||||
. = ALIGN(PAGESIZE);
|
||||
HIDDEN(_etext = .);
|
||||
PROVIDE_HIDDEN(etext = .);
|
||||
/*END: Read Only Data (only needed for initialization) */
|
||||
} :Rom
|
||||
|
||||
/* initialization image for thread-local storage, this is copied */
|
||||
@@ -383,37 +368,27 @@ SECTIONS {
|
||||
*(SORT_BY_ALIGNMENT(.tdata))
|
||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||
_tdata_end = .;
|
||||
KEEP(*(.ape.pad.rodata))
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
_etext = .;
|
||||
PROVIDE(etext = .);
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Tls :Rom
|
||||
/*END: Read Only Data */
|
||||
|
||||
. = DATA_SEGMENT_ALIGN(CONSTANT(COMMONPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||
. = DATA_SEGMENT_RELRO_END(0, .);
|
||||
|
||||
/* this only tells the linker about the layout of uninitialized */
|
||||
/* TLS data, and does not advance the linker's location counter */
|
||||
.tbss : {
|
||||
.tbss . : {
|
||||
_tbss_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tbss))
|
||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||
KEEP(*(.fstls))
|
||||
. = ALIGN(TLS_ALIGNMENT);
|
||||
/* the %fs register is based on this location */
|
||||
_tbss_end = .;
|
||||
} :Tls
|
||||
|
||||
.data . : {
|
||||
.data ALIGN(PAGESIZE) : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
#if SupportsWindows()
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.iat.*)))
|
||||
#endif
|
||||
/*BEGIN: NT FORK COPYING */
|
||||
KEEP(*(.dataprologue))
|
||||
*(.data .data.*)
|
||||
*(.PyRuntime) /* for python */
|
||||
*(.subrs) /* for emacs */
|
||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||
. += . > 0 ? CODE_GRANULE : 0;
|
||||
|
||||
@@ -428,28 +403,30 @@ SECTIONS {
|
||||
/*BEGIN: Post-Initialization Read-Only */
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||
PROVIDE_HIDDEN(__relo_end = .);
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
KEEP(*(.piro.pad.data))
|
||||
KEEP(*(.dataepilogue))
|
||||
. = ALIGN(512);
|
||||
/*END: NT FORK COPYING */
|
||||
_edata = .;
|
||||
PROVIDE(edata = .);
|
||||
_ezip = .; /* <-- very deprecated */
|
||||
HIDDEN(_edata = .);
|
||||
PROVIDE_HIDDEN(edata = .);
|
||||
KEEP(*(SORT_BY_NAME(.zip.*)))
|
||||
HIDDEN(_ezip = .);
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Ram
|
||||
|
||||
/*END: file content that's loaded by o/s */
|
||||
/*END: file content */
|
||||
/*BEGIN: bss memory that's addressable */
|
||||
|
||||
.bss : {
|
||||
.bss ALIGN(64) : {
|
||||
/*BEGIN: NT FORK COPYING */
|
||||
KEEP(*(.bssprologue))
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
|
||||
*(.piro.bss)
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||
__piro_end = .;
|
||||
HIDDEN(__piro_end = .);
|
||||
. += . > 0 ? CODE_GRANULE : 0;
|
||||
/*END: Post-Initialization Read-Only */
|
||||
|
||||
@@ -461,15 +438,11 @@ SECTIONS {
|
||||
KEEP(*(SORT_BY_NAME(.sort.bss.*)))
|
||||
|
||||
KEEP(*(.bssepilogue))
|
||||
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
|
||||
/*END: NT FORK COPYING */
|
||||
_end = .;
|
||||
PROVIDE(end = .);
|
||||
} :Ram
|
||||
|
||||
. = DATA_SEGMENT_END(.);
|
||||
. = ALIGN(PAGESIZE);
|
||||
HIDDEN(_end = .);
|
||||
PROVIDE_HIDDEN(end = .);
|
||||
} :Bss
|
||||
|
||||
/*END: nt addressability guarantee */
|
||||
/*END: bsd addressability guarantee */
|
||||
@@ -512,32 +485,14 @@ SECTIONS {
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||
|
||||
.zip 0 : {
|
||||
KEEP(*(.zip.file))
|
||||
__zip_cdir_start = .;
|
||||
KEEP(*(.zip.cdir))
|
||||
__zip_cdir_size = . - __zip_cdir_start;
|
||||
KEEP(*(.zip.eocd))
|
||||
}
|
||||
|
||||
/DISCARD/ : {
|
||||
#if !SupportsWindows()
|
||||
*(.idata.ro);
|
||||
*(.idata.ro.*)
|
||||
*(.piro.data.sort.iat.*)
|
||||
#endif
|
||||
*(__patchable_function_entries)
|
||||
*(__mcount_loc)
|
||||
*(.discard)
|
||||
*(.yoink)
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
ape_pe_filealignment = 512;
|
||||
ape_pe_sectionalignment = 4096;
|
||||
ape_pe_sizeofheaders = SIZEOF(.head);
|
||||
ape_pe_sizeofimage = ROUNDUP(_end - __executable_start, ape_pe_sectionalignment);
|
||||
|
||||
PFSTUB8(ape_elf_entry, _start);
|
||||
PFSTUB8(ape_elf_phoff, RVA(ape_phdrs));
|
||||
PFSTUB8(ape_elf_shoff, 0);
|
||||
@@ -545,58 +500,70 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
|
||||
PFSTUB4(ape_elf_shnum, 0);
|
||||
PFSTUB4(ape_elf_shstrndx, 0);
|
||||
|
||||
_tls_size = _tbss_end - _tdata_start;
|
||||
_tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tls_align = 1;
|
||||
HIDDEN(_tls_size = _tbss_end - _tdata_start);
|
||||
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
|
||||
HIDDEN(_tbss_size = _tbss_end - _tbss_start);
|
||||
HIDDEN(_tbss_offset = _tbss_start - _tdata_start);
|
||||
HIDDEN(_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start));
|
||||
|
||||
ape_cod_offset = 0;
|
||||
ape_cod_vaddr = ADDR(.head);
|
||||
ape_cod_paddr = LOADADDR(.head);
|
||||
ape_cod_filesz = SIZEOF(.head) + SIZEOF(.text);
|
||||
ape_cod_memsz = ape_cod_filesz;
|
||||
ape_cod_align = CONSTANT(COMMONPAGESIZE);
|
||||
ape_cod_rva = RVA(ape_cod_vaddr);
|
||||
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
||||
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
|
||||
ROUNDDOWN(__privileged_start, PAGESIZE)));
|
||||
|
||||
ape_rom_offset = ape_cod_offset + ape_cod_filesz;
|
||||
ape_rom_vaddr = ADDR(.rodata);
|
||||
ape_rom_paddr = LOADADDR(.rodata);
|
||||
ape_rom_filesz = SIZEOF(.rodata) + SIZEOF(.tdata);
|
||||
ape_rom_memsz = ape_rom_filesz;
|
||||
ape_rom_align = CONSTANT(COMMONPAGESIZE);
|
||||
ape_rom_rva = RVA(ape_rom_vaddr);
|
||||
HIDDEN(ape_rom_offset = 0);
|
||||
HIDDEN(ape_rom_vaddr = ADDR(.head));
|
||||
HIDDEN(ape_rom_paddr = LOADADDR(.head));
|
||||
HIDDEN(ape_rom_filesz = LOADADDR(.data) - ape_rom_paddr);
|
||||
HIDDEN(ape_rom_memsz = ADDR(.data) - ADDR(.head));
|
||||
HIDDEN(ape_rom_align = PAGESIZE);
|
||||
HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr));
|
||||
|
||||
ape_ram_offset = ape_rom_offset + ape_rom_filesz;
|
||||
ape_ram_vaddr = ADDR(.data);
|
||||
ape_ram_paddr = LOADADDR(.data);
|
||||
ape_ram_filesz = SIZEOF(.data);
|
||||
ape_ram_memsz = SIZEOF(.data) + SIZEOF(.bss);
|
||||
ape_ram_align = CONSTANT(COMMONPAGESIZE);
|
||||
ape_ram_rva = RVA(ape_ram_vaddr);
|
||||
HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz);
|
||||
HIDDEN(ape_ram_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_ram_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_ram_filesz = SIZEOF(.data));
|
||||
HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
|
||||
HIDDEN(ape_ram_align = PAGESIZE);
|
||||
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
|
||||
|
||||
ape_stack_pf = DEFINED(ape_stack_pf) ? ape_stack_pf : PF_R | PF_W;
|
||||
ape_stack_prot = _PF2PROT(ape_stack_pf);
|
||||
ape_stack_offset = 0;
|
||||
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
||||
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
|
||||
ape_stack_filesz = 0;
|
||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : APE_STACKSIZE;
|
||||
ape_stack_memsz2 = ape_stack_memsz * 2;
|
||||
ape_stack_align = 16;
|
||||
HIDDEN(ape_stack_pf = DEFINED(ape_stack_pf) ? ape_stack_pf : PF_R | PF_W);
|
||||
HIDDEN(ape_stack_prot = _PF2PROT(ape_stack_pf));
|
||||
HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz);
|
||||
HIDDEN(ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000);
|
||||
HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz);
|
||||
HIDDEN(ape_stack_filesz = 0);
|
||||
HIDDEN(ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : STACKSIZE);
|
||||
HIDDEN(ape_stack_align = 16);
|
||||
|
||||
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
|
||||
ape_note_filesz = ape_note_end - ape_note;
|
||||
ape_note_memsz = ape_note_filesz;
|
||||
HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr));
|
||||
HIDDEN(ape_note_vaddr = ape_note);
|
||||
HIDDEN(ape_note_paddr = ape_rom_paddr + ape_note_offset);
|
||||
HIDDEN(ape_note_filesz = ape_note_end - ape_note);
|
||||
HIDDEN(ape_note_memsz = ape_note_filesz);
|
||||
HIDDEN(ape_note_align = __SIZEOF_POINTER__);
|
||||
|
||||
ape_text_offset = ape_cod_offset + LOADADDR(.text) - ape_cod_paddr;
|
||||
ape_text_paddr = LOADADDR(.text);
|
||||
ape_text_vaddr = ADDR(.text);
|
||||
ape_text_filesz = SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.tdata);
|
||||
ape_text_memsz = ape_text_filesz;
|
||||
ape_text_align = CONSTANT(COMMONPAGESIZE);
|
||||
ape_text_rva = RVA(ape_text_vaddr);
|
||||
HIDDEN(ape_text_offset = ape_rom_offset + LOADADDR(.text) - ape_rom_paddr);
|
||||
HIDDEN(ape_text_paddr = LOADADDR(.text));
|
||||
HIDDEN(ape_text_vaddr = ADDR(.text));
|
||||
HIDDEN(ape_text_filesz = SIZEOF(.text) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_text_memsz = SIZEOF(.text) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_text_align = PAGESIZE);
|
||||
HIDDEN(ape_text_rva = RVA(ape_text_vaddr));
|
||||
|
||||
HIDDEN(ape_data_offset = ape_ram_offset + LOADADDR(.data) - ape_ram_paddr);
|
||||
HIDDEN(ape_data_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_data_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_data_filesz = SIZEOF(.data));
|
||||
HIDDEN(ape_data_memsz = SIZEOF(.data));
|
||||
HIDDEN(ape_data_align = PAGESIZE);
|
||||
HIDDEN(ape_data_rva = RVA(ape_data_vaddr));
|
||||
|
||||
HIDDEN(ape_bss_offset = ape_ram_offset + LOADADDR(.bss) - ape_ram_paddr);
|
||||
HIDDEN(ape_bss_paddr = LOADADDR(.bss));
|
||||
HIDDEN(ape_bss_vaddr = ADDR(.bss));
|
||||
HIDDEN(ape_bss_filesz = 0);
|
||||
HIDDEN(ape_bss_memsz = SIZEOF(.bss));
|
||||
HIDDEN(ape_bss_align = PAGESIZE);
|
||||
|
||||
/* we roundup here because xnu wants the file load segments page-aligned */
|
||||
/* but we don't want to add the nop padding to the ape program, so we'll */
|
||||
@@ -604,42 +571,76 @@ ape_text_rva = RVA(ape_text_vaddr);
|
||||
SHSTUB2(ape_loader_dd_skip, DEFINED(ape_loader) ? RVA(ape_loader) / 64 : 0);
|
||||
SHSTUB2(ape_loader_dd_count,
|
||||
DEFINED(ape_loader_end)
|
||||
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
|
||||
? ROUNDUP(ape_loader_end - ape_loader, PAGESIZE) / 64
|
||||
: 0);
|
||||
|
||||
#if defined(APE_IS_SHELL_SCRIPT) && !IsTiny()
|
||||
|
||||
#define IDENTITY(X) X
|
||||
HIDDEN(blink_aarch64_b0 = RVA(blink_aarch64) % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b1 = RVA(blink_aarch64) < 10 ? 32 : RVA(blink_aarch64) / 10 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b2 = RVA(blink_aarch64) < 100 ? 32 : RVA(blink_aarch64) / 100 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b3 = RVA(blink_aarch64) < 1000 ? 32 : RVA(blink_aarch64) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b4 = RVA(blink_aarch64) < 10000 ? 32 : RVA(blink_aarch64) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b5 = RVA(blink_aarch64) < 100000 ? 32 : RVA(blink_aarch64) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b6 = RVA(blink_aarch64) < 1000000 ? 32 : RVA(blink_aarch64) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b7 = RVA(blink_aarch64) < 10000000 ? 32 : RVA(blink_aarch64) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b8 = RVA(blink_aarch64) < 100000000 ? 32 : RVA(blink_aarch64) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b9 = RVA(blink_aarch64) < 1000000000 ? 32 : RVA(blink_aarch64) / 1000000000 % 10 + 48);
|
||||
|
||||
#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
|
||||
HIDDEN(blink_aarch64_size_b0 = blink_aarch64_size % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b1 = blink_aarch64_size < 10 ? 32 : blink_aarch64_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b2 = blink_aarch64_size < 100 ? 32 : blink_aarch64_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b3 = blink_aarch64_size < 1000 ? 32 : blink_aarch64_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b4 = blink_aarch64_size < 10000 ? 32 : blink_aarch64_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b5 = blink_aarch64_size < 100000 ? 32 : blink_aarch64_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b6 = blink_aarch64_size < 1000000 ? 32 : blink_aarch64_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b7 = blink_aarch64_size < 10000000 ? 32 : blink_aarch64_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b8 = blink_aarch64_size < 100000000 ? 32 : blink_aarch64_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b9 = blink_aarch64_size < 1000000000 ? 32 : blink_aarch64_size / 1000000000 % 10 + 48);
|
||||
|
||||
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);
|
||||
HIDDEN(blink_darwin_arm64_b0 = RVA(blink_darwin_arm64) % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b1 = RVA(blink_darwin_arm64) < 10 ? 32 : RVA(blink_darwin_arm64) / 10 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b2 = RVA(blink_darwin_arm64) < 100 ? 32 : RVA(blink_darwin_arm64) / 100 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b3 = RVA(blink_darwin_arm64) < 1000 ? 32 : RVA(blink_darwin_arm64) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b4 = RVA(blink_darwin_arm64) < 10000 ? 32 : RVA(blink_darwin_arm64) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b5 = RVA(blink_darwin_arm64) < 100000 ? 32 : RVA(blink_darwin_arm64) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b6 = RVA(blink_darwin_arm64) < 1000000 ? 32 : RVA(blink_darwin_arm64) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b7 = RVA(blink_darwin_arm64) < 10000000 ? 32 : RVA(blink_darwin_arm64) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b8 = RVA(blink_darwin_arm64) < 100000000 ? 32 : RVA(blink_darwin_arm64) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b9 = RVA(blink_darwin_arm64) < 1000000000 ? 32 : RVA(blink_darwin_arm64) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_darwin_arm64_size_b0 = blink_darwin_arm64_size % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b1 = blink_darwin_arm64_size < 10 ? 32 : blink_darwin_arm64_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b2 = blink_darwin_arm64_size < 100 ? 32 : blink_darwin_arm64_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b3 = blink_darwin_arm64_size < 1000 ? 32 : blink_darwin_arm64_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b4 = blink_darwin_arm64_size < 10000 ? 32 : blink_darwin_arm64_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b5 = blink_darwin_arm64_size < 100000 ? 32 : blink_darwin_arm64_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b6 = blink_darwin_arm64_size < 1000000 ? 32 : blink_darwin_arm64_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b7 = blink_darwin_arm64_size < 10000000 ? 32 : blink_darwin_arm64_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b8 = blink_darwin_arm64_size < 100000000 ? 32 : blink_darwin_arm64_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b9 = blink_darwin_arm64_size < 1000000000 ? 32 : blink_darwin_arm64_size / 1000000000 % 10 + 48);
|
||||
|
||||
#endif /* APE_IS_SHELL_SCRIPT */
|
||||
|
||||
#if SupportsMetal()
|
||||
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
|
||||
v_ape_realbytes = v_ape_realsectors * 512;
|
||||
v_ape_realdwords = v_ape_realsectors * (512 / 4);
|
||||
v_ape_allsectors = ROUNDUP(RVA(_ezip), 512) / 512;
|
||||
v_ape_allbytes = v_ape_allsectors * 512;
|
||||
v_ape_highsectors = MIN(0xffff, v_ape_allsectors - v_ape_realsectors);
|
||||
HIDDEN(v_ape_realsectors =
|
||||
MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512);
|
||||
HIDDEN(v_ape_realbytes = v_ape_realsectors * 512);
|
||||
HIDDEN(v_ape_realdwords = v_ape_realsectors * (512 / 4));
|
||||
HIDDEN(v_ape_allsectors = ROUNDUP(RVA(_ezip), 512) / 512);
|
||||
HIDDEN(v_ape_allbytes = v_ape_allsectors * 512);
|
||||
HIDDEN(v_ape_highsectors = MIN(0xffff, v_ape_allsectors - v_ape_realsectors));
|
||||
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
||||
#endif
|
||||
|
||||
/* ZIP End of Central Directory header */
|
||||
#define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0);
|
||||
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
|
||||
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
|
||||
ASSERT(v_zip_cdirsize % kZipCdirHdrLinkableSize == 0, "bad zip cdir");
|
||||
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);
|
||||
ZIPCONST(v_zip_commentsize, _ezip - __zip_end - kZipCdirHdrMinSize);
|
||||
|
||||
#if SupportsXnu()
|
||||
/* Generates deterministic ID. */
|
||||
#define PHI 0x9e3779b9925d4c17
|
||||
@@ -658,8 +659,19 @@ TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
||||
KMH(ape_uuid1, X); \
|
||||
XORSHIFT(ape_uuid2, X); \
|
||||
KMH(ape_uuid2, X)
|
||||
ape_uuid1 = 88172645463325252;
|
||||
ape_uuid2 = 88172645463325252;
|
||||
HIDDEN(ape_uuid1 = 88172645463325252);
|
||||
HIDDEN(ape_uuid2 = 88172645463325252);
|
||||
CHURN(ape_bss_align);
|
||||
CHURN(ape_bss_filesz);
|
||||
CHURN(ape_bss_memsz);
|
||||
CHURN(ape_bss_offset);
|
||||
CHURN(ape_bss_paddr);
|
||||
CHURN(ape_data_filesz);
|
||||
CHURN(ape_data_memsz);
|
||||
CHURN(ape_data_offset);
|
||||
CHURN(ape_data_paddr);
|
||||
CHURN(ape_data_rva);
|
||||
CHURN(ape_data_vaddr);
|
||||
CHURN(ape_elf_entry);
|
||||
CHURN(ape_elf_phnum);
|
||||
CHURN(ape_elf_phoff);
|
||||
@@ -668,10 +680,13 @@ CHURN(ape_elf_shoff);
|
||||
CHURN(ape_elf_shstrndx);
|
||||
CHURN(ape_macho_end);
|
||||
CHURN(ape_note);
|
||||
CHURN(ape_note_align);
|
||||
CHURN(ape_note_end);
|
||||
CHURN(ape_note_filesz);
|
||||
CHURN(ape_note_memsz);
|
||||
CHURN(ape_note_offset);
|
||||
CHURN(ape_note_paddr);
|
||||
CHURN(ape_note_vaddr);
|
||||
CHURN(ape_ram_align);
|
||||
CHURN(ape_ram_filesz);
|
||||
CHURN(ape_ram_memsz);
|
||||
@@ -685,14 +700,7 @@ CHURN(ape_rom_memsz);
|
||||
CHURN(ape_rom_offset);
|
||||
CHURN(ape_rom_paddr);
|
||||
CHURN(ape_rom_rva);
|
||||
CHURN(ape_cod_vaddr);
|
||||
CHURN(ape_cod_align);
|
||||
CHURN(ape_cod_filesz);
|
||||
CHURN(ape_cod_memsz);
|
||||
CHURN(ape_cod_offset);
|
||||
CHURN(ape_cod_paddr);
|
||||
CHURN(ape_cod_rva);
|
||||
CHURN(ape_cod_vaddr);
|
||||
CHURN(ape_rom_vaddr);
|
||||
CHURN(ape_text_align);
|
||||
CHURN(ape_text_filesz);
|
||||
CHURN(ape_text_memsz);
|
||||
@@ -725,23 +733,22 @@ CHURN(WinMain);
|
||||
#if SupportsWindows() || SupportsMetal()
|
||||
#define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain))
|
||||
PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
|
||||
ape_pe_optsz = ape_pe_sections - (ape_pe + 24);
|
||||
ASSERT(ape_pe_optsz % 8 == 0, "SizeOfOptionalHeader must be multiple of 8");
|
||||
ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40;
|
||||
ape_pe_base = IMAGE_BASE_VIRTUAL;
|
||||
ape_idataz = LINK_WINDOWS ? RVA(ape_idata_iat) : 0;
|
||||
ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0;
|
||||
ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0;
|
||||
ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0;
|
||||
v_ntversion = LINK_WINDOWS ? 6 : 1;
|
||||
v_ntdllchar = LINK_WINDOWS ? 288 : 0;
|
||||
v_ntsubversion = LINK_WINDOWS ? 6 : 5;
|
||||
v_ntsubsystem = (LINK_WINDOWS
|
||||
? (DEFINED(GetMessage)
|
||||
? kNtImageSubsystemWindowsGui
|
||||
: kNtImageSubsystemWindowsCui)
|
||||
: kNtImageSubsystemEfiApplication);
|
||||
ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain;
|
||||
HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24));
|
||||
HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40);
|
||||
HIDDEN(ape_pe_base = IMAGE_BASE_VIRTUAL);
|
||||
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_iat) : 0);
|
||||
HIDDEN(ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0);
|
||||
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0);
|
||||
HIDDEN(ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0);
|
||||
HIDDEN(v_ntversion = LINK_WINDOWS ? 6 : 1);
|
||||
HIDDEN(v_ntdllchar = LINK_WINDOWS ? 288 : 0);
|
||||
HIDDEN(v_ntsubversion = LINK_WINDOWS ? 6 : 5);
|
||||
HIDDEN(v_ntsubsystem = (LINK_WINDOWS
|
||||
? (DEFINED(GetMessage)
|
||||
? kNtImageSubsystemWindowsGui
|
||||
: kNtImageSubsystemWindowsCui)
|
||||
: kNtImageSubsystemEfiApplication));
|
||||
HIDDEN(ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain);
|
||||
#endif
|
||||
|
||||
#if SupportsXnu()
|
||||
|
||||
+42
-126
@@ -19,89 +19,6 @@ APE_FILES := $(wildcard ape/*.*)
|
||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||
APE_INCS = $(filter %.inc,$(APE_FILES))
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
|
||||
APE = o/$(MODE)/ape/aarch64.lds
|
||||
|
||||
APELINK = \
|
||||
$(COMPILE) \
|
||||
-ALINK.ape \
|
||||
$(LINK) \
|
||||
$(LINKARGS) \
|
||||
$(OUTPUT_OPTION) && \
|
||||
$(COMPILE) \
|
||||
-AFIXUP.ape \
|
||||
-wT$@ \
|
||||
$(FIXUPOBJ) \
|
||||
$@
|
||||
|
||||
APE_SRCS = ape/ape.S ape/start.S ape/launch.S ape/systemcall.S
|
||||
APE_OBJS = o/$(MODE)/ape/ape.o
|
||||
APE_NO_MODIFY_SELF = $(APE)
|
||||
APE_COPY_SELF = $(APE)
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE)
|
||||
|
||||
o/$(MODE)/ape/aarch64.lds: \
|
||||
ape/aarch64.lds \
|
||||
libc/zip.internal.h \
|
||||
libc/intrin/bits.h \
|
||||
libc/thread/tls.h \
|
||||
libc/calls/struct/timespec.h \
|
||||
libc/macros.internal.h \
|
||||
libc/str/str.h
|
||||
|
||||
APE_LOADER_LDFLAGS = \
|
||||
-pie \
|
||||
-static \
|
||||
-nostdlib \
|
||||
--no-dynamic-linker \
|
||||
-z norelro \
|
||||
-z common-page-size=0x4000 \
|
||||
-z max-page-size=0x4000
|
||||
|
||||
APE_LOADER_FLAGS = \
|
||||
-DNDEBUG \
|
||||
-iquote. \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-fpie \
|
||||
-Os \
|
||||
-ffreestanding \
|
||||
-mgeneral-regs-only \
|
||||
-fno-asynchronous-unwind-tables \
|
||||
-fno-stack-protector \
|
||||
-fno-ident \
|
||||
-fno-gnu-unique \
|
||||
-c \
|
||||
$(OUTPUT_OPTION) \
|
||||
$<
|
||||
|
||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||
$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
|
||||
|
||||
o/$(MODE)/ape/ape.elf.dbg: \
|
||||
o/$(MODE)/ape/start.o \
|
||||
o/$(MODE)/ape/loader.o \
|
||||
o/$(MODE)/ape/launch.o \
|
||||
o/$(MODE)/ape/systemcall.o
|
||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/start.o: ape/start.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/ape/launch.o: ape/launch.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/ape/systemcall.o: ape/systemcall.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: o/$(MODE)/ape/ape.elf
|
||||
|
||||
else
|
||||
|
||||
APE = o/$(MODE)/ape/ape.o \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
|
||||
@@ -110,12 +27,19 @@ APELINK = \
|
||||
-ALINK.ape \
|
||||
$(LINK) \
|
||||
$(LINKARGS) \
|
||||
$(OUTPUT_OPTION) && \
|
||||
$(COMPILE) \
|
||||
-AFIXUP.ape \
|
||||
-wT$@ \
|
||||
$(FIXUPOBJ) \
|
||||
$@
|
||||
$(OUTPUT_OPTION)
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
|
||||
APE_SRCS = ape/ape.S
|
||||
APE_OBJS = o/$(MODE)/ape/ape.o
|
||||
APE_NO_MODIFY_SELF = $(APE)
|
||||
APE_COPY_SELF = $(APE)
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE)
|
||||
|
||||
else
|
||||
|
||||
APE_NO_MODIFY_SELF = \
|
||||
o/$(MODE)/ape/ape.lds \
|
||||
@@ -134,7 +58,7 @@ APE_LOADER_FLAGS = \
|
||||
-Os \
|
||||
-ffreestanding \
|
||||
-mgeneral-regs-only \
|
||||
-fno-stack-protector \
|
||||
-mno-red-zone \
|
||||
-fno-ident \
|
||||
-fno-gnu-unique \
|
||||
-c \
|
||||
@@ -147,7 +71,7 @@ APE_SRCS = $(APE_SRCS_C) $(APE_SRCS_S)
|
||||
APE_OBJS = $(APE_SRCS_S:%.S=o/$(MODE)/%.o)
|
||||
APE_CHECKS = $(APE_HDRS:%=o/%.ok)
|
||||
|
||||
o/$(MODE)/ape/public/ape.lds: CPPFLAGS += -UCOSMO
|
||||
o/$(MODE)/ape/public/ape.lds: OVERRIDE_CPPFLAGS += -UCOSMO
|
||||
o/$(MODE)/ape/public/ape.lds: \
|
||||
ape/public/ape.lds \
|
||||
ape/ape.lds \
|
||||
@@ -164,7 +88,7 @@ o/$(MODE)/ape/public/ape.lds: \
|
||||
libc/macros.internal.h \
|
||||
libc/nt/pedef.internal.h \
|
||||
libc/str/str.h \
|
||||
libc/zip.internal.h
|
||||
libc/zip.h
|
||||
|
||||
o/ape/idata.inc: \
|
||||
ape/idata.internal.h \
|
||||
@@ -178,7 +102,6 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
ape/ape.internal.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/thread/tls.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
@@ -189,9 +112,10 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
libc/runtime/e820.internal.h \
|
||||
libc/runtime/mman.internal.h \
|
||||
libc/runtime/pc.internal.h \
|
||||
libc/runtime/symbolic.h \
|
||||
libc/sysv/consts/prot.h \
|
||||
ape/blink-linux-aarch64.gz \
|
||||
ape/blink-xnu-aarch64.gz \
|
||||
ape/blink-aarch64.gz \
|
||||
ape/blink-darwin-arm64.gz \
|
||||
o/$(MODE)/ape/ape.elf
|
||||
@$(COMPILE) \
|
||||
-AOBJECTIFY.S \
|
||||
@@ -208,7 +132,6 @@ o/$(MODE)/ape/ape-copy-self.o: \
|
||||
ape/ape.internal.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/thread/tls.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
@@ -219,51 +142,44 @@ o/$(MODE)/ape/ape-copy-self.o: \
|
||||
libc/runtime/e820.internal.h \
|
||||
libc/runtime/mman.internal.h \
|
||||
libc/runtime/pc.internal.h \
|
||||
libc/runtime/symbolic.h \
|
||||
libc/sysv/consts/prot.h \
|
||||
ape/blink-linux-aarch64.gz \
|
||||
ape/blink-xnu-aarch64.gz
|
||||
ape/blink-aarch64.gz \
|
||||
ape/blink-darwin-arm64.gz
|
||||
@$(COMPILE) \
|
||||
-AOBJECTIFY.S \
|
||||
$(OBJECTIFY.S) \
|
||||
$(OUTPUT_OPTION) \
|
||||
-DAPE_NO_MODIFY_SELF $<
|
||||
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c ape/loader.h
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b01111001 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-gcc.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b01111001 -S -g0 $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-clang.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=0b01111001 -S -g0 $(APE_LOADER_FLAGS)
|
||||
|
||||
o/$(MODE)/ape/loader-xnu.o: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-xnu.o: ape/loader.c ape/loader.h
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b00001000 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-xnu-gcc.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b00001000 -S -g0 $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=0b00001000 -S -g0 $(APE_LOADER_FLAGS)
|
||||
|
||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy.com -f -o $@ $<
|
||||
|
||||
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.elf.dbg
|
||||
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy.com -fm -o $@ $<
|
||||
|
||||
APE_LOADER_LDFLAGS = \
|
||||
-static \
|
||||
-nostdlib \
|
||||
--no-dynamic-linker \
|
||||
-z separate-code \
|
||||
-z common-page-size=0x1000 \
|
||||
-z max-page-size=0x10000
|
||||
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.macho.dbg
|
||||
|
||||
o/$(MODE)/ape/ape.elf.dbg: \
|
||||
o/$(MODE)/ape/loader-macho.o \
|
||||
o/$(MODE)/ape/start.o \
|
||||
o/$(MODE)/ape/loader.o \
|
||||
o/$(MODE)/ape/launch.o \
|
||||
o/$(MODE)/ape/systemcall.o \
|
||||
o/$(MODE)/ape/loader-elf.o \
|
||||
ape/loader.lds
|
||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||
@$(ELFLINK) -z max-page-size=0x10
|
||||
|
||||
o/$(MODE)/ape/ape.macho.dbg: \
|
||||
o/$(MODE)/ape/loader-xnu.o \
|
||||
o/$(MODE)/ape/loader-macho.o \
|
||||
ape/loader-macho.lds
|
||||
@$(ELFLINK) -z max-page-size=0x10
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE_CHECKS) \
|
||||
@@ -282,8 +198,8 @@ o/$(MODE)/ape/ape.o: ape/ape.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
o/$(MODE)/ape/ape.o: \
|
||||
ape/blink-linux-aarch64.gz \
|
||||
ape/blink-xnu-aarch64.gz
|
||||
ape/blink-aarch64.gz \
|
||||
ape/blink-darwin-arm64.gz
|
||||
|
||||
o/$(MODE)/ape/ape.lds: \
|
||||
ape/ape.lds \
|
||||
@@ -300,4 +216,4 @@ o/$(MODE)/ape/ape.lds: \
|
||||
libc/macros.internal.h \
|
||||
libc/nt/pedef.internal.h \
|
||||
libc/str/str.h \
|
||||
libc/zip.internal.h
|
||||
libc/zip.h
|
||||
+7
-2
@@ -12,8 +12,13 @@ echo "Author: Justine Tunney <[email protected]>" >&2
|
||||
################################################################################
|
||||
# INSTALL APE LOADER SYSTEMWIDE
|
||||
|
||||
if [ -f o/depend ] && make -j8 o//ape; then
|
||||
echo "successfully recompiled ape loader" >&2
|
||||
if [ -f o/depend ]; then
|
||||
# mkdeps.com build was successfully run so assume we can build
|
||||
echo >&2
|
||||
echo "recompiling ape loader" >&2
|
||||
echo "running: make -j8 o//ape" >&2
|
||||
make -j8 o//ape || exit
|
||||
echo "done" >&2
|
||||
elif [ -d build/bootstrap ]; then
|
||||
# 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
|
||||
|
||||
+2
-24
@@ -11,7 +11,7 @@ fi
|
||||
echo "APE Uninstaller intends to run (in pseudo-shell)"
|
||||
echo
|
||||
echo " sudo echo -1 into /proc/sys/fs/binfmt_misc/APE*"
|
||||
echo " sudo rm -f /usr/bin/ape ~/.ape /tmp/.ape # etc."
|
||||
echo " sudo rm -f /usr/bin/ape ~/.ape o/tmp/.ape /tmp/.ape"
|
||||
echo
|
||||
echo "You may then use ape/apeinstall.sh to reinstall it"
|
||||
echo
|
||||
@@ -23,26 +23,4 @@ for f in /proc/sys/fs/binfmt_misc/APE*; do
|
||||
$SUDO sh -c "echo -1 >$f" || exit
|
||||
fi
|
||||
done
|
||||
|
||||
# system installation
|
||||
if [ -f /usr/bin/ape ]; then
|
||||
$SUDO rm -f /usr/bin/ape
|
||||
fi
|
||||
|
||||
# legacy installations
|
||||
rm -f o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape"
|
||||
|
||||
# ad-hoc installations
|
||||
for x in .ape \
|
||||
.ape-1.1 \
|
||||
.ape-1.3 \
|
||||
.ape-1.4 \
|
||||
.ape-1.5 \
|
||||
.ape-blink-0.9.2 \
|
||||
.ape-blink-1.0.0; do
|
||||
rm -f \
|
||||
~/$x \
|
||||
/tmp/$x \
|
||||
o/tmp/$x \
|
||||
"${TMPDIR:-/tmp}/$x"
|
||||
done
|
||||
$SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape o/tmp/ape /tmp/.ape /tmp/ape || exit
|
||||
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
#ifndef COSMOPOLITAN_APE_CONFIG_H_
|
||||
#define COSMOPOLITAN_APE_CONFIG_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define STATIC_SYMBOL(NAME, VALUE) \
|
||||
asm(".equ\t" NAME "," VALUE "\n\t" \
|
||||
".globl\t" NAME)
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_APE_CONFIG_H_ */
|
||||
@@ -0,0 +1,249 @@
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/macho.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// APE Loader Executable Structure
|
||||
// Linux, FreeBSD, NetBSD, OpenBSD
|
||||
|
||||
.balign 8
|
||||
ehdr: .ascii "\177ELF"
|
||||
.byte ELFCLASS64
|
||||
.byte ELFDATA2LSB
|
||||
.byte 1
|
||||
.byte ELFOSABI_FREEBSD
|
||||
.quad 0
|
||||
.word ET_EXEC # e_type
|
||||
.word EM_NEXGEN32E # e_machine
|
||||
.long 1 # e_version
|
||||
.quad _start # e_entry
|
||||
.quad phdrs - ehdr # e_phoff
|
||||
.quad 0 # e_shoff
|
||||
.long 0 # e_flags
|
||||
.word 64 # e_ehsize
|
||||
.word 56 # e_phentsize
|
||||
.word 4 # e_phnum
|
||||
.word 0 # e_shentsize
|
||||
.word 0 # e_shnum
|
||||
.word 0 # e_shstrndx
|
||||
.endobj ehdr,globl
|
||||
|
||||
.balign 8
|
||||
phdrs: .long PT_LOAD # p_type
|
||||
.long PF_R|PF_X # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad ehdr # p_vaddr
|
||||
.quad ehdr # p_paddr
|
||||
.quad filesz # p_filesz
|
||||
.quad filesz # p_memsz
|
||||
.quad PAGESIZE # p_align
|
||||
|
||||
.long PT_LOAD # p_type
|
||||
.long PF_R|PF_W # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad bss # p_vaddr
|
||||
.quad bss # p_paddr
|
||||
.quad 0 # p_filesz
|
||||
.quad bsssize # p_memsz
|
||||
.quad PAGESIZE # p_align
|
||||
|
||||
.long PT_GNU_STACK # p_type
|
||||
.long PF_R|PF_W # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad 0 # p_vaddr
|
||||
.quad 0 # p_paddr
|
||||
.quad 0 # p_filesz
|
||||
.quad 0 # p_memsz
|
||||
.quad 16 # p_align
|
||||
|
||||
.long PT_NOTE # p_type
|
||||
.long PF_R # p_flags
|
||||
.quad note - ehdr # p_offset
|
||||
.quad note # p_vaddr
|
||||
.quad note # p_paddr
|
||||
.quad notesize # p_filesz
|
||||
.quad notesize # p_memsz
|
||||
.quad 8 # p_align
|
||||
.endobj phdrs
|
||||
|
||||
note: .long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "OpenBSD"
|
||||
2: .balign 4
|
||||
3: .long 0
|
||||
4: .long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "NetBSD"
|
||||
2: .balign 4
|
||||
3: .long 901000000
|
||||
4: .endobj note
|
||||
notesize = . - note
|
||||
|
||||
.balign 64,0 # for ape.S dd
|
||||
.org 0x180 # for ape.S dd
|
||||
|
||||
// APE Loader XNU Header
|
||||
//
|
||||
// This header is dd'd backwards by the APE shell script when
|
||||
// running on Mac OS X.
|
||||
//
|
||||
// @see ape/ape.S
|
||||
macho: .long 0xFEEDFACE+1
|
||||
.long MAC_CPU_NEXGEN32E
|
||||
.long MAC_CPU_NEXGEN32E_ALL
|
||||
.long MAC_EXECUTE
|
||||
.long 5 # number of load commands
|
||||
.long 60f-10f # size of all load commands
|
||||
.long MAC_NOUNDEFS # flags
|
||||
.long 0 # reserved
|
||||
10: .long MAC_LC_SEGMENT_64
|
||||
.long 20f-10b # unmaps first page dir
|
||||
.ascin "__PAGEZERO",16 # consistent with linux
|
||||
.quad 0,0x200000,0,0 # which forbids mem <2m
|
||||
.long 0,0,0,0
|
||||
20: .long MAC_LC_SEGMENT_64
|
||||
.long 30f-20b
|
||||
.ascin "__TEXT",16
|
||||
.quad ehdr # vaddr
|
||||
.quad 4096 # memsz
|
||||
.quad 0 # file offset
|
||||
.quad filesz # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_EXEC|PROT_READ # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
210: .ascin "__text",16 # section name (.text)
|
||||
.ascin "__TEXT",16
|
||||
.quad _start # vaddr
|
||||
.quad textsz # memsz
|
||||
.long textoff # offset
|
||||
.long 6 # align 2**6 = 64
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ATTR_SOME_INSTRUCTIONS # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
30: .long MAC_LC_SEGMENT_64
|
||||
.long 40f-30b
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.quad 0 # offset
|
||||
.quad 0 # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_READ|PROT_WRITE # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
310: .ascin "__bss",16 # section name (.bss)
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.long 0 # offset
|
||||
.long 12 # align 2**12 = 4096
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ZEROFILL # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
40: .long MAC_LC_UUID
|
||||
.long 50f-40b
|
||||
.quad 0x3fb29ee4ac6c87aa # uuid1
|
||||
.quad 0xdd2c9bb866d9eef8 # uuid2
|
||||
50: .long MAC_LC_UNIXTHREAD
|
||||
.long 60f-50b # cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E # flavaflav
|
||||
.long (520f-510f)/4 # count
|
||||
510: .quad 0 # rax
|
||||
.quad 0 # rbx
|
||||
.quad 0 # rcx
|
||||
.quad _HOSTXNU # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
.quad 0 # rbp
|
||||
.quad 0 # rsp
|
||||
.quad 0 # r8
|
||||
.quad 0 # r9
|
||||
.quad 0 # r10
|
||||
.quad 0 # r11
|
||||
.quad 0 # r12
|
||||
.quad 0 # r13
|
||||
.quad 0 # r14
|
||||
.quad 0 # r15
|
||||
.quad _start # rip
|
||||
.quad 0 # rflags
|
||||
.quad 0 # cs
|
||||
.quad 0 # fs
|
||||
.quad 0 # gs
|
||||
520:
|
||||
60:
|
||||
.endobj macho
|
||||
|
||||
.balign 64,0 # for ape.S dd
|
||||
.org 0x400 # for ape.S dd
|
||||
|
||||
// Ape Loader Entrpoint
|
||||
//
|
||||
// This is normally called by the operating system. However it may
|
||||
// be called by the Actually Portable Executables themselves, when
|
||||
// re-executing a program. Just do this:
|
||||
//
|
||||
// memcpy(0x200000, loader)
|
||||
// lea handoff(%rip),%rcx
|
||||
// lea argblock(%rip),%rsp
|
||||
// jmp 0x200400
|
||||
//
|
||||
// @see APE_LOADER_ENTRY
|
||||
// @see ape/loader.h
|
||||
_start:
|
||||
|
||||
// Hack for detecting M1 Rosetta environment.
|
||||
// https://github.com/jart/cosmopolitan/issues/429#issuecomment-1166704377
|
||||
cmp $-1,%ebx
|
||||
jne 0f
|
||||
cmp $+1,%edx
|
||||
jne 0f
|
||||
mov $_HOSTXNU,%dl
|
||||
xor %ecx,%ecx
|
||||
|
||||
0: mov %rsp,%rsi
|
||||
jmp ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
// System Call Entrpoint
|
||||
//
|
||||
// This function is used by the APE loader to make system calls.
|
||||
// We also pass a reference to this function to the APE binary's
|
||||
// _start() function. It's needed because on OpenBSD, msyscall()
|
||||
// restricts which pages can issue system calls, and it can only
|
||||
// be called once. Therefore if we want to be load and re-load a
|
||||
// binary multiple times without calling the system execve(), we
|
||||
// need to be able to handover the SYSCALL function. We hardcode
|
||||
// this to a fixed address, but that shouldn't be used, since we
|
||||
// would ideally want to move it to a random page in the future.
|
||||
__syscall_loader:
|
||||
clc
|
||||
syscall
|
||||
jc 1f
|
||||
ret
|
||||
1: neg %rax
|
||||
ret
|
||||
.endfn __syscall_loader,globl
|
||||
+99
-56
@@ -21,75 +21,118 @@
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// Apple Mach-O Executable Headers
|
||||
// Fixups are applied by objbincopy.com
|
||||
// There must exist a MAC_LC_SEGMENT_64 for every PT_LOAD
|
||||
// APE Loader Executable Structure for XNU
|
||||
|
||||
.section .macho,"a",@progbits
|
||||
.balign 64
|
||||
.long 0xFEEDFACE+1
|
||||
.balign 4096
|
||||
macho: .long 0xFEEDFACE+1
|
||||
.long MAC_CPU_NEXGEN32E
|
||||
.long MAC_CPU_NEXGEN32E_ALL
|
||||
.long MAC_EXECUTE
|
||||
.long 5 // number of load commands
|
||||
.long 60f-10f // size of all load commands
|
||||
.long MAC_NOUNDEFS|MAC_SPLIT_SEGS // flags
|
||||
.long 0 // reserved
|
||||
.long 5 # number of load commands
|
||||
.long 60f-10f # size of all load commands
|
||||
.long MAC_NOUNDEFS # flags
|
||||
.long 0 # reserved
|
||||
10: .long MAC_LC_SEGMENT_64
|
||||
.long 20f-10b // unmaps first page dir
|
||||
.ascin "__PAGEZERO",16 // consistent with linux
|
||||
.quad 0,0x200000,0,0 // which forbids mem <2m
|
||||
.long 20f-10b # unmaps first page dir
|
||||
.ascin "__PAGEZERO",16 # consistent with linux
|
||||
.quad 0,0x200000,0,0 # which forbids mem <2m
|
||||
.long 0,0,0,0
|
||||
20: .long MAC_LC_SEGMENT_64
|
||||
.long 30f-20b
|
||||
.ascin "__TEXT",16
|
||||
.quad 0 // vaddr
|
||||
.quad 0 // memsz
|
||||
.quad 0 // file offset
|
||||
.quad 0 // file size
|
||||
.long 0 // maxprot
|
||||
.long 0 // initprot
|
||||
.long 0 // segment section count
|
||||
.long 0 // flags
|
||||
.quad macho # vaddr
|
||||
.quad 4096 # memsz
|
||||
.quad 0 # file offset
|
||||
.quad filesz # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_EXEC|PROT_READ # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
210: .ascin "__text",16 # section name (.text)
|
||||
.ascin "__TEXT",16
|
||||
.quad _start # vaddr
|
||||
.quad textsz # memsz
|
||||
.long textoff # offset
|
||||
.long 6 # align 2**3 = 64
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ATTR_SOME_INSTRUCTIONS # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
30: .long MAC_LC_SEGMENT_64
|
||||
.long 40f-30b
|
||||
.ascin "__RODATA",16
|
||||
.quad 0 // vaddr
|
||||
.quad 0 // memsz
|
||||
.quad 0 // file offset
|
||||
.quad 0 // file size
|
||||
.long 0 // maxprot
|
||||
.long 0 // initprot
|
||||
.long 0 // segment section count
|
||||
.long 0 // flags
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.quad 0 # offset
|
||||
.quad 0 # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_READ|PROT_WRITE # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
310: .ascin "__bss",16 # section name (.bss)
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.long 0 # offset
|
||||
.long 12 # align 2**12 = 4096
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ZEROFILL # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
40: .long MAC_LC_UUID
|
||||
.long 50f-40b
|
||||
.quad 0x4527148ba7a513ef // uuid1
|
||||
.quad 0x56fa865940665e8f // uuid2
|
||||
.quad 0x3fb29ee4ac6c87aa # uuid1
|
||||
.quad 0xdd2c9bb866d9eef8 # uuid2
|
||||
50: .long MAC_LC_UNIXTHREAD
|
||||
.long 60f-50b // cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E // flavaflav
|
||||
.long (520f-510f)/4 // count
|
||||
510: .quad 0 // rax
|
||||
.quad 0 // rbx
|
||||
.quad 0 // rcx
|
||||
.quad 0 // rdx
|
||||
.quad 0 // rdi
|
||||
.quad 0 // rsi
|
||||
.quad 0 // rbp
|
||||
.quad 0 // rsp
|
||||
.quad 0 // r8
|
||||
.quad 0 // r9
|
||||
.quad 0 // r10
|
||||
.quad 0 // r11
|
||||
.quad 0 // r12
|
||||
.quad 0 // r13
|
||||
.quad 0 // r14
|
||||
.quad 0 // r15
|
||||
.quad XnuEntrypoint // rip
|
||||
.quad 0 // rflags
|
||||
.quad 0 // cs
|
||||
.quad 0 // fs
|
||||
.quad 0 // gs
|
||||
.long 60f-50b # cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E # flavaflav
|
||||
.long (520f-510f)/4 # count
|
||||
510: .quad 0 # rax
|
||||
.quad 0 # rbx
|
||||
.quad 0 # rcx
|
||||
.quad _HOSTXNU # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
.quad 0 # rbp
|
||||
.quad 0 # rsp
|
||||
.quad 0 # r8
|
||||
.quad 0 # r9
|
||||
.quad 0 # r10
|
||||
.quad 0 # r11
|
||||
.quad 0 # r12
|
||||
.quad 0 # r13
|
||||
.quad 0 # r14
|
||||
.quad 0 # r15
|
||||
.quad _start # rip
|
||||
.quad 0 # rflags
|
||||
.quad 0 # cs
|
||||
.quad 0 # fs
|
||||
.quad 0 # gs
|
||||
520:
|
||||
60:
|
||||
.endobj macho,globl
|
||||
|
||||
.balign 64
|
||||
_start:
|
||||
|
||||
// Hack for detecting M1 Rosetta environment.
|
||||
// https://github.com/jart/cosmopolitan/issues/429#issuecomment-1166704377
|
||||
cmp $-1,%ebx
|
||||
jne 0f
|
||||
cmp $+1,%edx
|
||||
jne 0f
|
||||
mov $_HOSTXNU,%dl
|
||||
xor %ecx,%ecx
|
||||
|
||||
0: mov %rsp,%rsi
|
||||
jmp ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
__syscall_loader:
|
||||
clc
|
||||
syscall
|
||||
jc 1f
|
||||
ret
|
||||
1: neg %rax
|
||||
ret
|
||||
.endfn __syscall_loader,globl
|
||||
@@ -0,0 +1,42 @@
|
||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x200000;
|
||||
.text : {
|
||||
*(.text)
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
filesz = . - macho;
|
||||
textsz = . - _start;
|
||||
.bss ALIGN(4096) : {
|
||||
bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
memsz = . - macho;
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
bsssize = SIZEOF(.bss);
|
||||
textoff = _start - macho;
|
||||
+401
-666
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,20 @@
|
||||
#ifndef COSMOPOLITAN_APE_LOADER_H_
|
||||
#define COSMOPOLITAN_APE_LOADER_H_
|
||||
|
||||
#define APE_LOADER_BASE 0x200000
|
||||
#define APE_LOADER_SIZE 0x200000
|
||||
#define APE_LOADER_ENTRY 0x200400
|
||||
#define APE_LOADER_BSS (PAGESIZE * 2)
|
||||
#define APE_LOADER_STACK 0x7f0000000000
|
||||
#define APE_BLOCK_BASE 0x7e0000000000
|
||||
#define APE_BLOCK_SIZE 0x000200000000
|
||||
|
||||
struct ApeLoader {
|
||||
int fd;
|
||||
int os;
|
||||
char *prog;
|
||||
char *page;
|
||||
void *systemcall;
|
||||
};
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_LOADER_H_ */
|
||||
+18
-70
@@ -1,7 +1,7 @@
|
||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
@@ -16,80 +16,28 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
ENTRY(ElfEntrypoint)
|
||||
|
||||
PHDRS {
|
||||
text PT_LOAD FLAGS(1) FILEHDR PHDRS; /* PF_X */
|
||||
rodata PT_LOAD FLAGS(4); /* PF_R */
|
||||
stack PT_GNU_STACK FLAGS(6); /* PF_W|PF_R */
|
||||
note PT_NOTE FLAGS(4); /* PF_R */
|
||||
}
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
|
||||
. = SEGMENT_START("text-segment", 0x7f000000);
|
||||
__executable_start = .;
|
||||
. += SIZEOF_HEADERS;
|
||||
|
||||
.macho : {
|
||||
KEEP(*(.macho))
|
||||
} :text
|
||||
|
||||
.note : {
|
||||
KEEP(*(.note))
|
||||
} :text :note
|
||||
|
||||
. = 0x200000;
|
||||
.text : {
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
} :text
|
||||
|
||||
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
} :rodata
|
||||
|
||||
.stack : {
|
||||
*(.stack)
|
||||
} :stack
|
||||
|
||||
*(.text)
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(64);
|
||||
}
|
||||
filesz = . - ehdr;
|
||||
textsz = . - _start;
|
||||
.bss ALIGN(4096) : {
|
||||
bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
_end = .;
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.debug_loclists 0 : { *(.debug_loclists) }
|
||||
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||
.debug_line_str 0 : { *(.debug_line_str) }
|
||||
.debug_extra 0 : { *(.debug_line_str) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
|
||||
memsz = _end - ehdr;
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
bsssize = SIZEOF(.bss);
|
||||
textoff = _start - ehdr;
|
||||
+25
-20
@@ -3,26 +3,31 @@
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const char __comment_start[] __attribute__((__weak__));
|
||||
extern unsigned char __executable_start[] __attribute__((__weak__));
|
||||
extern unsigned char __privileged_start[] __attribute__((__weak__));
|
||||
extern unsigned char _ehead[] __attribute__((__weak__));
|
||||
extern unsigned char _etext[] __attribute__((__weak__));
|
||||
extern unsigned char _edata[] __attribute__((__weak__));
|
||||
extern unsigned char _ezip[] __attribute__((__weak__));
|
||||
extern unsigned char _end[] __attribute__((__weak__));
|
||||
extern unsigned char _ereal[] __attribute__((__weak__));
|
||||
extern unsigned char _tdata_start[] __attribute__((__weak__));
|
||||
extern unsigned char _tdata_end[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_start[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_end[] __attribute__((__weak__));
|
||||
extern unsigned char _tls_align[] __attribute__((__weak__));
|
||||
extern unsigned char __test_start[] __attribute__((__weak__));
|
||||
extern unsigned char __ro[] __attribute__((__weak__));
|
||||
extern uint8_t __data_start[] __attribute__((__weak__));
|
||||
extern uint8_t __data_end[] __attribute__((__weak__));
|
||||
extern uint8_t __bss_start[] __attribute__((__weak__));
|
||||
extern uint8_t __bss_end[] __attribute__((__weak__));
|
||||
extern unsigned char _base[];
|
||||
extern unsigned char _ehead[];
|
||||
extern unsigned char _etext[];
|
||||
extern unsigned char _edata[];
|
||||
extern unsigned char _ezip[];
|
||||
extern unsigned char _end[];
|
||||
extern unsigned char _ereal[];
|
||||
extern unsigned char _tdata_start[];
|
||||
extern unsigned char _tdata_end[];
|
||||
extern unsigned char _tbss_start[];
|
||||
extern unsigned char _tbss_end[];
|
||||
extern unsigned char __privileged_start[];
|
||||
extern unsigned char __privileged_addr[];
|
||||
extern unsigned char __privileged_size[];
|
||||
extern unsigned char __privileged_end[];
|
||||
extern unsigned char __test_start[];
|
||||
extern unsigned char __ro[];
|
||||
extern unsigned char *__relo_start[];
|
||||
extern unsigned char *__relo_end[];
|
||||
extern uint8_t __zip_start[];
|
||||
extern uint8_t __zip_end[];
|
||||
extern uint8_t __data_start[];
|
||||
extern uint8_t __data_end[];
|
||||
extern uint8_t __bss_start[];
|
||||
extern uint8_t __bss_end[];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
||||
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.
+73
-145
@@ -6,41 +6,19 @@
|
||||
# - `make`
|
||||
# - Optimized
|
||||
# - Backtraces
|
||||
# - Debuggable
|
||||
# - Syscall tracing
|
||||
# - Function tracing
|
||||
# - Reasonably small
|
||||
#
|
||||
ifeq ($(MODE),)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
ifeq ($(MODE), aarch64)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
|
||||
# Zero Optimization Mode
|
||||
#
|
||||
# - Goes 2x slower
|
||||
# - Supports --strace
|
||||
# - Unsupports --ftrace
|
||||
# - Better GDB debugging
|
||||
#
|
||||
ifeq ($(MODE), zero)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
OVERRIDE_CFLAGS += -O0
|
||||
OVERRIDE_CXXFLAGS += -O0
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
ifeq ($(MODE), aarch64-zero)
|
||||
CONFIG_OFLAGS ?= -g
|
||||
OVERRIDE_CFLAGS += -O0
|
||||
OVERRIDE_CXXFLAGS += -O0
|
||||
ifeq ($(MODE), aarch64)
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES) #$(FTRACE)
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
|
||||
@@ -52,11 +30,12 @@ endif
|
||||
# - Function tracing
|
||||
# - Some optimizations
|
||||
# - Limited Backtraces
|
||||
# - Compiles 28% faster
|
||||
#
|
||||
ifeq ($(MODE), fastbuild)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DDWARFLESS
|
||||
CONFIG_OFLAGS += -g0
|
||||
CONFIG_LDFLAGS += -S
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
@@ -74,15 +53,12 @@ endif
|
||||
# - GCC 8+ hoists check fails into .text.cold, thus minimizing impact
|
||||
#
|
||||
ifeq ($(MODE), opt)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O3 -fmerge-all-constants
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -msse2avx -Wa,-msse2avx
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O3 -fmerge-all-constants
|
||||
TARGET_ARCH ?= -march=native
|
||||
endif
|
||||
|
||||
# Optimized Linux Mode
|
||||
# The Fastest Mode of All
|
||||
#
|
||||
# - `make MODE=optlinux`
|
||||
# - Turns on red zone
|
||||
@@ -92,10 +68,9 @@ endif
|
||||
# - Turns off support for other operating systems
|
||||
#
|
||||
ifeq ($(MODE), optlinux)
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -msse2avx -Wa,-msse2avx -DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
|
||||
CONFIG_COPTS += -mred-zone
|
||||
DEFAULT_COPTS += -mred-zone
|
||||
TARGET_ARCH ?= -march=native
|
||||
endif
|
||||
|
||||
@@ -107,7 +82,6 @@ endif
|
||||
# - More optimized
|
||||
# - Reasonably small
|
||||
# - Numeric backtraces
|
||||
# - No DWARF data bloat
|
||||
# - Toilsome debuggability
|
||||
# - assert() statements removed
|
||||
# - DCHECK_xx() statements removed
|
||||
@@ -115,7 +89,7 @@ endif
|
||||
# - CHECK_xx() won't leak strings into binary
|
||||
#
|
||||
ifeq ($(MODE), rel)
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DDWARFLESS
|
||||
CONFIG_CPPFLAGS += -DNDEBUG
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||
TARGET_ARCH ?= -msse3
|
||||
PYFLAGS += -O1
|
||||
@@ -133,13 +107,9 @@ endif
|
||||
# - Larger binaries
|
||||
#
|
||||
ifeq ($(MODE), asan)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_CPPFLAGS += -D__SANITIZE_ADDRESS__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
|
||||
CONFIG_COPTS += -fsanitize=address
|
||||
TARGET_ARCH ?= -msse3
|
||||
QUOTA ?= -C64 -L300
|
||||
endif
|
||||
|
||||
# Debug Mode
|
||||
@@ -147,28 +117,17 @@ endif
|
||||
# - `make MODE=dbg`
|
||||
# - Backtraces
|
||||
# - Enables asan
|
||||
# - Enables ubsan
|
||||
# - Enables ubsan (TODO)
|
||||
# - Stack canaries
|
||||
# - No optimization
|
||||
# - No optimization (TODO)
|
||||
# - Enormous binaries
|
||||
#
|
||||
ifeq ($(MODE), dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ -D__SANITIZE_UNDEFINED__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O -fno-inline
|
||||
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
|
||||
TARGET_ARCH ?= -msse3
|
||||
OVERRIDE_CCFLAGS += -fno-pie
|
||||
QUOTA ?= -C64 -L300
|
||||
endif
|
||||
ifeq ($(MODE), aarch64-dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
|
||||
CONFIG_COPTS += -fsanitize=undefined
|
||||
QUOTA ?= -C64 -L300
|
||||
endif
|
||||
|
||||
# System Five Mode
|
||||
@@ -182,9 +141,7 @@ endif
|
||||
# - No Windows bloat!
|
||||
#
|
||||
ifeq ($(MODE), sysv)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
@@ -213,17 +170,22 @@ CONFIG_CCFLAGS += \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops \
|
||||
-fschedule-insns2 \
|
||||
-fomit-frame-pointer \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls \
|
||||
-DDWARFLESS
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
PYFLAGS += \
|
||||
-O2 \
|
||||
-B
|
||||
endif
|
||||
|
||||
ifeq ($(MODE), aarch64-tiny)
|
||||
# TODO(jart): -mcmodel=tiny
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
@@ -235,9 +197,14 @@ CONFIG_CCFLAGS += \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops \
|
||||
-fschedule-insns2 \
|
||||
-fomit-frame-pointer \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls \
|
||||
-DDWARFLESS
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
PYFLAGS += \
|
||||
-O2 \
|
||||
-B
|
||||
@@ -263,6 +230,12 @@ CONFIG_CPPFLAGS += \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=1 \
|
||||
-DDWARFLESS
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
@@ -294,6 +267,12 @@ CONFIG_CPPFLAGS += \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=113 \
|
||||
-DDWARFLESS
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
@@ -324,12 +303,18 @@ CONFIG_CPPFLAGS += \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=121 \
|
||||
-DDWARFLESS
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
@@ -360,44 +345,40 @@ CONFIG_CCFLAGS += \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
# no x87 instructions mode
|
||||
#
|
||||
# export MODE=nox87
|
||||
# make -j8 toolchain
|
||||
# cosmocc -o /tmp/hello.com hello.c
|
||||
#
|
||||
# lets you shave ~23kb off blink
|
||||
#
|
||||
# git clone https://github.com/jart/blink
|
||||
# cd blink
|
||||
# ./configure --disable-x87
|
||||
# make -j8
|
||||
# o//blink/blink /tmp/hello.com
|
||||
#
|
||||
ifeq ($(MODE), nox87)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_COPTS += -mlong-double-64
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DNOX87
|
||||
# GCC11 Mode
|
||||
# https://justine.lol/compilers/x86_64-linux-musl__x86_64-linux-musl__g++-11.2.0.tar.xz
|
||||
ifeq ($(MODE), gcc11)
|
||||
.UNVEIL += rx:/opt/gcc11
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O2
|
||||
AS = /opt/gcc11/bin/x86_64-linux-musl-as
|
||||
CC = /opt/gcc11/bin/x86_64-linux-musl-gcc
|
||||
CXX = /opt/gcc11/bin/x86_64-linux-musl-g++
|
||||
CXXFILT = /opt/gcc11/bin/x86_64-linux-musl-c++filt
|
||||
LD = /opt/gcc11/bin/x86_64-linux-musl-ld.bfd
|
||||
NM = /opt/gcc11/bin/x86_64-linux-musl-nm
|
||||
GCC = /opt/gcc11/bin/x86_64-linux-musl-gcc
|
||||
STRIP = /opt/gcc11/bin/x86_64-linux-musl-strip
|
||||
OBJCOPY = /opt/gcc11/bin/x86_64-linux-musl-objcopy
|
||||
OBJDUMP = /opt/gcc11/bin/x86_64-linux-musl-objdump
|
||||
ADDR2LINE = /opt/gcc11/bin/x86_64-linux-musl-addr2line
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2 -Wno-stringop-overread
|
||||
CONFIG_CFLAGS += -Wno-old-style-definition
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
|
||||
# LLVM Mode
|
||||
#
|
||||
# We aim to support:
|
||||
#
|
||||
# make -j8 m=llvm o/llvm/libc
|
||||
#
|
||||
# The rest of the monorepo may not work with llvm.
|
||||
#
|
||||
ifeq ($(MODE), llvm)
|
||||
.STRICT = 0
|
||||
TARGET_ARCH ?= -msse3
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O2
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O2
|
||||
AS = clang
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
@@ -435,65 +416,12 @@ endif
|
||||
# such as MSVC or XCode. You can run your binary objects through a tool
|
||||
# like objconv to convert them to COFF or MachO. Then use ANSI mode to
|
||||
# rollup one header file that'll enable linkage with minimal issues.
|
||||
|
||||
ifeq ($(MODE), ansi)
|
||||
|
||||
CONFIG_CFLAGS += -std=c11
|
||||
#CONFIG_CPPFLAGS += -ansi
|
||||
CONFIG_CXXFLAGS += -std=c++11
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
|
||||
ifneq ($(ENABLE_FTRACE),)
|
||||
CONFIG_CPPFLAGS += -DFTRACE
|
||||
FTRACE_CCFLAGS = -fno-inline-functions-called-once
|
||||
OVERRIDE_CFLAGS += $(FTRACE_CCFLAGS)
|
||||
OVERRIDE_CXXFLAGS += $(FTRACE_CCFLAGS)
|
||||
# function prologue nops for --ftrace
|
||||
ifeq ($(ARCH), x86_64)
|
||||
# this flag causes gcc to generate functions like this
|
||||
#
|
||||
# nop nop nop nop nop nop nop nop nop
|
||||
# func:
|
||||
# nop nop
|
||||
# ...
|
||||
#
|
||||
# which tool/build/fixupobj.c improves at build time like this
|
||||
#
|
||||
# nop nop nop nop nop nop nop nop nop
|
||||
# func:
|
||||
# xchg %ax,%ax
|
||||
# ...
|
||||
#
|
||||
# which --ftrace morphs at runtime like this
|
||||
#
|
||||
# ud2 # 2 bytes
|
||||
# call ftrace_hook # 5 bytes
|
||||
# jmp +2 # 2 bytes
|
||||
# func:
|
||||
# jmp -7 # 2 bytes
|
||||
# ...
|
||||
#
|
||||
CONFIG_CCFLAGS += -fpatchable-function-entry=18,16
|
||||
endif
|
||||
ifeq ($(ARCH), aarch64)
|
||||
# this flag causes gcc to generate functions like this
|
||||
#
|
||||
# nop nop nop nop nop nop
|
||||
# func:
|
||||
# nop
|
||||
# ...
|
||||
#
|
||||
# which --ftrace morphs at runtime like this
|
||||
#
|
||||
# brk #31337
|
||||
# stp x29,x30,[sp,#-16]!
|
||||
# mov x29,sp
|
||||
# bl ftrace_hook
|
||||
# ldp x29,x30,[sp],#16
|
||||
# b +1
|
||||
# func:
|
||||
# b -5
|
||||
# ...
|
||||
#
|
||||
CONFIG_CCFLAGS += -fpatchable-function-entry=7,6
|
||||
endif
|
||||
endif
|
||||
+47
-80
@@ -33,25 +33,14 @@
|
||||
#
|
||||
# VARIABLES
|
||||
#
|
||||
# Our configuration variables, ordered by increasing preference:
|
||||
#
|
||||
# CCFLAGS frontend flags (.i, .c, .cc, .f, .S, .lds, etc.)
|
||||
# OFLAGS objectify flags (precludes -S and -E)
|
||||
# CCFLAGS gcc frontend flags (.i, .c, .cc, .f, .S, .lds, etc.)
|
||||
# CPPFLAGS preprocessor flags (.h, .c, .cc, .S, .inc, .lds, etc.)
|
||||
# TARGET_ARCH microarchitecture flags (e.g. -march=native)
|
||||
# COPTS c/c++ flags (.c, .cc)
|
||||
# CFLAGS c flags (.c only)
|
||||
# CXXFLAGS c++ flags (.cc only)
|
||||
# COPTS c/c++ flags (.c, .cc)
|
||||
# LDFLAGS linker flags (don't use -Wl, frontend prefix)
|
||||
# ASFLAGS assembler flags (don't use -Wa, frontend prefix)
|
||||
#
|
||||
# For each FOO above, there exists (by increasing preference)
|
||||
#
|
||||
# DEFAULT_FOO see build/definitions.mk
|
||||
# CONFIG_FOO see build/config.mk
|
||||
# FOO set ~/.cosmo.mk and target-specific
|
||||
# OVERRIDE_FOO set ~/.cosmo.mk and target-specific (use rarely)
|
||||
#
|
||||
# TARGET_ARCH microarchitecture flags (e.g. -march=native)
|
||||
|
||||
LC_ALL = C
|
||||
SOURCE_DATE_EPOCH = 0
|
||||
@@ -69,33 +58,28 @@ 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
|
||||
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)
|
||||
IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
|
||||
IGNORE := $(shell $(ECHO) -2 ♥cosmo)
|
||||
IGNORE := $(shell $(MKDIR) $(TMPDIR))
|
||||
IGNORE := $(shell $(MKDIR) o/tmp)
|
||||
|
||||
ifneq ($(findstring aarch64,$(MODE)),)
|
||||
ARCH = aarch64
|
||||
VM = o/third_party/qemu/qemu-aarch64
|
||||
HOSTS ?= pi silicon
|
||||
else
|
||||
ARCH = x86_64
|
||||
HOSTS ?= freebsd openbsd openbsd73 netbsd rhel7 rhel5 xnu win10
|
||||
endif
|
||||
|
||||
ifeq ($(PREFIX),)
|
||||
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
|
||||
ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-*)","")
|
||||
PREFIX = o/third_party/gcc/bin/x86_64-pc-linux-gnu-
|
||||
else
|
||||
@@ -105,8 +89,6 @@ endif
|
||||
ifeq ($(ARCH), aarch64)
|
||||
PREFIX = o/third_party/gcc/bin/aarch64-linux-musl-
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
AS = $(PREFIX)as
|
||||
CC = $(PREFIX)gcc
|
||||
@@ -118,11 +100,7 @@ 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
|
||||
@@ -132,18 +110,20 @@ export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
|
||||
ifeq ($(LANDLOCKMAKE_VERSION),)
|
||||
TMPSAFE = $(join $(TMPDIR),$(subst /,_,$@)).tmp
|
||||
TMPSAFE = $(TMPDIR)/$(subst /,_,$@).tmp
|
||||
else
|
||||
TMPSAFE = $(TMPDIR)/
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
IMAGE_BASE_VIRTUAL ?= 0x010000000000
|
||||
else
|
||||
IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
ifneq ($(ARCH), aarch64)
|
||||
MNO_FENTRY = -mno-fentry
|
||||
endif
|
||||
|
||||
FTRACE = \
|
||||
-pg
|
||||
|
||||
BACKTRACES = \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
@@ -155,6 +135,7 @@ SANITIZER = \
|
||||
-fsanitize=address
|
||||
|
||||
NO_MAGIC = \
|
||||
$(MNO_FENTRY) \
|
||||
-fno-stack-protector \
|
||||
-fwrapv \
|
||||
-fno-sanitize=all
|
||||
@@ -168,49 +149,38 @@ TRADITIONAL = \
|
||||
-Wno-return-type \
|
||||
-Wno-pointer-sign
|
||||
|
||||
DEFAULT_CCFLAGS += \
|
||||
DEFAULT_CCFLAGS = \
|
||||
-Wall \
|
||||
-Werror \
|
||||
-fno-omit-frame-pointer \
|
||||
-fdebug-prefix-map='$(PWD)'= \
|
||||
-frecord-gcc-switches
|
||||
|
||||
DEFAULT_COPTS ?= \
|
||||
DEFAULT_OFLAGS = \
|
||||
-g \
|
||||
-gdwarf-4 \
|
||||
-gdescribe-dies
|
||||
|
||||
DEFAULT_COPTS = \
|
||||
-fno-math-errno \
|
||||
-fno-fp-int-builtin-inexact \
|
||||
-fno-ident \
|
||||
-fno-common \
|
||||
-fno-gnu-unique \
|
||||
-fstrict-aliasing \
|
||||
-fstrict-overflow \
|
||||
-fno-semantic-interposition \
|
||||
-fno-dwarf2-cfi-asm \
|
||||
-fno-unwind-tables \
|
||||
-fno-asynchronous-unwind-tables
|
||||
-fno-semantic-interposition
|
||||
|
||||
ifeq ($(ARCH), x86_64)
|
||||
ifneq ($(ARCH), aarch64)
|
||||
DEFAULT_COPTS += \
|
||||
-mno-red-zone \
|
||||
-mno-tls-direct-seg-refs
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
#
|
||||
# - Apple says in "Writing ARM64 code for Apple platforms" that we're
|
||||
# not allowed to use the x18 register.
|
||||
#
|
||||
# - Cosmopolitan Libc uses x28 for thread-local storage because Apple
|
||||
# forbids us from using tpidr_el0 too.
|
||||
#
|
||||
DEFAULT_COPTS += \
|
||||
-ffixed-x18 \
|
||||
-ffixed-x28 \
|
||||
-mno-outline-atomics
|
||||
endif
|
||||
|
||||
MATHEMATICAL = \
|
||||
-O3 \
|
||||
-fwrapv
|
||||
|
||||
DEFAULT_CPPFLAGS += \
|
||||
DEFAULT_CPPFLAGS = \
|
||||
-DCOSMO \
|
||||
-DMODE='"$(MODE)"' \
|
||||
-DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \
|
||||
@@ -232,33 +202,27 @@ DEFAULT_CXXFLAGS = \
|
||||
DEFAULT_ASFLAGS = \
|
||||
-W \
|
||||
-I. \
|
||||
--noexecstack
|
||||
--noexecstack \
|
||||
--nocompress-debug-sections
|
||||
|
||||
DEFAULT_LDFLAGS = \
|
||||
-static \
|
||||
-nostdlib \
|
||||
-znorelro \
|
||||
--gc-sections \
|
||||
--build-id=none \
|
||||
--no-dynamic-linker
|
||||
--no-dynamic-linker \
|
||||
-zmax-page-size=0x1000 #--cref [email protected]
|
||||
|
||||
# # generate linker report files
|
||||
# DEFAULT_LDFLAGS += --cref [email protected]
|
||||
ZIPOBJ_FLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
DEFAULT_LDFLAGS += \
|
||||
-zmax-page-size=0x4000 \
|
||||
-zcommon-page-size=0x4000 \
|
||||
-znorelro
|
||||
else
|
||||
DEFAULT_LDFLAGS += \
|
||||
-zmax-page-size=0x10000 \
|
||||
-zcommon-page-size=0x1000
|
||||
endif
|
||||
PYFLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
ASONLYFLAGS = \
|
||||
-c \
|
||||
-g
|
||||
-g \
|
||||
--debug-prefix-map='$(PWD)'=
|
||||
|
||||
DEFAULT_LDLIBS =
|
||||
|
||||
@@ -332,19 +296,19 @@ LD.libs = \
|
||||
$(CONFIG_LIBS) \
|
||||
$(LIBS)
|
||||
|
||||
COMPILE.c.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(c.flags)
|
||||
COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(cxx.flags)
|
||||
COMPILE.c.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(c.flags)
|
||||
COMPILE.cxx.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(cxx.flags)
|
||||
COMPILE.f.flags = $(cc.flags) $(copt.flags) $(f.flags)
|
||||
COMPILE.F.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(f.flags)
|
||||
COMPILE.F.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(f.flags)
|
||||
COMPILE.i.flags = $(cc.flags) $(copt.flags) $(c.flags)
|
||||
COMPILE.ii.flags = $(cc.flags) $(copt.flags) $(cxx.flags)
|
||||
LINK.flags = $(DEFAULT_LDFLAGS) $(CONFIG_LDFLAGS) $(LDFLAGS)
|
||||
OBJECTIFY.c.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(c.flags)
|
||||
OBJECTIFY.cxx.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(cxx.flags)
|
||||
OBJECTIFY.c.flags = $(OBJECTIFY.S.flags) $(copt.flags) $(c.flags)
|
||||
OBJECTIFY.cxx.flags = $(OBJECTIFY.S.flags) $(copt.flags) $(cxx.flags)
|
||||
OBJECTIFY.s.flags = $(ASONLYFLAGS) $(s.flags)
|
||||
OBJECTIFY.S.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags)
|
||||
OBJECTIFY.f.flags = $(cc.flags) $(o.flags) $(S.flags) $(f.flags)
|
||||
OBJECTIFY.F.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(f.flags)
|
||||
OBJECTIFY.S.flags = $(copt.flags) $(cc.flags) $(o.flags) $(cpp.flags) $(S.flags)
|
||||
OBJECTIFY.f.flags = $(copt.flags) $(cc.flags) $(o.flags) $(copt.flags) $(S.flags) $(f.flags)
|
||||
OBJECTIFY.F.flags = $(OBJECTIFY.f.flags) $(cpp.flags)
|
||||
PREPROCESS.flags = -E $(copt.flags) $(cc.flags) $(cpp.flags)
|
||||
PREPROCESS.lds.flags = -D__LINKER__ $(filter-out -g%,$(PREPROCESS.flags)) -P -xc
|
||||
|
||||
@@ -363,7 +327,7 @@ PREPROCESS = $(CC) $(PREPROCESS.flags)
|
||||
PREPROCESS.lds = $(CC) $(PREPROCESS.lds.flags)
|
||||
LINK = $(LD) $(LINK.flags)
|
||||
ELF = o/libc/elf/elf.lds
|
||||
ELFLINK = $(COMPILE) -ALINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION) && $(COMPILE) -AFIXUP.ape -T$@ $(FIXUPOBJ) $@
|
||||
ELFLINK = $(COMPILE) -ALINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION)
|
||||
LINKARGS = $(patsubst %.lds,-T %.lds,$(call uniqr,$(LD.libs) $(filter-out %.pkg,$^)))
|
||||
LOLSAN = build/lolsan -b $(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
@@ -380,6 +344,7 @@ OBJECTIFY.greg.c = \
|
||||
-fno-optimize-sibling-calls \
|
||||
-fno-sanitize=all \
|
||||
-ffreestanding \
|
||||
$(MNO_FENTRY) \
|
||||
-fwrapv \
|
||||
-c
|
||||
|
||||
@@ -419,6 +384,7 @@ OBJECTIFY.ncabi.c = \
|
||||
$(OBJECTIFY.c.flags) \
|
||||
-mno-sse \
|
||||
-mfpmath=387 \
|
||||
$(MNO_FENTRY) \
|
||||
-fno-stack-protector \
|
||||
-fno-instrument-functions \
|
||||
-fno-optimize-sibling-calls \
|
||||
@@ -437,6 +403,7 @@ OBJECTIFY.ncabi.c = \
|
||||
OBJECTIFY.initabi.c = \
|
||||
$(GCC) \
|
||||
$(OBJECTIFY.c.flags) \
|
||||
$(MNO_FENTRY) \
|
||||
-fno-stack-protector \
|
||||
-fno-instrument-functions \
|
||||
-fno-optimize-sibling-calls \
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
#!/bin/sh
|
||||
if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then
|
||||
for last; do true; done
|
||||
if printf '%s\n' "$last" | grep aarch64 >/dev/null 2>&1; then
|
||||
exec o/third_party/gcc/bin/aarch64-linux-musl-objdump "$@"
|
||||
else
|
||||
exec o/third_party/gcc/bin/x86_64-linux-musl-objdump "$@"
|
||||
|
||||
+3
-3
@@ -23,9 +23,9 @@
|
||||
# - tool/build/runitd.c
|
||||
|
||||
.PRECIOUS: o/$(MODE)/%.com.ok
|
||||
o/$(MODE)/%.com.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet
|
||||
o/$(MODE)/%.com.ok: .PLEDGE = stdio rpath wpath cpath proc fattr inet
|
||||
o/$(MODE)/%.com.ok: \
|
||||
o//tool/build/runit.com \
|
||||
o//tool/build/runitd.com \
|
||||
o/$(MODE)/tool/build/runit.com \
|
||||
o/$(MODE)/tool/build/runitd.com \
|
||||
o/$(MODE)/%.com
|
||||
@$(COMPILE) -wATEST -tT$@ $^ $(HOSTS)
|
||||
+20
-35
@@ -16,22 +16,18 @@
|
||||
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
MAKE_ZIPCOPY = $(COMPILE) -AZIPCOPY -wT$@ $(ZIPCOPY) $< $@
|
||||
ifneq ($(ARCH), aarch64)
|
||||
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@ && $(MAKE_ZIPCOPY)
|
||||
else
|
||||
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S $< $@ && $(MAKE_ZIPCOPY)
|
||||
endif
|
||||
|
||||
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
|
||||
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(MAKE_OBJCOPY)
|
||||
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
|
||||
o/$(MODE)/%.o: %.f ; @$(COMPILE) -AOBJECTIFY.f $(OBJECTIFY.f) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.F ; @$(COMPILE) -AOBJECTIFY.F $(OBJECTIFY.F) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.h: %.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
o/$(MODE)/%.h: o/$(MODE)/%.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
o/$(MODE)/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.initabi.o: %.initabi.c ; @$(COMPILE) -AOBJECTIFY.init $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $<
|
||||
@@ -80,18 +76,6 @@ o/$(MODE)/%.o: o/$(MODE)/%.cc
|
||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/%.greg.o: %.greg.c
|
||||
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.o: %.greg.c
|
||||
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.greg.o: %.greg.c
|
||||
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/%.a:
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),$^)
|
||||
@$(COMPILE) -AARCHIVE -wT$@ $(AR) $(ARFLAGS) $@ @$(TMPDIR)/$(subst /,_,$@)
|
||||
@@ -104,21 +88,21 @@ o/$(MODE)/%.pkg:
|
||||
$(file >$(TMPSAFE).args,$(filter %.o,$^))
|
||||
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
|
||||
|
||||
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com $(VM)
|
||||
@$(COMPILE) -wAPYOBJ $(VM) o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
|
||||
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com
|
||||
@$(COMPILE) -wAPYOBJ o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
|
||||
|
||||
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com $(VM)
|
||||
@$(COMPILE) -wAPYCOMP $(VM) o/$(MODE)/third_party/python/pycomp.com $(PYCFLAGS) -o $@ $<
|
||||
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com
|
||||
@$(COMPILE) -wAPYCOMP o/$(MODE)/third_party/python/pycomp.com $(PYCFLAGS) -o $@ $<
|
||||
|
||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com $(VM)
|
||||
@$(COMPILE) -wALUAC $(VM) o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
|
||||
@$(COMPILE) -wALUAC o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
|
||||
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean.com $(VM)
|
||||
@$(COMPILE) -wALUA -tT$@ $(VM) o/$(MODE)/tool/net/redbean.com $(LUAFLAGS) -i $<
|
||||
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean.com
|
||||
@$(COMPILE) -wALUA -tT$@ o/$(MODE)/tool/net/redbean.com $(LUAFLAGS) -i $<
|
||||
|
||||
o/$(MODE)/%: o/$(MODE)/%.com o/$(MODE)/tool/build/cp.com o/$(MODE)/tool/build/assimilate.com $(VM)
|
||||
@$(COMPILE) -wACP -T$@ $(VM) o/$(MODE)/tool/build/cp.com $< $@
|
||||
@$(COMPILE) -wAASSIMILATE -T$@ $(VM) o/$(MODE)/tool/build/assimilate.com $@
|
||||
o/$(MODE)/%: o/$(MODE)/%.com o/$(MODE)/tool/build/cp.com o/$(MODE)/tool/build/assimilate.com
|
||||
@$(COMPILE) -wACP -T$@ o/$(MODE)/tool/build/cp.com $< $@
|
||||
@$(COMPILE) -wAASSIMILATE -T$@ o/$(MODE)/tool/build/assimilate.com $@
|
||||
|
||||
################################################################################
|
||||
# LOCAL UNIT TESTS
|
||||
@@ -215,16 +199,18 @@ o/$(MODE)/%.okk: %
|
||||
################################################################################
|
||||
# EXECUTABLE HELPERS
|
||||
|
||||
MAKE_OBJCOPY = \
|
||||
$(COMPILE) -AOBJCOPY -T$@ \
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
MAKE_SYMTAB_CREATE = \
|
||||
$(COMPILE) -wASYMTAB \
|
||||
$(VM) \
|
||||
o/$(MODE)/tool/build/symtab.com \
|
||||
-o $(TMPSAFE)/.symtab \
|
||||
$<
|
||||
|
||||
MAKE_SYMTAB_ZIP = \
|
||||
$(COMPILE) -AZIP -T$@ \
|
||||
$(VM) \
|
||||
o/$(MODE)/third_party/zip/zip.com \
|
||||
-b$(TMPDIR) \
|
||||
-9qj \
|
||||
@@ -246,8 +232,7 @@ o/$(MODE)/%-clang.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-clang.asm: %.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
|
||||
# TODO(jart): Make intrinsics support Clang.
|
||||
# o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
o/$(MODE)/%-clang.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-clang.asm: %.cc
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/bin/sh
|
||||
if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then
|
||||
for last; do true; done
|
||||
if printf '%s\n' "$last" | grep aarch64 >/dev/null 2>&1; then
|
||||
if [ ! -f o/third_party/qemu/qemu-aarch64 ]; then
|
||||
make -j8 o/third_party/qemu/qemu-aarch64
|
||||
fi
|
||||
|
||||
+4
-3
@@ -25,7 +25,8 @@ DSP_BMP_A_CHECKS = \
|
||||
|
||||
DSP_BMP_A_DIRECTDEPS = \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_TINYMATH
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STUBS
|
||||
|
||||
DSP_BMP_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(DSP_BMP_A_DIRECTDEPS),$($(x))))
|
||||
@@ -40,11 +41,11 @@ $(DSP_BMP_A).pkg: \
|
||||
|
||||
o/$(MODE)/dsp/bmp/float2short.o \
|
||||
o/$(MODE)/dsp/bmp/scalevolume.o: private \
|
||||
CFLAGS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
o/tiny/dsp/bmp/scalevolume.o: private \
|
||||
CFLAGS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
DSP_BMP_LIBS = $(foreach x,$(DSP_BMP_ARTIFACTS),$($(x)))
|
||||
|
||||
+2
-1
@@ -26,7 +26,7 @@
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int alaw(int x) {
|
||||
int a, b, i;
|
||||
int a, b, e, i;
|
||||
if ((a = x) < 0) a = ~a;
|
||||
a >>= 4;
|
||||
if (a > 15) {
|
||||
@@ -36,6 +36,7 @@ int alaw(int x) {
|
||||
a -= 16;
|
||||
a += (b + 1) << 4;
|
||||
} else {
|
||||
e = 1;
|
||||
a -= 16;
|
||||
a += 16;
|
||||
}
|
||||
|
||||
+2
-1
@@ -7,7 +7,8 @@
|
||||
*
|
||||
* @define (a + b) / 2
|
||||
*/
|
||||
__funline unsigned char C11(unsigned char al, unsigned char bl) {
|
||||
static inline pureconst artificial unsigned char C11(unsigned char al,
|
||||
unsigned char bl) {
|
||||
short ax;
|
||||
ax = al;
|
||||
ax += bl;
|
||||
|
||||
+3
-2
@@ -3,8 +3,9 @@
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
__funline unsigned char C121(unsigned char al, unsigned char bl,
|
||||
unsigned char cl) {
|
||||
forceinline pureconst artificial unsigned char C121(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char cl) {
|
||||
unsigned short ax, bx;
|
||||
ax = al;
|
||||
ax += bl;
|
||||
|
||||
+3
-1
@@ -2,7 +2,9 @@
|
||||
#define COSMOPOLITAN_DSP_CORE_C121S_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
__funline signed char C121S(signed char al, signed char bl, signed char cl) {
|
||||
forceinline pureconst artificial signed char C121S(signed char al,
|
||||
signed char bl,
|
||||
signed char cl) {
|
||||
short ax, bx;
|
||||
ax = al;
|
||||
ax += bl;
|
||||
|
||||
+4
-2
@@ -9,8 +9,10 @@
|
||||
* @see C161() afterward for superior sin(𝑥)/𝑥
|
||||
* @limit [0,255] → [0..2,044] → [0..255]
|
||||
*/
|
||||
__funline unsigned char C1331(unsigned char al, unsigned char bl,
|
||||
unsigned char cl, unsigned char dl) {
|
||||
forceinline pureconst artificial unsigned char C1331(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char cl,
|
||||
unsigned char dl) {
|
||||
short ax, bx;
|
||||
bx = bl;
|
||||
bx += cl;
|
||||
|
||||
+4
-2
@@ -8,8 +8,10 @@
|
||||
* @define (1*(a-128)+3*(a-128)+3*(a-128)+1*(a-128))/(1+3+3+1)+128
|
||||
* @see C1331(), Y420CbCr2RgbScale()
|
||||
*/
|
||||
__funline signed char C1331S(signed char al, signed char bl, signed char cl,
|
||||
signed char dl) {
|
||||
forceinline pureconst artificial signed char C1331S(signed char al,
|
||||
signed char bl,
|
||||
signed char cl,
|
||||
signed char dl) {
|
||||
short ax, bx;
|
||||
bx = bl;
|
||||
bx += cl;
|
||||
|
||||
+3
-2
@@ -12,8 +12,9 @@
|
||||
* @limit [0..255] → [-510..1,532] → [-127..383] → [0..255]
|
||||
* @see C1331()
|
||||
*/
|
||||
__funline unsigned char C161(unsigned char al, unsigned char bl,
|
||||
unsigned char cl) {
|
||||
forceinline pureconst artificial unsigned char C161(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char cl) {
|
||||
short ax, bx, cx;
|
||||
ax = al;
|
||||
bx = bl;
|
||||
|
||||
+3
-1
@@ -4,7 +4,9 @@
|
||||
#include "libc/macros.internal.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
__funline signed char C161S(signed char al, signed char bl, signed char cl) {
|
||||
forceinline pureconst artificial signed char C161S(signed char al,
|
||||
signed char bl,
|
||||
signed char cl) {
|
||||
short ax, bx, cx;
|
||||
ax = al;
|
||||
bx = bl;
|
||||
|
||||
+3
-2
@@ -9,8 +9,9 @@ COSMOPOLITAN_C_START_
|
||||
* @define (3*a + 3*b + 1*c) / 7
|
||||
* @see C1331()
|
||||
*/
|
||||
__funline unsigned char C331(unsigned char al, unsigned char bl,
|
||||
unsigned char cl) {
|
||||
static inline pureconst artificial unsigned char C331(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char cl) {
|
||||
unsigned eax, ebx, ecx;
|
||||
eax = al;
|
||||
ebx = bl;
|
||||
|
||||
+15
-6
@@ -8,8 +8,16 @@ DSP_CORE = $(DSP_CORE_A_DEPS) $(DSP_CORE_A)
|
||||
DSP_CORE_A = o/$(MODE)/dsp/core/core.a
|
||||
DSP_CORE_A_FILES := $(wildcard dsp/core/*)
|
||||
DSP_CORE_A_HDRS = $(filter %.h,$(DSP_CORE_A_FILES))
|
||||
DSP_CORE_A_SRCS = $(filter %.c,$(DSP_CORE_A_FILES))
|
||||
DSP_CORE_A_OBJS = $(DSP_CORE_A_SRCS:%.c=o/$(MODE)/%.o)
|
||||
DSP_CORE_A_SRCS_S = $(filter %.S,$(DSP_CORE_A_FILES))
|
||||
DSP_CORE_A_SRCS_C = $(filter %.c,$(DSP_CORE_A_FILES))
|
||||
|
||||
DSP_CORE_A_SRCS = \
|
||||
$(DSP_CORE_A_SRCS_S) \
|
||||
$(DSP_CORE_A_SRCS_C)
|
||||
|
||||
DSP_CORE_A_OBJS = \
|
||||
$(DSP_CORE_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(DSP_CORE_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
DSP_CORE_A_CHECKS = \
|
||||
$(DSP_CORE_A).pkg \
|
||||
@@ -20,7 +28,8 @@ DSP_CORE_A_DIRECTDEPS = \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STR \
|
||||
LIBC_TINYMATH
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STUBS
|
||||
|
||||
DSP_CORE_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(DSP_CORE_A_DIRECTDEPS),$($(x))))
|
||||
@@ -39,15 +48,15 @@ o/$(MODE)/dsp/core/magikarp.o \
|
||||
o/$(MODE)/dsp/core/c93654369.o \
|
||||
o/$(MODE)/dsp/core/float2short.o \
|
||||
o/$(MODE)/dsp/core/scalevolume.o: private \
|
||||
CFLAGS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
o/tiny/dsp/core/scalevolume.o: private \
|
||||
CFLAGS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
o/$(MODE)/dsp/core/det3.o: private \
|
||||
CFLAGS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-ffast-math
|
||||
|
||||
DSP_CORE_LIBS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)))
|
||||
|
||||
+2
-2
@@ -11,11 +11,11 @@
|
||||
*
|
||||
* @see round(), rint()
|
||||
*/
|
||||
__funline long ituround(double x) {
|
||||
static inline pureconst artificial long ituround(double x) {
|
||||
return floor(x + .5);
|
||||
}
|
||||
|
||||
__funline int ituroundf(float x) {
|
||||
static inline pureconst artificial int ituroundf(float x) {
|
||||
return floorf(x + .5f);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
.balign 16
|
||||
|
||||
// Mixes audio.
|
||||
//
|
||||
// @param rdi is # aligned int16[16] sample chunks to process
|
||||
// @param rsi points to aligned pcm s16le input/output memory
|
||||
// @param rdx points to aligned pcm s16le [0..1] input memory
|
||||
sad16x8n:
|
||||
.leafprologue
|
||||
.profilable
|
||||
test %rdi,%rdi
|
||||
jz 1f
|
||||
shl $3,%rdi
|
||||
0: sub $8,%rdi
|
||||
movdqa (%rsi,%rdi,2),%xmm0
|
||||
paddsw (%rdx,%rdi,2),%xmm0
|
||||
movdqa %xmm0,(%rsi,%rdi,2)
|
||||
jnz 0b
|
||||
1: .leafepilogue
|
||||
.endfn sad16x8n,globl,hidden
|
||||
+3
-2
@@ -6,8 +6,9 @@ COSMOPOLITAN_C_START_
|
||||
/**
|
||||
* 8-bit linear interpolation kernel.
|
||||
*/
|
||||
__funline unsigned char twixt8(unsigned char al, unsigned char bl,
|
||||
unsigned char p) {
|
||||
static inline pureconst artificial unsigned char twixt8(unsigned char al,
|
||||
unsigned char bl,
|
||||
unsigned char p) {
|
||||
short bx;
|
||||
bx = bl;
|
||||
bx -= al;
|
||||
|
||||
+3
-3
@@ -34,10 +34,10 @@ DSP_MPEG_A_DIRECTDEPS = \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
THIRD_PARTY_COMPILER_RT
|
||||
LIBC_TINYMATH
|
||||
|
||||
DSP_MPEG_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(DSP_MPEG_A_DIRECTDEPS),$($(x))))
|
||||
@@ -51,7 +51,7 @@ $(DSP_MPEG_A).pkg: \
|
||||
$(foreach x,$(DSP_MPEG_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/dsp/mpeg/clamp4int256-k8.o: private \
|
||||
CFLAGS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
DSP_MPEG_LIBS = $(foreach x,$(DSP_MPEG_ARTIFACTS),$($(x)))
|
||||
|
||||
@@ -38,11 +38,11 @@
|
||||
|
||||
signed char g_magikarp[8];
|
||||
const signed char kMagikarp[8][8] = {
|
||||
{-1, -1, 3, 15, 15, 3, -1, -1}, // magic kernel sharp
|
||||
{-1, -3, 6, 28, 6, -3, -1, 0}, //
|
||||
{0, 0, -11, 53, -11, 0, 0, 0}, //
|
||||
{-2, -6, 2, 22, 22, 2, -6, -2}, //
|
||||
{-3, -9, 1, 27, 27, 1, -9, -3}, //
|
||||
{-1, -3, 3, 17, 17, 3, -3, -1}, /* 1331+161 derived w/ one off cas */
|
||||
{-1, -3, 6, 28, 6, -3, -1, 0}, /* no due to the convolution theorem? */
|
||||
{0, 0, -11, 53, -11, 0, 0, 0}, /* no plus, some random experimenting */
|
||||
{-2, -6, 2, 22, 22, 2, -6, -2}, /* one a line please clang-format? */
|
||||
{-3, -9, 1, 27, 27, 1, -9, -3},
|
||||
};
|
||||
|
||||
signed char g_magkern[8];
|
||||
|
||||
+3
-1
@@ -31,6 +31,8 @@ DSP_SCALE_A_DIRECTDEPS = \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_STUBS \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_X
|
||||
@@ -50,7 +52,7 @@ o/$(MODE)/dsp/scale/cdecimate2xuint8x8.o \
|
||||
o/$(MODE)/dsp/scale/gyarados.o \
|
||||
o/$(MODE)/dsp/scale/magikarp.o \
|
||||
o/$(MODE)/dsp/scale/scale.o: private \
|
||||
CFLAGS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
DSP_SCALE_LIBS = $(foreach x,$(DSP_SCALE_ARTIFACTS),$($(x)))
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
*/
|
||||
int ttyconfig(int ttyfd, ttyconf_f fn, int64_t arg,
|
||||
struct termios *opt_out_oldconf) {
|
||||
struct termios conf[2] = {0};
|
||||
struct termios conf[2];
|
||||
if (tcgetattr(ttyfd, &conf[0]) != -1 &&
|
||||
fn(memcpy(&conf[1], &conf[0], sizeof(conf[0])), arg) != -1 &&
|
||||
tcsetattr(ttyfd, TCSAFLUSH, &conf[1]) != -1) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/intrin/pushpop.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ extern char *ttyraster(char *, const struct TtyRgb *, size_t, size_t,
|
||||
|
||||
#ifndef ttyquant
|
||||
#define ttyquant() (&g_ttyquant_)
|
||||
#define TTYQUANT() __veil("r", &g_ttyquant_)
|
||||
#define TTYQUANT() VEIL("r", &g_ttyquant_)
|
||||
#define rgb2tty(...) (ttyquant()->rgb2tty(__VA_ARGS__))
|
||||
#define tty2rgb(...) (ttyquant()->tty2rgb(__VA_ARGS__))
|
||||
#define rgb2ttyf(...) (ttyquant()->rgb2ttyf(__VA_ARGS__))
|
||||
|
||||
+2
-7
@@ -35,6 +35,7 @@ DSP_TTY_A_DIRECTDEPS = \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_STR \
|
||||
LIBC_STDIO \
|
||||
LIBC_STUBS \
|
||||
LIBC_SOCK \
|
||||
LIBC_SYSV \
|
||||
LIBC_TINYMATH \
|
||||
@@ -53,15 +54,9 @@ $(DSP_TTY_A).pkg: \
|
||||
$(foreach x,$(DSP_TTY_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/dsp/tty/ttyraster.o: private \
|
||||
CFLAGS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
# takes 14 seconds to compile with aarch64 gcc
|
||||
o/$(MODE)/dsp/tty/ttyraster.o: private CFLAGS += -O1
|
||||
o/$(MODE)/dsp/tty/ttyraster.o: private QUOTA += -C128
|
||||
endif
|
||||
|
||||
DSP_TTY_LIBS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)))
|
||||
DSP_TTY_SRCS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)_SRCS))
|
||||
DSP_TTY_HDRS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)_HDRS))
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
// @param rdi points to nonempty array
|
||||
// @param rsi is item count divisible by 16
|
||||
// @note needs avx2 (haswell+)
|
||||
.ftrace1
|
||||
windex_avx2:
|
||||
.ftrace2
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
and $-32,%rsp
|
||||
sub $32,%rsp
|
||||
vmovdqa (%rdi),%ymm1
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
// @param rdi points to nonempty array
|
||||
// @param esi is 16-byte aligned 8+ / 8 multiple array item count
|
||||
// @note needs sse4 (nehalem+)
|
||||
.ftrace1
|
||||
windex_sse4:
|
||||
.ftrace2
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $8,%eax
|
||||
sub $32,%rsp
|
||||
movdqa (%rdi),%xmm2
|
||||
|
||||
@@ -16,31 +16,26 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e s
|
||||
.long \e - kPollNames
|
||||
.long .L\@ - kPollNames
|
||||
.rodata.str1.1
|
||||
.L\@: .string "\s"
|
||||
// Dispatches to fastest windex() implementation.
|
||||
.initbss 300,_init_windex
|
||||
windex: .quad 0
|
||||
.endobj windex,globl
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.section .rodata,"a",@progbits
|
||||
.balign 4
|
||||
.underrun
|
||||
kPollNames:
|
||||
.e POLLNVAL "POLLNVAL"
|
||||
.e POLLWRNORM "POLLWRNORM"
|
||||
.e POLLWRBAND "POLLWRBAND"
|
||||
.e POLLRDNORM "POLLRDNORM"
|
||||
.e POLLRDHUP "POLLRDHUP"
|
||||
.e POLLRDBAND "POLLRDBAND"
|
||||
.e POLLHUP "POLLHUP"
|
||||
.e POLLERR "POLLERR"
|
||||
.e POLLPRI "POLLPRI"
|
||||
.e POLLOUT "POLLOUT"
|
||||
.e POLLIN "POLLIN"
|
||||
.endobj kPollNames,globl,hidden
|
||||
.overrun
|
||||
.init.start 300,_init_windex
|
||||
ezlea windex_avx2,ax
|
||||
#if !X86_NEED(AVX2)
|
||||
ezlea windex_sse4,dx
|
||||
testb X86_HAVE(AVX2)+kCpuids(%rip)
|
||||
cmovz %rdx,%rax
|
||||
#endif /* AVX2 */
|
||||
#if !X86_NEED(SSE4_2)
|
||||
ezlea windex_k8,dx
|
||||
testb X86_HAVE(SSE4_2)+kCpuids(%rip)
|
||||
cmovz %rdx,%rax
|
||||
#endif /* SSE4 */
|
||||
stosq
|
||||
.init.end 300,_init_windex
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern unsigned (*windex)(uint16_t *, size_t);
|
||||
extern unsigned (*const windex)(uint16_t *, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/log/log.h"
|
||||
|
||||
/**
|
||||
* Automatically launches GDB Debugger TUI during crash.
|
||||
@@ -41,6 +41,6 @@
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ShowCrashReports();
|
||||
__builtin_trap();
|
||||
asm("int3"); /* cf. __die(), perror("msg"), abort(), exit(1), _Exit(1) */
|
||||
return 0;
|
||||
}
|
||||
@@ -23,7 +23,13 @@ int main(int argc, char *argv[]) {
|
||||
kprintf("try running: o//tool/build/strace.com %s%n", argv[0]);
|
||||
}
|
||||
|
||||
__builtin_trap();
|
||||
asm volatile("mov\t%4,%%r10\n\t"
|
||||
"mov\t%5,%%r8\n\t"
|
||||
"mov\t%6,%%r9\n\t"
|
||||
"int3"
|
||||
: /* no outputs */
|
||||
: "a"(0), "D"(1), "S"(2), "d"(3), "g"(4), "g"(5), "g"(6)
|
||||
: "r8", "r9", "r10");
|
||||
|
||||
printf("recovered from SIGTRAP without handler\r\n");
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
#include "third_party/mbedtls/ssl.h"
|
||||
#include "third_party/mbedtls/x509_crt.h"
|
||||
|
||||
__static_yoink("ssl_root_support");
|
||||
STATIC_YOINK("ssl_root_support");
|
||||
|
||||
#define MODE_NONE 0
|
||||
#define MODE_FILE 1
|
||||
|
||||
+2
-2
@@ -75,8 +75,8 @@
|
||||
* the following functions to further expand the information shown by
|
||||
* the NDEBUG check failure:
|
||||
*
|
||||
* __static_yoink("__die");
|
||||
* __static_yoink("strerror");
|
||||
* STATIC_YOINK("__die");
|
||||
* STATIC_YOINK("strerror");
|
||||
*
|
||||
* Please note that backtraces aren't ever available in MODE=tiny.
|
||||
*/
|
||||
|
||||
+1
-3
@@ -7,17 +7,15 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* @fileoverview clock() function demo
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ShowCrashReports();
|
||||
unsigned long i;
|
||||
volatile unsigned long x;
|
||||
struct timespec now, start, next, interval;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#endif
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
+16
-52
@@ -12,14 +12,14 @@
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "third_party/getopt/getopt.internal.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
#define CHUNK 32768
|
||||
@@ -48,62 +48,26 @@ FLAGS\n\
|
||||
// clang-format off
|
||||
// make -j8 o//examples && dd if=/dev/urandom count=100 | tee a | o//examples/compress.com | o//examples/decompress.com >b && sha1sum a b
|
||||
/*
|
||||
#!/bin/bash
|
||||
# data file is o/dbg/third_party/python/python.com
|
||||
# level 1 348739 compress 22.8 MB/s decompress 444 MB/s
|
||||
# level 2 347549 compress 37.8 MB/s decompress 457 MB/s
|
||||
# level 3 346902 compress 33.3 MB/s decompress 463 MB/s
|
||||
# level 4 345671 compress 29.3 MB/s decompress 467 MB/s
|
||||
# level 5 344392 compress 22.4 MB/s decompress 506 MB/s
|
||||
# level 6 342105 compress 10.9 MB/s decompress 516 MB/s
|
||||
# level 7 342046 compress 7.9 MB/s decompress 515 MB/s
|
||||
# level 8 342009 compress 5.8 MB/s decompress 518 MB/s
|
||||
# level 9 342001 compress 5.7 MB/s decompress 524 MB/s
|
||||
# level F 1 362426 compress 48.2 MB/s decompress 488 MB/s
|
||||
# level F 2 360875 compress 42.7 MB/s decompress 484 MB/s
|
||||
# level F 3 359992 compress 37.1 MB/s decompress 499 MB/s
|
||||
# level F 4 358460 compress 32.9 MB/s decompress 503 MB/s
|
||||
# level F 5 356431 compress 24.0 MB/s decompress 547 MB/s
|
||||
# level F 6 352274 compress 11.6 MB/s decompress 558 MB/s
|
||||
# level F 7 352155 compress 8.7 MB/s decompress 554 MB/s
|
||||
# level F 8 352065 compress 6.3 MB/s decompress 554 MB/s
|
||||
# level F 9 352051 compress 6.2 MB/s decompress 556 MB/s
|
||||
# level L 1 348739 compress 41.1 MB/s decompress 446 MB/s
|
||||
# level L 2 347549 compress 37.4 MB/s decompress 443 MB/s
|
||||
# level L 3 346902 compress 32.3 MB/s decompress 462 MB/s
|
||||
# level L 4 351932 compress 28.8 MB/s decompress 511 MB/s
|
||||
# level L 5 351384 compress 23.6 MB/s decompress 520 MB/s
|
||||
# level L 6 351328 compress 12.1 MB/s decompress 522 MB/s
|
||||
# level L 7 351230 compress 7.3 MB/s decompress 518 MB/s
|
||||
# level L 8 351192 compress 5.7 MB/s decompress 522 MB/s
|
||||
# level L 9 351182 compress 6.5 MB/s decompress 519 MB/s
|
||||
# level R 1 388209 compress 83.1 MB/s decompress 371 MB/s
|
||||
# level R 2 388209 compress 82.3 MB/s decompress 362 MB/s
|
||||
# level R 3 388209 compress 81.8 MB/s decompress 361 MB/s
|
||||
# level R 4 388209 compress 81.7 MB/s decompress 364 MB/s
|
||||
# level R 5 388209 compress 81.7 MB/s decompress 363 MB/s
|
||||
# level R 6 388209 compress 80.1 MB/s decompress 359 MB/s
|
||||
# level R 7 388209 compress 80.3 MB/s decompress 354 MB/s
|
||||
# level R 8 388209 compress 80.3 MB/s decompress 363 MB/s
|
||||
# level R 9 388209 compress 81.3 MB/s decompress 364 MB/s
|
||||
# level H 1 390207 compress 87.6 MB/s decompress 371 MB/s
|
||||
# level H 2 390207 compress 87.5 MB/s decompress 372 MB/s
|
||||
# level H 3 390207 compress 85.5 MB/s decompress 364 MB/s
|
||||
# level H 4 390207 compress 87.3 MB/s decompress 375 MB/s
|
||||
# level H 5 390207 compress 89.0 MB/s decompress 373 MB/s
|
||||
# level H 6 390207 compress 87.3 MB/s decompress 372 MB/s
|
||||
# level H 7 390207 compress 87.0 MB/s decompress 368 MB/s
|
||||
# level H 8 390207 compress 86.2 MB/s decompress 367 MB/s
|
||||
# level H 9 390207 compress 86.9 MB/s decompress 369 MB/s
|
||||
# level 0 147517 compress 495 MB/s decompress 1.4 GB/s
|
||||
# level 1 80274 compress 29.2 MB/s decompress 303 MB/s
|
||||
# level 2 79384 compress 33.8 MB/s decompress 212 MB/s
|
||||
# level 3 78875 compress 28.9 MB/s decompress 224 MB/s
|
||||
# level 4 78010 compress 27.1 MB/s decompress 319 MB/s <-- sweet spot?
|
||||
# level 5 77107 compress 19.5 MB/s decompress 273 MB/s
|
||||
# level 6 75081 compress 10.0 MB/s decompress 99.3 MB/s
|
||||
# level 7 75022 compress 7.5 MB/s decompress 287 MB/s
|
||||
# level 8 75016 compress 5.4 MB/s decompress 109 MB/s
|
||||
# level 9 75016 compress 5.4 MB/s decompress 344 MB/s
|
||||
m=
|
||||
make -j8 MODE=$m o/$m/examples || exit
|
||||
for strategy in ' ' F L R H; do
|
||||
for level in $(seq 1 9); do
|
||||
o/$m/examples/compress.com -$level$strategy <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
|
||||
for strategy in F L R H; do
|
||||
o/$m/examples/compress.com -$strategy$level <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
|
||||
compspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
|
||||
o/$m/examples/decompress.com </tmp/comp | dd count=10000 2>/tmp/info >/dev/null
|
||||
decompspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
|
||||
size=$(o/$m/examples/compress.com -$level$strategy <o/$m/examples/compress.com | wc -c)
|
||||
size=$(o/$m/examples/compress.com -$strategy$level <o/$m/examples/compress.com | wc -c)
|
||||
echo "level $strategy $level $size compress $compspeed decompress $decompspeed"
|
||||
done
|
||||
done
|
||||
@@ -210,7 +174,7 @@ const char *zerr(int rc) {
|
||||
case Z_VERSION_ERROR:
|
||||
return "zlib version mismatch!";
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
|
||||
/**
|
||||
@@ -25,18 +24,14 @@
|
||||
* o//examples/crashreport.com
|
||||
*/
|
||||
|
||||
dontubsan int main(int argc, char *argv[]) {
|
||||
noubsan int main(int argc, char *argv[]) {
|
||||
|
||||
kprintf("----------------\n");
|
||||
kprintf(" THIS IS A TEST \n");
|
||||
kprintf("SIMULATING CRASH\n");
|
||||
kprintf("----------------\n");
|
||||
|
||||
ShowCrashReports();
|
||||
|
||||
volatile double a = 0;
|
||||
volatile double b = 23;
|
||||
volatile double c = exp(b) / a;
|
||||
|
||||
volatile int64_t x;
|
||||
ShowCrashReports();
|
||||
return 1 / (x = 0);
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#include "libc/x/x.h"
|
||||
#include "net/http/escape.h"
|
||||
#include "net/http/http.h"
|
||||
#include "third_party/getopt/getopt.internal.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/stb/stb_image.h"
|
||||
|
||||
#define USAGE \
|
||||
|
||||
+6
-57
@@ -7,66 +7,15 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/x/xiso8601.h"
|
||||
|
||||
/**
|
||||
* @fileoverview High performance ISO-8601 timestamp formatter.
|
||||
* @fileoverview ISO-8601 international high-precision timestamp printer.
|
||||
*/
|
||||
|
||||
char *GetTimestamp(void) {
|
||||
int x;
|
||||
struct timespec ts;
|
||||
_Thread_local static long last;
|
||||
_Thread_local static char s[27];
|
||||
_Thread_local static struct tm tm;
|
||||
clock_gettime(0, &ts);
|
||||
if (ts.tv_sec != last) {
|
||||
localtime_r(&ts.tv_sec, &tm);
|
||||
x = tm.tm_year + 1900;
|
||||
s[0] = '0' + x / 1000;
|
||||
s[1] = '0' + x / 100 % 10;
|
||||
s[2] = '0' + x / 10 % 10;
|
||||
s[3] = '0' + x % 10;
|
||||
s[4] = '-';
|
||||
x = tm.tm_mon + 1;
|
||||
s[5] = '0' + x / 10;
|
||||
s[6] = '0' + x % 10;
|
||||
s[7] = '-';
|
||||
x = tm.tm_mday;
|
||||
s[8] = '0' + x / 10;
|
||||
s[9] = '0' + x % 10;
|
||||
s[10] = 'T';
|
||||
x = tm.tm_hour;
|
||||
s[11] = '0' + x / 10;
|
||||
s[12] = '0' + x % 10;
|
||||
s[13] = ':';
|
||||
x = tm.tm_min;
|
||||
s[14] = '0' + x / 10;
|
||||
s[15] = '0' + x % 10;
|
||||
s[16] = ':';
|
||||
x = tm.tm_sec;
|
||||
s[17] = '0' + x / 10;
|
||||
s[18] = '0' + x % 10;
|
||||
s[19] = '.';
|
||||
s[26] = 0;
|
||||
last = ts.tv_sec;
|
||||
}
|
||||
x = ts.tv_nsec;
|
||||
s[20] = '0' + x / 100000000;
|
||||
s[21] = '0' + x / 10000000 % 10;
|
||||
s[22] = '0' + x / 1000000 % 10;
|
||||
s[23] = '0' + x / 100000 % 10;
|
||||
s[24] = '0' + x / 10000 % 10;
|
||||
s[25] = '0' + x / 1000 % 10;
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char buf[128], *p = buf;
|
||||
p = stpcpy(p, GetTimestamp());
|
||||
p = stpcpy(p, "\n");
|
||||
write(1, buf, p - buf);
|
||||
puts(_gc(xiso8601ts(NULL)));
|
||||
return 0;
|
||||
}
|
||||
+31
-2
@@ -10,14 +10,43 @@
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
#define CHUNK 32768
|
||||
|
||||
// clang-format off
|
||||
// make -j8 o//examples && dd if=/dev/urandom count=100 | tee a | o//examples/compress.com | o//examples/decompress.com >b && sha1sum a b
|
||||
/*
|
||||
# data file is o/dbg/third_party/python/python.com
|
||||
# level 0 147517 compress 495 MB/s decompress 1.4 GB/s
|
||||
# level 1 80274 compress 29.2 MB/s decompress 303 MB/s
|
||||
# level 2 79384 compress 33.8 MB/s decompress 212 MB/s
|
||||
# level 3 78875 compress 28.9 MB/s decompress 224 MB/s
|
||||
# level 4 78010 compress 27.1 MB/s decompress 319 MB/s <-- sweet spot?
|
||||
# level 5 77107 compress 19.5 MB/s decompress 273 MB/s
|
||||
# level 6 75081 compress 10.0 MB/s decompress 99.3 MB/s
|
||||
# level 7 75022 compress 7.5 MB/s decompress 287 MB/s
|
||||
# level 8 75016 compress 5.4 MB/s decompress 109 MB/s
|
||||
# level 9 75016 compress 5.4 MB/s decompress 344 MB/s
|
||||
m=
|
||||
make -j8 MODE=$m o/$m/examples || exit
|
||||
for level in $(seq 0 9); do
|
||||
for strategy in F L R H; do
|
||||
o/$m/examples/compress.com -$strategy$level <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
|
||||
compspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
|
||||
o/$m/examples/decompress.com </tmp/comp | dd count=10000 2>/tmp/info >/dev/null
|
||||
decompspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
|
||||
size=$(o/$m/examples/compress.com -$strategy$level <o/$m/examples/compress.com | wc -c)
|
||||
echo "level $strategy $level $size compress $compspeed decompress $decompspeed"
|
||||
done
|
||||
done
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
int decompressor(int infd, int outfd) {
|
||||
int rc;
|
||||
unsigned have;
|
||||
@@ -82,7 +111,7 @@ const char *zerr(int rc) {
|
||||
case Z_VERSION_ERROR:
|
||||
return "zlib version mismatch!";
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ EXAMPLES_DIRECTDEPS = \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TESTLIB \
|
||||
@@ -76,10 +77,10 @@ EXAMPLES_DIRECTDEPS = \
|
||||
THIRD_PARTY_DOUBLECONVERSION \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_HIREDIS \
|
||||
THIRD_PARTY_LIBCXX \
|
||||
THIRD_PARTY_LINENOISE \
|
||||
THIRD_PARTY_LUA \
|
||||
THIRD_PARTY_HIREDIS \
|
||||
THIRD_PARTY_MBEDTLS \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_NSYNC \
|
||||
@@ -102,7 +103,7 @@ o/$(MODE)/examples/examples.pkg: \
|
||||
$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/examples/unbourne.o: private \
|
||||
CPPFLAGS += \
|
||||
OVERRIDE_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED \
|
||||
-fpie
|
||||
|
||||
@@ -161,14 +162,13 @@ o/$(MODE)/examples/nesemu1.com.dbg: \
|
||||
o/$(MODE)/examples/symtab.com: \
|
||||
o/$(MODE)/examples/symtab.com.dbg \
|
||||
o/$(MODE)/third_party/zip/zip.com \
|
||||
o/$(MODE)/tool/build/symtab.com \
|
||||
$(VM)
|
||||
o/$(MODE)/tool/build/symtab.com
|
||||
@$(MAKE_OBJCOPY)
|
||||
@$(MAKE_SYMTAB_CREATE)
|
||||
@$(MAKE_SYMTAB_ZIP)
|
||||
|
||||
o/$(MODE)/examples/picol.o: private \
|
||||
CPPFLAGS += \
|
||||
OVERRIDE_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
||||
o/$(MODE)/examples/picol.com.dbg: \
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
__static_yoink("strerror");
|
||||
STATIC_YOINK("strerror");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sigset_t ss;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "libc/sysv/consts/grnd.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "third_party/getopt/getopt.internal.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
|
||||
#define B 4096
|
||||
|
||||
@@ -77,8 +77,8 @@ uint64_t unixv7(void) {
|
||||
|
||||
uint64_t ape(void) {
|
||||
static int i;
|
||||
if ((i += 8) > _end - __executable_start) i = 8;
|
||||
return READ64LE(__executable_start + i);
|
||||
if ((i += 8) > _end - _base) i = 8;
|
||||
return READ64LE(_base + i);
|
||||
}
|
||||
|
||||
uint64_t moby(void) {
|
||||
|
||||
@@ -176,7 +176,7 @@ void *Worker(void *id) {
|
||||
// inherited by the accepted sockets, but using them also has the
|
||||
// side-effect that the listening socket fails with EAGAIN, every
|
||||
// several seconds. we can use that to our advantage to check for
|
||||
// the ctrl-c shutdowne event; otherwise we retry the accept call
|
||||
// the ctrl-c shutdowne event; otherwise, we retry the accept call
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ void *Worker(void *id) {
|
||||
// we're not terrible concerned when errors happen here
|
||||
if ((got = read(client, inbuf, sizeof(inbuf))) <= 0) break;
|
||||
// check that client message wasn't fragmented into more reads
|
||||
if ((inmsglen = ParseHttpMessage(&msg, inbuf, got)) <= 0) break;
|
||||
if (!(inmsglen = ParseHttpMessage(&msg, inbuf, got))) break;
|
||||
++messages;
|
||||
|
||||
#if LOGGING
|
||||
|
||||
+4
-1
@@ -7,9 +7,12 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
STATIC_YOINK("mmap"); // TODO: fix bandaid for MODE=asan
|
||||
|
||||
int main() {
|
||||
printf("hello world\n");
|
||||
printf("%s\n", "hello world");
|
||||
return 0;
|
||||
}
|
||||
+2
-2
@@ -8,10 +8,10 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/errno.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main() {
|
||||
printf("%g %`'s\n", M_PI, "hello\1\2world→→");
|
||||
printf("%`'s\n", "hello\1\2world→→");
|
||||
return errno;
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
#include "libc/x/xasprintf.h"
|
||||
#include "net/http/escape.h"
|
||||
#include "net/http/http.h"
|
||||
#include "third_party/getopt/getopt.internal.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/stb/stb_image.h"
|
||||
|
||||
#define USAGE \
|
||||
|
||||
+1
-1
@@ -355,7 +355,7 @@ int getCursorPosition(int64_t ifd, int64_t ofd, int *rows, int *cols) {
|
||||
* Returns 0 on success, -1 on error. */
|
||||
int getWindowSize(int64_t ifd, int64_t ofd, int *rows, int *cols) {
|
||||
struct winsize ws;
|
||||
if (tcgetwinsize(1, &ws) == -1 || ws.ws_col == 0) {
|
||||
if (_getttysize(1, &ws) == -1 || ws.ws_col == 0) {
|
||||
/* ioctl() failed. Try to query the terminal itself. */
|
||||
int orig_row, orig_col, retval;
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "third_party/getopt/getopt.internal.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
|
||||
/**
|
||||
* @fileoverview netcat clone
|
||||
|
||||
+4
-5
@@ -14,7 +14,6 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
@@ -42,13 +41,13 @@
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
#include "libc/x/xsigaction.h"
|
||||
#include "libc/zip.internal.h"
|
||||
#include "libc/zip.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
#include "third_party/getopt/getopt.internal.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/libcxx/vector"
|
||||
#include "tool/viz/lib/knobs.h"
|
||||
|
||||
__static_yoink("zipos");
|
||||
STATIC_YOINK("zipos");
|
||||
|
||||
#define USAGE \
|
||||
" [ROM] [FMV]\n\
|
||||
@@ -288,7 +287,7 @@ void GetTermSize(void) {
|
||||
struct winsize wsize_;
|
||||
wsize_.ws_row = 25;
|
||||
wsize_.ws_col = 80;
|
||||
tcgetwinsize(0, &wsize_);
|
||||
_getttysize(0, &wsize_);
|
||||
FreeSamplingSolution(ssy_);
|
||||
FreeSamplingSolution(ssx_);
|
||||
tyn_ = wsize_.ws_row * 2;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (__executable_start[0] == 'M' && __executable_start[1] == 'Z') {
|
||||
if (_base[0] == 'M' && _base[1] == 'Z') {
|
||||
printf("success: %s spawned without needing to modify its "
|
||||
"executable header",
|
||||
argv[0]);
|
||||
|
||||
@@ -43,6 +43,7 @@ EXAMPLES_PACKAGE_DIRECTDEPS = \
|
||||
EXAMPLES_PACKAGE_LIB \
|
||||
LIBC_INTRIN \
|
||||
LIBC_STDIO \
|
||||
LIBC_STUBS \
|
||||
LIBC_TINYMATH
|
||||
|
||||
# Evaluates the set of transitive package dependencies.
|
||||
|
||||
@@ -69,9 +69,10 @@ EXAMPLES_PACKAGE_LIB_A_CHECKS = \
|
||||
# Lists packages whose symbols are or may be directly referenced here.
|
||||
# Note that linking stubs is always a good idea due to synthetic code.
|
||||
EXAMPLES_PACKAGE_LIB_A_DIRECTDEPS = \
|
||||
LIBC_STDIO \
|
||||
LIBC_INTRIN \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STDIO
|
||||
LIBC_STUBS
|
||||
|
||||
# Evaluates variable as set of transitive package dependencies.
|
||||
EXAMPLES_PACKAGE_LIB_A_DEPS := \
|
||||
@@ -95,10 +96,6 @@ $(EXAMPLES_PACKAGE_LIB_A).pkg: \
|
||||
# Invalidates objects in package when makefile is edited.
|
||||
$(EXAMPLES_PACKAGE_LIB_A_OBJS): examples/package/lib/build.mk
|
||||
|
||||
# let these assembly objects build on aarch64
|
||||
o/$(MODE)/examples/package/lib/myasm.o: examples/package/lib/myasm.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
EXAMPLES_PACKAGE_LIB_LIBS = $(foreach x,$(EXAMPLES_PACKAGE_LIB_ARTIFACTS),$($(x)))
|
||||
EXAMPLES_PACKAGE_LIB_SRCS = $(foreach x,$(EXAMPLES_PACKAGE_LIB_ARTIFACTS),$($(x)_SRCS))
|
||||
EXAMPLES_PACKAGE_LIB_HDRS = $(foreach x,$(EXAMPLES_PACKAGE_LIB_ARTIFACTS),$($(x)_HDRS))
|
||||
|
||||
@@ -8,18 +8,9 @@
|
||||
// somehow they usually make code faster
|
||||
// it's convention for keeping stack 16-byte aligned
|
||||
// cpus still devote much to pushing & popping b/c i386
|
||||
MyAsm:
|
||||
|
||||
#ifdef __x86_64__
|
||||
push %rbp
|
||||
MyAsm: push %rbp
|
||||
mov %rsp,%rbp
|
||||
call MyPrint2
|
||||
pop %rbp
|
||||
#elif defined(__aarch64__)
|
||||
bl MyPrint2
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
|
||||
ret
|
||||
.endfn MyAsm,globl
|
||||
+5
-5
@@ -8,10 +8,10 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/gdb.h"
|
||||
@@ -77,7 +77,7 @@ void GetTtySize(void) {
|
||||
struct winsize wsize;
|
||||
wsize.ws_row = tyn;
|
||||
wsize.ws_col = txn;
|
||||
tcgetwinsize(1, &wsize);
|
||||
_getttysize(1, &wsize);
|
||||
tyn = wsize.ws_row;
|
||||
txn = wsize.ws_col;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ int Write(const char *s) {
|
||||
}
|
||||
|
||||
void Setup(void) {
|
||||
CHECK_NE(-1, tcgetattr(1, &oldterm));
|
||||
CHECK_NE(-1, ioctl(1, TCGETS, &oldterm));
|
||||
}
|
||||
|
||||
void Enter(void) {
|
||||
@@ -100,13 +100,13 @@ void Enter(void) {
|
||||
term.c_cflag &= ~(CSIZE | PARENB);
|
||||
term.c_cflag |= CS8;
|
||||
term.c_iflag |= IUTF8;
|
||||
CHECK_NE(-1, tcsetattr(1, TCSANOW, &term));
|
||||
CHECK_NE(-1, ioctl(1, TCSETS, &term));
|
||||
Write("\e[?25l");
|
||||
}
|
||||
|
||||
void Leave(void) {
|
||||
Write(gc(xasprintf("\e[?25h\e[%d;%dH\e[S\r\n", tyn, txn)));
|
||||
tcsetattr(1, TCSANOW, &oldterm);
|
||||
ioctl(1, TCSETS, &oldterm);
|
||||
}
|
||||
|
||||
void Clear(void) {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "third_party/getopt/getopt.internal.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
@@ -176,7 +176,7 @@ main(int argc, char *argv[])
|
||||
playback(fscript);
|
||||
|
||||
if (tcgetattr(STDIN_FILENO, &tt) == -1 ||
|
||||
tcgetwinsize(STDIN_FILENO, &win) == -1) {
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1) {
|
||||
if (errno != ENOTTY) /* For debugger. */
|
||||
err(1, "tcgetattr/ioctl");
|
||||
if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
|
||||
/**
|
||||
* @fileoverview swapcontext() and makecontext() example
|
||||
* @note adapted from the Linux man-pages project
|
||||
*/
|
||||
|
||||
static ucontext_t uctx_main;
|
||||
static ucontext_t uctx_func1;
|
||||
static ucontext_t uctx_func2;
|
||||
|
||||
#define say(s) write(1, s, strlen(s))
|
||||
#define handle_error(msg) \
|
||||
do { \
|
||||
perror(msg); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static void func1(void) {
|
||||
say("func1: started\n");
|
||||
say("func1: swapcontext(&uctx_func1, &uctx_func2)\n");
|
||||
if (swapcontext(&uctx_func1, &uctx_func2) == -1) {
|
||||
handle_error("swapcontext");
|
||||
}
|
||||
say("func1: returning\n");
|
||||
}
|
||||
|
||||
static void func2(void) {
|
||||
say("func2: started\n");
|
||||
say("func2: swapcontext(&uctx_func2, &uctx_func1)\n");
|
||||
if (swapcontext(&uctx_func2, &uctx_func1) == -1) {
|
||||
handle_error("swapcontext");
|
||||
}
|
||||
say("func2: returning\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char func1_stack[8192];
|
||||
char func2_stack[8192];
|
||||
|
||||
if (getcontext(&uctx_func1) == -1) {
|
||||
handle_error("getcontext");
|
||||
}
|
||||
uctx_func1.uc_stack.ss_sp = func1_stack;
|
||||
uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
|
||||
uctx_func1.uc_link = &uctx_main;
|
||||
makecontext(&uctx_func1, func1, 0);
|
||||
|
||||
if (getcontext(&uctx_func2) == -1) {
|
||||
handle_error("getcontext");
|
||||
}
|
||||
uctx_func2.uc_stack.ss_sp = func2_stack;
|
||||
uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
|
||||
/* Successor context is f1(), unless argc > 1 */
|
||||
uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
|
||||
makecontext(&uctx_func2, func2, 0);
|
||||
|
||||
say("main: swapcontext(&uctx_main, &uctx_func2)\n");
|
||||
if (swapcontext(&uctx_main, &uctx_func2) == -1) {
|
||||
handle_error("swapcontext");
|
||||
}
|
||||
|
||||
say("main: exiting\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
Loaded 100 of 8892 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user