commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
--- |
||||
BasedOnStyle: Google |
||||
StatementMacros: |
||||
- INITIALIZER |
||||
AlignConsecutiveMacros: true |
||||
AlignConsecutiveDeclarations: false |
||||
AlwaysBreakBeforeMultilineStrings: false |
||||
AllowShortFunctionsOnASingleLine: false |
||||
KeepEmptyLinesAtTheStartOfBlocks: true |
||||
--- |
||||
Language: Proto |
||||
... |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
/o |
||||
|
||||
*.tmp |
||||
/.bochs.log |
||||
/HTAGS |
||||
/TAGS |
||||
/bx_enh_dbg.ini |
||||
/tool/emacs/*.elc |
@ -0,0 +1,259 @@
@@ -0,0 +1,259 @@
|
||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Freestanding Hermetically-Sealed Monolithic Repository
|
||||
#
|
||||
# REQUIREMENTS
|
||||
#
|
||||
# You can run your programs on any operating system, but you have
|
||||
# to build them on Linux 2.6+ (or WSL) using GNU Make. A modern C
|
||||
# compiler that's statically-linked comes included as a courtesy.
|
||||
#
|
||||
# EXAMPLES
|
||||
#
|
||||
# # build and run everything
|
||||
# make -j8 -O
|
||||
# make -j8 -O MODE=dbg
|
||||
# make -j8 -O MODE=opt
|
||||
# make -j8 -O MODE=rel
|
||||
# make -j8 -O MODE=tiny
|
||||
#
|
||||
# # build individual target
|
||||
# make -j8 -O o//examples/hello.com
|
||||
# o//examples/hello.com
|
||||
#
|
||||
# # view source
|
||||
# less examples/hello.c
|
||||
#
|
||||
# # view binary
|
||||
# o//tool/viz/bing.com o//examples/hello.com |
|
||||
# o//tool/viz/fold.com
|
||||
#
|
||||
# # view transitive closure of legalese
|
||||
# o//tool/viz/bing.com -n o//examples/hello.com |
|
||||
# o//tool/viz/fold.com
|
||||
#
|
||||
# # basic debugging
|
||||
# make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
|
||||
# o/dbg/examples/crashreport.com
|
||||
# less examples/crashreport.c
|
||||
#
|
||||
# # extremely tiny binaries
|
||||
# make -j8 -O MODE=tiny \
|
||||
# LDFLAGS=-s \
|
||||
# CPPFLAGS=-DSUPPORT_VECTOR=0b00000001 \
|
||||
# o/tiny/examples/hello4.elf
|
||||
# ls -hal o/tiny/examples/hello4.elf
|
||||
# o/tiny/examples/hello4.elf
|
||||
#
|
||||
# TROUBLESHOOTING
|
||||
#
|
||||
# make -j8 -O SILENT=0 o//examples/hello.com
|
||||
# make o//examples/life.elf -pn |& less
|
||||
# etc.
|
||||
#
|
||||
# SEE ALSO
|
||||
#
|
||||
# build/config.mk
|
||||
|
||||
SHELL = dash |
||||
HOSTS ?= freebsd openbsd alpine |
||||
|
||||
.SUFFIXES: |
||||
.DELETE_ON_ERROR: |
||||
.FEATURES: output-sync |
||||
.PHONY: all o bins check test depend tags |
||||
|
||||
all: o |
||||
o: o/libc \ |
||||
o/$(MODE)/ape \
|
||||
o/$(MODE)/dsp \
|
||||
o/$(MODE)/net \
|
||||
o/$(MODE)/libc \
|
||||
o/$(MODE)/test \
|
||||
o/$(MODE)/tool \
|
||||
o/$(MODE)/examples \
|
||||
o/$(MODE)/third_party |
||||
|
||||
PKGS = |
||||
|
||||
include build/functions.mk #─┐
|
||||
include build/definitions.mk # ├──meta
|
||||
include build/config.mk # │
|
||||
include build/rules.mk # │
|
||||
include build/online.mk # │
|
||||
include libc/stubs/stubs.mk #─┘
|
||||
include libc/nexgen32e/nexgen32e.mk #─┐
|
||||
include libc/intrin/intrin.mk # │
|
||||
include libc/math/math.mk # ├──metal
|
||||
include libc/tinymath/tinymath.mk # │
|
||||
include third_party/compiler_rt/compiler_rt.mk # │
|
||||
include libc/bits/bits.mk # │
|
||||
include libc/str/str.mk # │
|
||||
include third_party/xed/xed.mk # │
|
||||
include third_party/zlib/zlib.mk # │
|
||||
include libc/elf/elf.mk # │
|
||||
include ape/lib/apelib.mk # │
|
||||
include ape/ape.mk #─┘
|
||||
include libc/sysv/sysv.mk #─┐
|
||||
include libc/nt/nt.mk # ├──system
|
||||
include libc/conv/conv.mk # │
|
||||
include libc/fmt/fmt.mk # │
|
||||
include libc/rand/rand.mk #─┘
|
||||
include libc/calls/calls.mk #─┐
|
||||
include libc/runtime/runtime.mk # ├──systems
|
||||
include libc/unicode/unicode.mk # │
|
||||
include third_party/dlmalloc/dlmalloc.mk # │
|
||||
include libc/mem/mem.mk # │
|
||||
include libc/zipos/zipos.mk # │
|
||||
include third_party/dtoa/dtoa.mk # │
|
||||
include libc/time/time.mk # │
|
||||
include libc/escape/escape.mk # │
|
||||
include libc/alg/alg.mk # │
|
||||
include libc/calls/hefty/hefty.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include third_party/f2c/f2c.mk # │
|
||||
include third_party/blas/blas.mk # │
|
||||
include net/net.mk # │
|
||||
include libc/log/log.mk # │
|
||||
include dsp/core/core.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/musl/musl.mk # │
|
||||
include third_party/getopt/getopt.mk # │
|
||||
include libc/libc.mk #─┘
|
||||
include libc/sock/sock.mk #─┐
|
||||
include dsp/tty/tty.mk # ├──online
|
||||
include libc/dns/dns.mk # │
|
||||
include libc/crypto/crypto.mk # │
|
||||
include net/http/http.mk #─┘
|
||||
include third_party/linenoise/linenoise.mk |
||||
include third_party/editline/editline.mk |
||||
include third_party/duktape/duktape.mk |
||||
include third_party/regex/regex.mk |
||||
include third_party/avir/avir.mk |
||||
include third_party/third_party.mk |
||||
include libc/testlib/testlib.mk |
||||
include libc/crt/crt.mk |
||||
include tool/viz/lib/vizlib.mk |
||||
include examples/examples.mk |
||||
include third_party/lex/lex.mk |
||||
include third_party/m4/m4.mk |
||||
include third_party/lz4cli/lz4cli.mk |
||||
include third_party/bzip2/bzip2.mk |
||||
include tool/build/lib/buildlib.mk |
||||
include tool/build/build.mk |
||||
include tool/debug/debug.mk |
||||
include tool/decode/lib/decodelib.mk |
||||
include tool/decode/decode.mk |
||||
include tool/hash/hash.mk |
||||
include tool/net/net.mk |
||||
include tool/viz/viz.mk |
||||
include tool/cc/cc.mk |
||||
include tool/tool.mk |
||||
include test/libc/alg/test.mk |
||||
include test/libc/tinymath/test.mk |
||||
include test/libc/math/test.mk |
||||
include test/libc/intrin/test.mk |
||||
include test/libc/mem/test.mk |
||||
include test/libc/nexgen32e/test.mk |
||||
include test/libc/runtime/test.mk |
||||
include test/libc/sock/test.mk |
||||
include test/libc/bits/test.mk |
||||
include test/libc/crypto/test.mk |
||||
include test/libc/str/test.mk |
||||
include test/libc/unicode/test.mk |
||||
include test/libc/calls/test.mk |
||||
include test/libc/x/test.mk |
||||
include test/libc/xed/test.mk |
||||
include test/libc/fmt/test.mk |
||||
include test/libc/dns/test.mk |
||||
include test/libc/rand/test.mk |
||||
include test/libc/time/test.mk |
||||
include test/libc/stdio/test.mk |
||||
include test/libc/conv/test.mk |
||||
include test/libc/test.mk |
||||
include test/ape/lib/test.mk |
||||
include test/ape/test.mk |
||||
include test/net/http/test.mk |
||||
include test/net/test.mk |
||||
include test/tool/build/lib/test.mk |
||||
include test/tool/build/test.mk |
||||
include test/tool/viz/lib/test.mk |
||||
include test/tool/viz/test.mk |
||||
include test/tool/test.mk |
||||
include test/test.mk |
||||
include test/dsp/core/test.mk |
||||
include test/dsp/scale/test.mk |
||||
include test/dsp/tty/test.mk |
||||
include test/dsp/test.mk |
||||
|
||||
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS)) |
||||
SRCS = $(foreach x,$(PKGS),$($(x)_SRCS)) |
||||
HDRS = $(foreach x,$(PKGS),$($(x)_HDRS)) |
||||
BINS = $(foreach x,$(PKGS),$($(x)_BINS)) |
||||
TESTS = $(foreach x,$(PKGS),$($(x)_TESTS)) |
||||
CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS)) |
||||
|
||||
bins: $(BINS) |
||||
check: $(CHECKS) |
||||
test: $(TESTS) |
||||
depend: o/$(MODE)/depend |
||||
tags: TAGS HTAGS |
||||
|
||||
o/$(MODE)/.x: |
||||
@mkdir -p $(dir $@) && touch $@ |
||||
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x)))) |
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x))) |
||||
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS),$(dir $(x)))) |
||||
$(file >$@) $(foreach x,$(HDRS),$(file >>$@,$(x))) |
||||
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt $(SRCS) $(HDRS) |
||||
@build/mkdeps -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt |
||||
|
||||
TAGS: o/$(MODE)/srcs.txt $(SRCS) |
||||
@rm -f $@ |
||||
@ACTION=TAGS TARGET=$@ build/do $(TAGS) $(TAGSFLAGS) -L $< -o $@ |
||||
|
||||
HTAGS: o/$(MODE)/hdrs.txt $(HDRS) |
||||
@rm -f $@ |
||||
@ACTION=TAGS TARGET=$@ build/do build/htags -L $< -o $@ |
||||
|
||||
loc:; find -name \*.h -or -name \*.c -or -name \*.S | \ |
||||
$(XARGS) wc -l | grep total | awk '{print $$1}' | summy |
||||
|
||||
# UNSPECIFIED PREREQUISITES TUTORIAL
|
||||
#
|
||||
# A build rule must exist for all files that make needs to consider in
|
||||
# order to build the requested goal. That includes input source files,
|
||||
# even if the rule is empty and does nothing. Otherwise, the .DEFAULT
|
||||
# rule gets triggered.
|
||||
#
|
||||
# This is a normal and neecssary behavior when source files get deleted.
|
||||
# The build reacts automatically to this happening, by simply deleting
|
||||
# and regenerating the dependency graph; so we can safely use wildcard.
|
||||
#
|
||||
# This is abnormal if it needs to keep doing that repeatedly. That can
|
||||
# only mean the build config is broken.
|
||||
#
|
||||
# Also note that a suboptimal in-between state may exist, where running
|
||||
# `make -pn` reveals rules being generated with the .DEFAULT target, but
|
||||
# never get executed since they're not members of the transitive closure
|
||||
# of `make all`. In that case the build config could be improved.
|
||||
%.mk: |
||||
$(SRCS): |
||||
$(HDRS): |
||||
.DEFAULT: |
||||
@echo >&2 |
||||
@echo NOTE: deleting o/$(MODE)/depend due to unspecified prerequisite: $@ >&2 |
||||
@echo >&2 |
||||
rm -f o/$(MODE)/depend |
||||
|
||||
-include o/$(MODE)/depend |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
# Cosmopolitan |
||||
|
||||
Cosmopolitan builds run natively on most platforms without dependencies, |
||||
because it implements the subset of the C library, compiler runtimes and |
||||
system call interfaces that've achieved near universal consensus amongst |
||||
all major platforms, e.g. Linux/BSD/XNU/NT. Containerization is achieved |
||||
by having binaries also be ZIP files. Modern static stock GNU toolchains |
||||
are provided in a hermetic mono repo for maximum historical determinism. |
||||
|
||||
Here's how you can get started by printing cat videos inside a terminal: |
||||
|
||||
make -j8 o//tool/viz/printvideo.com |
||||
wget https://justine.storage.googleapis.com/cats.mpg |
||||
o//tool/viz/printvideo.com cats.mpg |
||||
unzip -vl o//tool/viz/printvideo.com |
||||
|
||||
Cosmopolitan provides a native development environment similar to those |
||||
currently being offered by RedHat, Google, Apple, Microsoft, etc. We're |
||||
different in two ways: (1) we're not a platform therefore we don't have |
||||
any commercial interest in making our tooling work better on one rather |
||||
than another; and (2) we're only focused on catering towards interfaces |
||||
all platforms agree upon. Goal is software that stands the test of time |
||||
without the costs and restrictions cross-platform distribution entails. |
||||
That makes Cosmopolitan an excellent fit for writing small CLI programs |
||||
that do things like heavyweight numerical computations as a subprocess. |
||||
|
||||
## Licensing |
||||
|
||||
Cosmopolitan is Free Software licensed under the GPLv2. The build config |
||||
**will embed all linked sources inside your binaries** so the compliance |
||||
is easy while facilitating trust and transparency similar to JavaScript. |
||||
You can audit your source filesystem using ZIP GUIs e.g. WIN10, InfoZip. |
||||
|
||||
### Commercial Support |
||||
|
||||
If you want to be able to distribute binaries in binary form only, then |
||||
please send $1,000 to jtunney@gmail.com on PayPal for a license lasting |
||||
1 year. Please be sure to provide your contact information, and details |
||||
on whether or not the license is for an individual or a corporation. If |
||||
you want your license to last 5 years, send $10,000 to the author above |
||||
who is Justine Tunney <jtunney@gmail.com>. This README will be updated, |
||||
if pricing and other details should change. Reach out for more details. |
||||
|
||||
## Contributing |
||||
|
||||
We'd love to accept your patches! Before we can take them, we have to |
||||
jump through one legal hurdle. Please write an email to Justine Tunney |
||||
<jtunney@gmail.com> saying you agree to give her copyright ownership to |
||||
any changes you contribute to Cosmopolitan. We need to do that in order |
||||
to dual license Cosmopolitan. Otherwise we can't tax corporations that |
||||
don't want to share their code with the community. |
@ -0,0 +1,660 @@
@@ -0,0 +1,660 @@
|
||||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │ |
||||
│ │ |
||||
│ This program is free software; you can redistribute it and/or modify │ |
||||
│ it under the terms of the GNU General Public License as published by │ |
||||
│ the Free Software Foundation; version 2 of the License. │ |
||||
│ │ |
||||
│ This program is distributed in the hope that it will be useful, but │ |
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │ |
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │ |
||||
│ General Public License for more details. │ |
||||
│ │ |
||||
│ You should have received a copy of the GNU General Public License │ |
||||
│ along with this program; if not, write to the Free Software │ |
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │ |
||||
│ 02110-1301 USA │ |
||||
╠──────────────────────────────────────────────────────────────────────────────╣ |
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ |
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│ |
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│ |
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│ |
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│ |
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│ |
||||
│ αcτµαlly pδrταblε εxεcµταblε § linker │ |
||||
╚──────────────────────────────────────────────────────────────────────────────╝ |
||||
Having an executable run natively on stock Windows / Mac / Linux / BSD |
||||
entails two steps: (1) create a .com.dbg binary w/ Linux toolchain and |
||||
then (2) unwrap the .com binary embedded within: |
||||
|
||||
objcopy -SO binary input.com.dbg output.com |
||||
|
||||
Both executables will work fine, but only the .com format is portable. |
||||
|
||||
───BUILDING───────────────────────────────────────────────────────────── |
||||
|
||||
LC_ALL=C ld -T ape/ape.lds ... |
||||
|
||||
───RUNNING────────────────────────────────────────────────────────────── |
||||
|
||||
./foo.com.dbg # works on host machine |
||||
./foo.com # works on any os / arch |
||||
qemu-system-x86_64 -s foo.com # works on any os / arch |
||||
|
||||
───BACKGROUND─────────────────────────────────────────────────────────── |
||||
|
||||
The purpose of this software is to help native programs have the same |
||||
level of consistency, in terms of user experience, that we enjoy with |
||||
web applications. It's basically like MeteorJS, except primarily CLI, |
||||
bootable, and more on the order of a few kilobytes than hundred megs. |
||||
|
||||
Rather than Isomorphic JavaScript it's built using Isomorphic Binary, |
||||
since it grants the fastest possible performance and can be trivially |
||||
emulated in the browser. System resource utilization is also a few kb |
||||
and GUIs are possible too since Cosmopolitan exports the Windows API, |
||||
but we recommend doing it with a CLI web server instead and embedding |
||||
files in your αcτµαlly pδrταblε εxεcµταblε as it's isomorphic to zip. |
||||
|
||||
Isomorphic Binary principles state that most platform differences are |
||||
just numbers, which we integrate easily into a unified business logic |
||||
through the use of a sufficiently powerful linker. System numbers are |
||||
otherwise known as ABIs and they're usually the most stable canonical |
||||
interfaces that platforms provide. This is how we are able to support |
||||
more versions of Linux than most Linux-only software, e.g. glibc FTMP |
||||
|
||||
───DEBUGGING──────────────────────────────────────────────────────────── |
||||
|
||||
Can be done in a few ways: |
||||
|
||||
gdb --tui foo.com.dbg |
||||
gdb --tui foo.com -ex 'add-symbol-file foo.com.dbg 0x200000' |
||||
gdb --tui -ex 'add-symbol-file foo.com.dbg 0x7c00' \ |
||||
-ex 'add-symbol-file foo.com.dbg 0x200000' \ |
||||
-ex -target remote localhost:1234' |
||||
|
||||
───TRANSPARENCY───────────────────────────────────────────────────────── |
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is designed to facilitate maximum |
||||
transparency to engender trust in this linker process. |
||||
|
||||
The headers and symbols can be viewed using readelf or objdump: |
||||
|
||||
readelf -Wa input.com.dbg # maximum transparency |
||||
objdump -wxd input.com.dbg # maximum transparency |
||||
|
||||
The disassembly can be viewed using objdump: |
||||
|
||||
readelf -Wa input.com.dbg # maximum transparency |
||||
objdump -d input.com.dbg # maximum transparency |
||||
objdump -dj.text input.com.dbg # skip αpε boilerplate |
||||
objdump -j.load -dMi8086 input.com.dbg # fixes real mode code |
||||
|
||||
Some commands for controlling the verbosity of binaries: |
||||
|
||||
strip -X input.com.dbg # remove ".L" symbols |
||||
strip input.com.dbg # remove all symbols |
||||
strip -S input.com.dbg # remove debug info only |
||||
make CPPFLAGS=-DNDEBUG # remove asserts (prod) |
||||
make CPPFLAGS=-DIM_FEELING_NAUGHTY # remove legal notices |
||||
|
||||
The Makefile build is also configured to always produce a .map file |
||||
when building each program, which provides further details. |
||||
|
||||
───HACKABILITY────────────────────────────────────────────────────────── |
||||
|
||||
Your linker and assemblies were designed provide extensibility through |
||||
the use of link-time data structures we call "decentralized sections". |
||||
They allow functions like _init() to be comprised of many small pieces |
||||
defined throughout the codebase. The same applies to ELF / PE headers. |
||||
|
||||
Extending that content usually entails writing a .S file. The process |
||||
has more in common with JavaScript programming than contemporary C++ |
||||
development practices. It's the reason Cosmopolitan is able to build |
||||
the fast tiny multiplatform autonomous binaries that indie developers |
||||
love using a scalable development model that big businesses respect. |
||||
|
||||
───SECURITY───────────────────────────────────────────────────────────── |
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is designed to be secure in untrustworthy |
||||
computing environments. Code and data are separated. Data structures |
||||
initialized at startup are automatically memory protected afterwards. |
||||
Code intended for platforms you don't use is automatically unmapped |
||||
too, minimizing any possible chance of impacting your system, while |
||||
still being there in case you ever need it. |
||||
|
||||
───CONFIDENTIALITY────────────────────────────────────────────────────── |
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is also designed to not leak confidential |
||||
information by default. Details relating to the host build environment |
||||
such as system/library versions, user ids, home folder locations, etc. |
||||
are not taken into consideration at build time since it's hermetic. We |
||||
can't make speak for debug information, which is why it's put in other |
||||
files. We also provide the bing and fold programs for auditing binary. |
||||
|
||||
───DESIGN─DETAILS─────────────────────────────────────────────────────── |
||||
|
||||
αcτµαlly pδrταblε εxεcµταblε is a non-reflective (a.k.a. flat) binary |
||||
format that includes ELF, PE, and Macho-O headers only to respect the |
||||
initialization rituals that supported platforms require. |
||||
|
||||
Binaries are sparse because Intel's six thousand page manual says: |
||||
|
||||
“Always put code and data on separate pages. [...] If code is |
||||
to be modified, try to do it all at once and make sure the |
||||
code that performs the modifications and the code being |
||||
modified are on separate 4KByte pages or on separate aligned |
||||
1-KByte subpages. [...] If (hopefully read-only) data must |
||||
occur on the same page as code, avoid placing it immediately |
||||
after an indirect jump [...] or inserting an illegal opcode |
||||
[...] after the indirect branch [which] may degrade perf in |
||||
some circumstances.” ──Intel V.O §3.6.9 |
||||
|
||||
Support for linking dynamic shared objects is only implemented on |
||||
Windows NT for the reasons described by Ulrich Drepper in his DSO |
||||
tutorial. We've implemented this independently of the ld codebase |
||||
because authentic GNU tooling is powerful enough to generalize to |
||||
arbitrary formats without needing to add features to its codebase. |
||||
|
||||
Cosmopolitan core library functions may be converted to the COFF or |
||||
Mach-O object formats using objconv. That gives you some freedom to |
||||
choose to use the Microsoft or Apple linker instead of this one. We |
||||
otherwise can't use those formats, due to how they heavily restrict |
||||
naming, which basically makes everything we're doing impossible. In |
||||
the future an authentic GNU toolchain will be made available on the |
||||
Windows and Apple platforms, using canonical formats and behaviors. |
||||
Until then, we can build for those platforms using Linux or WSL. */ |
||||
|
||||
#ifdef __LINKER__ |
||||
#include "ape/macros.h" |
||||
#include "ape/config.h" |
||||
#include "libc/nt/pedef.h" |
||||
#include "libc/zip.h" |
||||
|
||||
ENTRY(_start) |
||||
|
||||
/* Plans real memory solution at linktime. */ |
||||
MEMORY { |
||||
PageZero : org = 0x0000000000000000, len = 0x0000000000001000 |
||||
RealBss : org = XLM_BASE_REAL, len = XLM_SIZE |
||||
RealProgram : org = IMAGE_BASE_REAL, len = 0x0000000000010000 - IMAGE_BASE_REAL |
||||
RealScratch : org = REAL_SCRATCH_AREA, len = REAL_STACK_FRAME - REAL_SCRATCH_AREA |
||||
RealStack : org = REAL_STACK_FRAME, len = 0x0000000000010000 |
||||
EbdaMemory : org = 0x0000000000080000, len = 0x0000000000020000 |
||||
VideoMemory : org = 0x00000000000a0000, len = 0x0000000000020000 |
||||
Romz : org = 0x00000000000c0000, len = 0x0000000000030000 |
||||
BiosMemory : org = 0x00000000000f0000, len = 0x0000000000010000 |
||||
SmallCode : org = IMAGE_BASE_PHYSICAL, len = 0x0000000040000000 - IMAGE_BASE_PHYSICAL |
||||
ZipData : org = 0x0000000040000000, len = 0x0000000040000000 |
||||
} |
||||
|
||||
PHDRS { |
||||
Head PT_LOAD FLAGS(5); |
||||
Rom PT_LOAD FLAGS(5); |
||||
Ram PT_LOAD FLAGS(6); |
||||
stack PT_GNU_STACK FLAGS(6); |
||||
} |
||||
|
||||
SECTIONS { |
||||
|
||||
/*BEGIN: realmode addressability guarantee */ |
||||
/*BEGIN: xnu addressability guarantee */ |
||||
/*BEGIN: linux addressability guarantee */ |
||||
/*BEGIN: bsd addressability guarantee */ |
||||
|
||||
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : { |
||||
HIDDEN(_base = .); |
||||
|
||||
/* Real Mode */ |
||||
KEEP(*(.head)) |
||||
. += 1; |
||||
|
||||
/* Executable & Linkable Format */ |
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1); |
||||
KEEP(*(.elf.phdrs)) |
||||
HIDDEN(.Lape.phdrs.end = .); |
||||
. += 1; |
||||
|
||||
/* OpenBSD */ |
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1); |
||||
HIDDEN(.Lape.note = .); |
||||
KEEP(*(.note.openbsd.ident)) |
||||
HIDDEN(.Lape.note.end = .); |
||||
. += 1; |
||||
|
||||
/* Portable Executable */ |
||||
KEEP(*(.pe.header)) |
||||
HIDDEN(.Lape.pe.sections = .); |
||||
KEEP(*(.pe.sections)) |
||||
HIDDEN(.Lape.pe.sections_end = .); |
||||
. += 1; |
||||
|
||||
/* Mach-O */ |
||||
KEEP(*(.macho)) |
||||
. = ALIGN(__SIZEOF_POINTER__); |
||||
HIDDEN(.Lape.macho.end = .); |
||||
. += 1; |
||||
|
||||
KEEP(*(.ape.pad.head)) |
||||
. = ALIGN(4096); /* alignments only mandatory when impossible otherwise */ |
||||
HIDDEN(_ehead = .); |
||||
} AT>SmallCode :Head |
||||
|
||||
/*BEGIN: nt addressability guarantee */ |
||||
|
||||
.text . : { |
||||
/* Code that needs to be addressable in Real Mode */ |
||||
*(.text.real) |
||||
KEEP(*(SORT_BY_NAME(.sort.text.real.*))) |
||||
*(.rodata.real) |
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.real.*))) |
||||
HIDDEN(_ereal = .); |
||||
|
||||
/*END: realmode addressability guarantee */ |
||||
|
||||
/* Normal Code */ |
||||
*(.start) |
||||
KEEP(*(.initprologue)) |
||||
KEEP(*(SORT_BY_NAME(.init.*))) |
||||
KEEP(*(SORT_NONE(.init))) |
||||
KEEP(*(.initepilogue)) |
||||
KEEP(*(.pltprologue)) |
||||
*(.plt) |
||||
KEEP(*(.pltepilogue)) |
||||
KEEP(*(.pltgotprologue)) |
||||
*(.plt.got) |
||||
KEEP(*(.pltgotepilogue)) |
||||
*(.text.startup .text.startup.*) |
||||
*(.text.exit .text.exit.*) |
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*) |
||||
*(SORT_BY_ALIGNMENT(.text.antiquity)) |
||||
*(SORT_BY_ALIGNMENT(.text.antiquity.*)) |
||||
KEEP(*(.textwindowsprologue)) |
||||
*(.text.windows) |
||||
KEEP(*(.textwindowsepilogue)) |
||||
*(SORT_BY_ALIGNMENT(.text.modernity)) |
||||
*(SORT_BY_ALIGNMENT(.text.modernity.*)) |
||||
*(SORT_BY_ALIGNMENT(.text.hot)) |
||||
*(SORT_BY_ALIGNMENT(.text.hot.*)) |
||||
KEEP(*(.keep.text)) |
||||
*(.text .stub .text.*) |
||||
KEEP(*(SORT_BY_NAME(.sort.text.*))) |
||||
|
||||
/* Won't support NX bit DRM for tiny executables */ |
||||
HIDDEN(.Lape.piro.align = ABSOLUTE(. > APE_PIRO_THRESHOLD ? 0x1000 : 8)); |
||||
|
||||
/* Code that musn't be mapped in production */ |
||||
KEEP(*(.ape.pad.test)); |
||||
. = ALIGN(.Lape.piro.align); |
||||
HIDDEN(__test_start = .); |
||||
*(.test.unlikely) |
||||
*(.test .test.*) |
||||
|
||||
/* Privileged code invulnerable to magic */ |
||||
KEEP(*(.ape.pad.privileged)); |
||||
. = ALIGN(.Lape.piro.align); |
||||
HIDDEN(__privileged_start = .); |
||||
HIDDEN(__test_end = .); |
||||
. += 1; |
||||
*(.privileged) |
||||
|
||||
/*BEGIN: Read Only Data */ |
||||
|
||||
KEEP(*(.ape.pad.rodata)); |
||||
. = ALIGN(.Lape.piro.align); |
||||
. += 1; |
||||
|
||||
/* Nonspecific Read-Only Data */ |
||||
*(.rodata .rodata.*) |
||||
. += 1; |
||||
|
||||
/* Undefined Behavior Sanitizer Types */ |
||||
HIDDEN(__ubsan_types_start = .); |
||||
*(.ubsan.types) |
||||
HIDDEN(__ubsan_types_end = .); |
||||
. += 1; |
||||
|
||||
/* Undefined Behavior Sanitizer Data */ |
||||
HIDDEN(__ubsan_data_start = .); |
||||
*(.ubsan.data) |
||||
HIDDEN(__ubsan_data_end = .); |
||||
|
||||
/* Unit Test & Fixture Registry */ |
||||
|
||||
/*BEGIN: Read only data that needn't be mapped after initialization */ |
||||
|
||||
/* Legal Notices */ |
||||
KEEP(*(.commentprologue)) |
||||
KEEP(*(.comment)) |
||||
KEEP(*(.commentepilogue)) |
||||
|
||||
/* Windows DLL Import Directory */ |
||||
KEEP(*(.idata.ro)); |
||||
KEEP(*(SORT_BY_NAME(.idata.ro.*))) |
||||
. += 1; |
||||
|
||||
/* Encoded Data Structures w/ Linear Initialization Order */ |
||||
KEEP(*(.initroprologue)) |
||||
KEEP(*(SORT_BY_NAME(.initro.*))) |
||||
KEEP(*(.initroepilogue)) |
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*))) |
||||
|
||||
KEEP(*(.ape.pad.text)) |
||||
HIDDEN(.Lape.data.align = ABSOLUTE(PAGESIZE)); |
||||
. = ALIGN(.Lape.data.align); |
||||
HIDDEN(_etext = .); |
||||
PROVIDE_HIDDEN(etext = .); |
||||
/*END: Read Only Data (only needed for initialization) */ |
||||
/*END: Read Only Data */ |
||||
} AT>SmallCode :Rom |
||||
|
||||
.data . : { |
||||
/*BEGIN: Read/Write Data */ |
||||
KEEP(*(.dataprologue)) |
||||
*(.data .data.*) |
||||
KEEP(*(SORT_BY_NAME(.sort.data.*))) |
||||
. += . > 0 ? 1 : 0; |
||||
|
||||
KEEP(*(.gotprologue)) |
||||
*(.got) |
||||
KEEP(*(.gotepilogue)) |
||||
|
||||
KEEP(*(.gotpltprologue)) |
||||
*(.got.plt) |
||||
KEEP(*(.gotpltepilogue)) |
||||
|
||||
/*BEGIN: Post-Initialization Read-Only */ |
||||
. = ALIGN(.Lape.piro.align); |
||||
HIDDEN(__piro_start = .); |
||||
|
||||
QUAD(IMAGE_BASE_VIRTUAL); |
||||
|
||||
PROVIDE_HIDDEN(__init_array_start = .); |
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) |
||||
SORT_BY_INIT_PRIORITY(.ctors.*))) |
||||
KEEP(*(SORT_NONE(.ctors))) |
||||
KEEP(*(SORT_NONE(.init_array))) |
||||
KEEP(*(SORT_NONE(.preinit_array))) |
||||
PROVIDE_HIDDEN(__init_array_end = .); |
||||
|
||||
. += 1; |
||||
. = ALIGN(__SIZEOF_POINTER__); |
||||
PROVIDE_HIDDEN(__fini_array_start = .); |
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) |
||||
SORT_BY_INIT_PRIORITY(.dtors.*))) |
||||
KEEP(*(SORT_NONE(.dtors))) |
||||
PROVIDE_HIDDEN(__fini_array_end = .); |
||||
|
||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*))) |
||||
PROVIDE_HIDDEN(__relo_end = .); |
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*))) |
||||
KEEP(*(.piro.pad.data)) |
||||
. = ALIGN(.Lape.data.align); |
||||
HIDDEN(_edata = .); |
||||
PROVIDE_HIDDEN(edata = .); |
||||
} AT>SmallCode :Ram |
||||
|
||||
.bss . : { |
||||
KEEP(*(SORT_BY_NAME(.piro.bss.init.*))) |
||||
*(.piro.bss) |
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*))) |
||||
. += 1; |
||||
. = ALIGN(.Lape.piro.align); |
||||
HIDDEN(__piro_end = .); |
||||
/*END: Post-Initialization Read-Only */ |
||||
|
||||
/* Statically Allocated Empty Space */ |
||||
*(SORT_BY_ALIGNMENT(.bss)) |
||||
*(SORT_BY_ALIGNMENT(.bss.*)) |
||||
*(COMMON) |
||||
|
||||
KEEP(*(SORT_BY_NAME(.sort.bss.*))) |
||||
|
||||
/* eXtreme Low Memory w/ Userspace Remapping */ |
||||
. = ALIGN(0x1000); |
||||
*(.xlm) |
||||
. = ALIGN(0x1000); |
||||
|
||||
HIDDEN(_end = .); |
||||
PROVIDE_HIDDEN(end = .); |
||||
} AT>SmallCode :Ram |
||||
|
||||
/*END: nt addressability guarantee */ |
||||
/*END: bsd addressability guarantee */ |
||||
/*END: linux addressability guarantee */ |
||||
/*END: xnu addressability guarantee */ |
||||
|
||||
.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) } |
||||
.comment 0 : { *(.comment) } |
||||
.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) } |
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) } |
||||
.GCC.command.line 0 : { *(.GCC.command.line) } |
||||
|
||||
/DISCARD/ : { |
||||
*(.discard) |
||||
*(.yoink) |
||||
*(.*) |
||||
} |
||||
} |
||||
|
||||
PFSTUB8(.Lape.elf.entry, _start); |
||||
PFSTUB8(.Lape.elf.phoff, RVA(ape.phdrs)); |
||||
PFSTUB8(.Lape.elf.shoff, 0); |
||||
PFSTUB4(.Lape.elf.phnum, (.Lape.phdrs.end - ape.phdrs) / 56); |
||||
PFSTUB4(.Lape.elf.shnum, 0); |
||||
PFSTUB4(.Lape.elf.shstrndx, 0); |
||||
SHSTUB2(.Lape.macho.dd.skip, RVA(ape.macho) / 8); |
||||
SHSTUB2(.Lape.macho.dd.count, (.Lape.macho.end - ape.macho) / 8); |
||||
PFSTUB4(.Lape.pe.offset, ape.pe - ape.mz); |
||||
|
||||
HIDDEN(.Lape.pe.optsz = .Lape.pe.sections - (ape.pe + 24)); |
||||
HIDDEN(.Lape.pe.shnum = (.Lape.pe.sections_end - .Lape.pe.sections) / 40); |
||||
HIDDEN(.Lidata.idtsize = idata.idtend - idata.idt); |
||||
HIDDEN(.Lidata.iatsize = idata.iatend - idata.iat); |
||||
|
||||
HIDDEN(.Lape.rom.offset = 0); |
||||
HIDDEN(.Lape.rom.vaddr = ADDR(.head)); |
||||
HIDDEN(.Lape.rom.paddr = LOADADDR(.head)); |
||||
HIDDEN(.Lape.rom.filesz = LOADADDR(.data) - .Lape.rom.paddr); |
||||
HIDDEN(.Lape.rom.memsz = ADDR(.data) - ADDR(.head)); |
||||
HIDDEN(.Lape.rom.align = 0x1000); |
||||
HIDDEN(.Lape.rom.rva = RVA(.Lape.rom.vaddr)); |
||||
|
||||
HIDDEN(.Lape.ram.offset = .Lape.rom.offset + .Lape.rom.filesz); |
||||
HIDDEN(.Lape.ram.vaddr = ADDR(.data)); |
||||
HIDDEN(.Lape.ram.paddr = LOADADDR(.data)); |
||||
HIDDEN(.Lape.ram.filesz = LOADADDR(.bss) - LOADADDR(.data)); |
||||
HIDDEN(.Lape.ram.memsz = ADDR(.bss) + SIZEOF(.bss) - .Lape.ram.vaddr); |
||||
HIDDEN(.Lape.ram.align = 0x1000); |
||||
HIDDEN(.Lape.ram.rva = RVA(.Lape.ram.vaddr)); |
||||
|
||||
HIDDEN(.Lape.note.offset = .Lape.rom.offset + (.Lape.note - .Lape.rom.vaddr)); |
||||
HIDDEN(.Lape.note.vaddr = .Lape.note); |
||||
HIDDEN(.Lape.note.paddr = .Lape.rom.paddr + .Lape.note.offset); |
||||
HIDDEN(.Lape.note.filesz = .Lape.note.end - .Lape.note); |
||||
HIDDEN(.Lape.note.memsz = .Lape.note.filesz); |
||||
HIDDEN(.Lape.note.align = __SIZEOF_POINTER__); |
||||
|
||||
HIDDEN(.Lape.text.offset = .Lape.rom.offset + LOADADDR(.text) - .Lape.rom.paddr); |
||||
HIDDEN(.Lape.text.paddr = LOADADDR(.text)); |
||||
HIDDEN(.Lape.text.vaddr = ADDR(.text)); |
||||
HIDDEN(.Lape.text.filesz = SIZEOF(.text)); |
||||
HIDDEN(.Lape.text.memsz = SIZEOF(.text)); |
||||
HIDDEN(.Lape.text.align = 4096); |
||||
HIDDEN(.Lape.text.rva = RVA(.Lape.text.vaddr)); |
||||
|
||||
HIDDEN(.Lape.data.offset = .Lape.ram.offset + LOADADDR(.data) - .Lape.ram.paddr); |
||||
HIDDEN(.Lape.data.paddr = LOADADDR(.data)); |
||||
HIDDEN(.Lape.data.vaddr = ADDR(.data)); |
||||
HIDDEN(.Lape.data.filesz = SIZEOF(.data)); |
||||
HIDDEN(.Lape.data.memsz = SIZEOF(.data)); |
||||
HIDDEN(.Lape.data.align = 0x1000); |
||||
HIDDEN(.Lape.data.rva = RVA(.Lape.data.vaddr)); |
||||
|
||||
HIDDEN(.Lape.bss.offset = .Lape.ram.offset + LOADADDR(.bss) - .Lape.ram.paddr); |
||||
HIDDEN(.Lape.bss.paddr = LOADADDR(.bss)); |
||||
HIDDEN(.Lape.bss.vaddr = ADDR(.bss)); |
||||
HIDDEN(.Lape.bss.filesz = 0); |
||||
HIDDEN(.Lape.bss.memsz = SIZEOF(.bss)); |
||||
HIDDEN(.Lape.bss.align = .Lape.data.align); |
||||
|
||||
/* Program Loader Auto-Tune */ |
||||
HIDDEN(v_ape_realsectors = |
||||
MIN(REAL_SCRATCH_AREA - IMAGE_BASE_REAL, |
||||
ROUNDUP(RVA(_edata), 512)) / 512); |
||||
HIDDEN(v_ape_highsectors = |
||||
(ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors); |
||||
|
||||
/* Windows NT Auto-Subsystem Embedding */ |
||||
HIDDEN(v_ntsubsystem = (DEFINED(GetMessage) |
||||
? kNtImageSubsystemWindowsGui |
||||
: kNtImageSubsystemWindowsCui)); |
||||
|
||||
/* 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); |
||||
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize); |
||||
ZIPCONST(v_zip_commentsize, _edata - __zip_end - kZipCdirHdrMinSize); |
||||
|
||||
/* Generates deterministic ID for Mach-O. */ |
||||
#define PHI 0x9e3779b9925d4c17 |
||||
#define XOR(X,Y) ((X | Y) - (X & Y)) |
||||
#define XORSHIFT(X,Y) \ |
||||
X = XOR(X, (Y >> 12)); \ |
||||
X = XOR(X, (Y << 25)); \ |
||||
X = XOR(X, (Y >> 27)) |
||||
#define KMH(X,Y) \ |
||||
X = (X + (Y >> 000) & 0xFF) * PHI; \ |
||||
X = (X + (Y >> 010) & 0xFF) * PHI; \ |
||||
X = (X + (Y >> 020) & 0xFF) * PHI; \ |
||||
X = (X + (Y >> 030) & 0xFF) * PHI |
||||
#define BOOP(X) \ |
||||
XORSHIFT(uuid1_, X); \ |
||||
KMH(uuid1_, X); \ |
||||
XORSHIFT(uuid2_, X); \ |
||||
KMH(uuid2_, X) |
||||
|
||||
HIDDEN(uuid1_ = 88172645463325252); |
||||
HIDDEN(uuid2_ = 88172645463325252); |
||||
|
||||
BOOP(.Lape.bss.align); |
||||
BOOP(.Lape.bss.filesz); |
||||
BOOP(.Lape.bss.memsz); |
||||
BOOP(.Lape.bss.offset); |
||||
BOOP(.Lape.bss.paddr); |
||||
BOOP(.Lape.data.align); |
||||
BOOP(.Lape.data.filesz); |
||||
BOOP(.Lape.data.memsz); |
||||
BOOP(.Lape.data.offset); |
||||
BOOP(.Lape.data.paddr); |
||||
BOOP(.Lape.data.rva); |
||||
BOOP(.Lape.data.vaddr); |
||||
BOOP(.Lape.elf.entry); |
||||
BOOP(.Lape.elf.phnum); |
||||
BOOP(.Lape.elf.phoff); |
||||
BOOP(.Lape.elf.shnum); |
||||
BOOP(.Lape.elf.shoff); |
||||
BOOP(.Lape.elf.shstrndx); |
||||
BOOP(.Lape.macho.end); |
||||
BOOP(.Lape.note); |
||||
BOOP(.Lape.note.align); |
||||
BOOP(.Lape.note.end); |
||||
BOOP(.Lape.note.filesz); |
||||
BOOP(.Lape.note.memsz); |
||||
BOOP(.Lape.note.offset); |
||||
BOOP(.Lape.note.paddr); |
||||
BOOP(.Lape.note.vaddr); |
||||
BOOP(.Lape.pe.offset); |
||||
BOOP(.Lape.pe.optsz); |
||||
BOOP(.Lape.pe.sections); |
||||
BOOP(.Lape.pe.sections_end); |
||||
BOOP(.Lape.pe.shnum); |
||||
BOOP(.Lape.phdrs.end); |
||||
BOOP(.Lape.ram.align); |
||||
BOOP(.Lape.ram.filesz); |
||||
BOOP(.Lape.ram.memsz); |
||||
BOOP(.Lape.ram.offset); |
||||
BOOP(.Lape.ram.paddr); |
||||
BOOP(.Lape.ram.rva); |
||||
BOOP(.Lape.ram.vaddr); |
||||
BOOP(.Lape.rom.align); |
||||
BOOP(.Lape.rom.filesz); |
||||
BOOP(.Lape.rom.memsz); |
||||
BOOP(.Lape.rom.offset); |
||||
BOOP(.Lape.rom.paddr); |
||||
BOOP(.Lape.rom.rva); |
||||
BOOP(.Lape.rom.vaddr); |
||||
BOOP(.Lape.text.align); |
||||
BOOP(.Lape.text.filesz); |
||||
BOOP(.Lape.text.memsz); |
||||
BOOP(.Lape.text.offset); |
||||
BOOP(.Lape.text.paddr); |
||||
BOOP(.Lape.text.rva); |
||||
BOOP(.Lape.text.vaddr); |
||||
BOOP(ADDR(.bss)); |
||||
BOOP(WinMain); |
||||
BOOP(_start); |
||||
BOOP(ape.macho); |
||||
BOOP(ape.mz); |
||||
BOOP(ape.pe); |
||||
BOOP(ape.phdrs); |
||||
BOOP(v_ape_realsectors); |
||||
|
||||
ASSERT(ape.mz == IMAGE_BASE_VIRTUAL, "linker panic"); |
||||
ASSERT((DEFINED(__init_bss_end) ? __init_bss_end : 0) % __SIZEOF_POINTER__ == 0, |
||||
"__init_bss misalign"); |
||||
ASSERT(((DEFINED(__init_rodata_end) ? __init_rodata_end : 0) % |
||||
__SIZEOF_POINTER__ == 0), |
||||
"__init_rodata misalign"); |
||||
|
||||
ASSERT((!DEFINED(ape.grub) ? 1 : RVA(ape.grub) < 8192), |
||||
"grub stub needs to be in first 8kb of image"); |
||||
|
||||
ASSERT(DEFINED(_start) || DEFINED(_start16), |
||||
"please link a _start() or _start16() entrypoint"); |
||||
|
||||
ASSERT(!DEFINED(_start16) || REAL(_end) < 65536, |
||||
"ape won't support non-tiny real mode programs"); |
||||
|
||||
/* Let's not be like Knight Capital. */ |
||||
/* NOCROSSREFS_TO(.test .text) */ |
||||
|
||||
/* ASSERT(ape_sysv_start == .Lape.text.vaddr, */ |
||||
/* "ape_sysv_start() must be first in .text"); */ |
||||
|
||||
#endif /* __LINKER__ */ |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# αcτµαlly pδrταblε εxεcµταblε
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This file defines the libraries, runtimes, and build rules needed to
|
||||
# create executables from your Linux workstation that'll run anywhere.
|
||||
# Loading this package will make certain systemic modifications to the
|
||||
# build like turning off the System V "Red Zone" optimization, because
|
||||
# αcτµαlly pδrταblε εxεcµταblεs need to be able to run in kernelspace.
|
||||
|
||||
PKGS += APE |
||||
|
||||
DEFAULT_COPTS += -mno-red-zone |
||||
DEFAULT_LDFLAGS += -z max-page-size=0x1000 |
||||
|
||||
APELINK = ACTION=LINK.ape $(LINK) $(LINKARGS) $(OUTPUT_OPTION) && $(STRIP) -X $@ && $(GZ) $(ZFLAGS) -f $@.map |
||||
|
||||
APE = $(APE_DEPS) \
|
||||
$(APE_OBJS) \
|
||||
o/$(MODE)/ape/ape.lds |
||||
|
||||
APE_FILES := \
|
||||
$(wildcard ape/*.*) |
||||
|
||||
APE_HDRS = \
|
||||
$(filter %.h,$(APE_FILES)) |
||||
|
||||
APE_SRCS = \
|
||||
$(filter %.S,$(APE_FILES)) |
||||
|
||||
APE_OBJS = \
|
||||
$(APE_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(APE_SRCS:%.S=o/$(MODE)/%.o) |
||||
|
||||
APE_DEPS = \
|
||||
$(APE_LIB) |
||||
|
||||
APE_CHECKS = \
|
||||
$(APE_HDRS:%=o/%.ok) |
||||
|
||||
o/%.com: o/%.com.dbg |
||||
@ACTION=OBJCOPY.ape TARGET=$@ build/do $(OBJCOPY) -SO binary $< $@ |
||||
|
||||
o/ape/idata.inc: ape/idata.h ape/relocations.h |
||||
|
||||
$(APE_OBJS): $(BUILD_FILES) \ |
||||
ape/ape.mk |
||||
|
||||
.PHONY: o/$(MODE)/ape |
||||
o/$(MODE)/ape: $(APE) \ |
||||
$(APE_CHECKS) \
|
||||
o/$(MODE)/ape/lib |
@ -0,0 +1,137 @@
@@ -0,0 +1,137 @@
|
||||
#ifndef APE_CONFIG_H_ |
||||
#define APE_CONFIG_H_ |
||||
#include "ape/relocations.h" |
||||
#include "libc/macros.h" |
||||
|
||||
/**
|
||||
* @fileverview αcτµαlly pδrταblε εxεcµταblε configuration. |
||||
*/ |
||||
|
||||
/**
|
||||
* Post-Initialization Read-Only Code Size Threshold. |
||||
* |
||||
* An executable needs to have at least this much code, before the |
||||
* linker adds non-mandatory 4kb alignments. The benefit is better |
||||
* memory protection. The tradeoff is sparser binaries. |
||||
*/ |
||||
#ifndef APE_PIRO_THRESHOLD |
||||
#ifdef CONFIG_DBG |
||||
#define APE_PIRO_THRESHOLD 0x1000 |
||||
#else |
||||
#define APE_PIRO_THRESHOLD 0x10000 |
||||
#endif |
||||
#endif |
||||
|
||||
/**
|
||||
* PC Standard I/O Configuration. |
||||
*/ |
||||
#ifndef METAL_STDIN |
||||
#define METAL_STDIN COM1 |
||||
#endif |
||||
#ifndef METAL_STDOUT |
||||
#define METAL_STDOUT COM1 |
||||
#endif |
||||
#ifndef METAL_STDERR |
||||
#define METAL_STDERR COM2 /* will fallback to stdout if COM2 not present */ |
||||
#endif |
||||
|
||||
/**
|
||||
* PC Display Configuration (MDA/CGA) |
||||
* @see www.lammertbies.nl/comm/info/serial-uart.html |
||||
* @see ape/lib/vidya.h |
||||
*/ |
||||
#ifndef VIDYA_MODE |
||||
#define VIDYA_MODE VIDYA_MODE_MDA |
||||
#endif |
||||
|
||||
/* FPU Control Word (x87) Exception Masks
|
||||
@see Intel Manual V1 §8.1.5 |
||||
|
||||
IM: Invalid Operation ───────────────┐ |
||||
DM: Denormal Operand ───────────────┐│ |
||||
ZM: Zero Divide ───────────────────┐││ |
||||
OM: Overflow ─────────────────────┐│││ |
||||
UM: Underflow ───────────────────┐││││ |
||||
PM: Precision ──────────────────┐│││││ |
||||
PC: Precision Control ────────┐ ││││││ |
||||
{float,∅,double,long double} │ ││││││ |
||||
RC: Rounding Control ───────┐ │ ││││││ |
||||
{even, →-∞, →+∞, →0} │┌┤ ││││││ |
||||
┌┤││ ││││││ |
||||
d││││rr││││││*/ |
||||
#define X87_NORMAL 0b000000000001101111111 |
||||
#define X87_DTOA 0b000000000001000000000 |
||||
#define X87_DTOA_MASK 0b000000000001100000000 |
||||
#ifndef X87_DEFAULT |
||||
#define X87_DEFAULT X87_NORMAL |
||||
#endif |
||||
|
||||
/**
|
||||
* Serial Line Configuration (8250 UART 16550) |
||||
* @see ape/lib/uart.h |
||||
*/ |
||||
#ifndef UART_BAUD_RATE |
||||
#define UART_BAUD_RATE 9600 /* bits per second ∈ [50,115200] */ |
||||
#endif |
||||
#define UART_CONF_DLR (1843200 /*hz*/ / 16 /*wut*/ / (UART_BAUD_RATE)) |
||||
#ifndef UART_CONF_IIR |
||||
/* ┌interrupt trigger level {1,4,8,14}
|
||||
│ ┌enable 64 byte fifo (UART 16750+) |
||||
│ │ ┌select dma mode |
||||
│ │ │┌clear transmit fifo |
||||
│ │ ││┌clear receive fifo |
||||
├┐│ │││┌enable fifos*/ |
||||
#define UART_CONF_IIR 0b00000000 |
||||
#endif |
||||
#ifndef UART_CONF_LCR |
||||
/* ┌dlab: flips configuration mode state
|
||||
│┌enable break signal |
||||
││ ┌parity {none,odd,even,high,low} |
||||
││ │ ┌extra stop bit |
||||
││ │ │┌data word length (bits+5) |
||||
││┌┴┐│├┐*/ |
||||
#define UART_CONF_LCR 0b01000011 |
||||
#endif |
||||
|
||||
/**
|
||||
* eXtreme Low Memory. |
||||
*/ |
||||
#define XLM(VAR) (XLM_BASE_REAL + XLM_##VAR) |
||||
#define XLMV(VAR) (__xlm + XLM_##VAR) |
||||
#define XLM_BASE_REAL 0x1000 |
||||
#define XLM_E820 0 |
||||
#define XLM_E820_SIZE 0x2000 |
||||
#define XLM_BIOS_DATA_AREA 0x2000 |
||||
#define XLM_BIOS_DATA_AREA_SIZE 256 |
||||
#define XLM_DRIVE_BASE_TABLE 0x2200 /* drive values are contiguous */ |
||||
#define XLM_DRIVE_BASE_TABLE_SIZE 11 |
||||
#define XLM_DRIVE_TYPE 0x220b |
||||
#define XLM_DRIVE_TYPE_SIZE 1 |
||||
#define XLM_DRIVE_LAST_SECTOR 0x220c /* 1-based inclusive, e.g. 18 */ |
||||
#define XLM_DRIVE_LAST_SECTOR_SIZE 1 |
||||
#define XLM_DRIVE_LAST_CYLINDER 0x220d /* 0-based incl, e.g. 79 */ |
||||
#define XLM_DRIVE_LAST_CYLINDER_SIZE 2 |
||||
#define XLM_DRIVE_ATTACHED 0x220f |
||||
#define XLM_DRIVE_ATTACHED_SIZE 1 |
||||
#define XLM_DRIVE_LAST_HEAD 0x2210 /* 0-based inclusive, e.g. 1 */ |
||||
#define XLM_DRIVE_LAST_HEAD_SIZE 1 |
||||
#define XLM_DRIVE 0x2211 |
||||
#define XLM_DRIVE_SIZE 1 |
||||
#define XLM_HAVEEXTMEMKB 0x2212 |
||||
#define XLM_HAVEEXTMEMKB_SIZE 4 |
||||
#define XLM_VIDEO_POSITION_FAR_POINTER 0x2216 /* video cursor far pointer */ |
||||
#define XLM_VIDEO_POSITION_FAR_POINTER_SIZE 4 |
||||
#define XLM_PAGE_TABLE_STACK_POINTER 0x2220 |
||||
#define XLM_PAGE_TABLE_STACK_POINTER_SIZE 8 |
||||
# |