Compare commits

...
102 Commits
Author SHA1 Message Date
Justine Tunney 69faf1b403 Release Cosmpolitan v3.1 2023-11-18 20:40:35 -08:00
Justine Tunney e4dea37b8e Make clock_nanosleep() cancel faster 2023-11-18 18:12:09 -08:00
Justine Tunney 0c89516ac5 Fix unzip warning with apelink generated symtabs 2023-11-18 17:15:22 -08:00
Justine Tunney 3e6d536822 Correct misunderstanding with zip64 extra records 2023-11-18 14:35:57 -08:00
Justine Tunney dbd8176ea8 Add CPU_COUNT_S() 2023-11-18 12:38:30 -08:00
Justine Tunney 545a8f4cb0 Add more sched.h content 2023-11-18 08:08:15 -08:00
Justine Tunney f7cfe03888 Fix dlopen() for FreeBSD and NetBSD 2023-11-18 04:35:48 -08:00
Justine Tunney 2c1efd3d78 Fix Python build break 2023-11-18 02:32:01 -08:00
Matheus Moreira 3ac473df3b Floating point parsing support for scanf family (#924) 2023-11-18 02:25:36 -08:00
Justine Tunney 8caf1b48a9 Improve time/sleep accuracy on Windows
It's now almost as good as Linux thanks to a Windows 8+ API.
2023-11-18 01:57:44 -08:00
Justine Tunney 72ac5f18d9 Fix dash compatible syntax issue 2023-11-17 16:47:47 -08:00
Justine Tunney 2c9d2943d6 Introduce AddDllDirectory() 2023-11-17 10:35:34 -08:00
Justine Tunney 32b97f2d25 Improve execve() path argument munging
Munging of paths passed inside the system() interpreter command is no
longer supported. You have to pass your paths to posix_spawn() or the
execve() family of functions if you want them to be munged. The first
three characters must match `^/[a-z]/` in which case, it'll be turned
into a DOS-style drive path with backslashes.
2023-11-17 09:59:03 -08:00
Justine Tunney 529cb4817c Improve dlopen() on Apple Silicon
- Introduce MAP_JIT which is zero on other platforms
- Invent __jit_begin() and __jit_end() which wrap Apple's APIs
- Runtime dispatch to sys_icache_invalidate() in __clear_cache()
2023-11-17 02:33:14 -08:00
Justine Tunney 7a9e176ecf Improve debug binary location detection 2023-11-17 00:07:39 -08:00
Justine Tunney 68c7c9c1e0 Clean up some code
- Use good ELF technique in cosmo_dlopen()
- Make strerror() conform more to other libc impls
- Introduce __clear_cache() and use it in cosmo_dlopen()
- Remove libc/fmt/fmt.h header (trying to kill off LIBC_FMT)
2023-11-16 17:31:07 -08:00
tkchia 7010a8081e Fix regression when building deathstar.com for aarch64 (#957)
It turns out my earlier commit ddc08dc974 caused a build with
MODE=aarch64 to fail.  The commit changed deathstar.c to link
in code to support a VGA console, but this is not implemented
yet for AArch64.  Thanks to @ahgamut for spotting this issue.
2023-11-16 12:13:17 -08:00
tkchia 665747a319 Make test/libc/calls/pledge_test.c work with "nonstandard" umask (#956)
The test was failing if the process's umask happened to be
0077, for example.  The file `foo` was then created with a
file mode of 0100600, rather than the expected 0100644.
2023-11-16 00:47:21 -08:00
Justine Tunney e05933c641 Mention zsh and fish in readme 2023-11-15 23:25:47 -08:00
Justine Tunney 8f5e516b39 Remove sync_file_range()
After hearing horror stories from a trusted colleague, I don't think
this is the kind of API we want to be supporting. Also SQLite wisdom
regarding fdatasync() has been added to the documentation.
2023-11-15 23:21:22 -08:00
Justine Tunney 8318d67503 Fix regression in cosmocc toolchain 2023-11-15 21:41:53 -08:00
Justine Tunney 1351d3cede Remove bool from public headers 2023-11-15 20:58:46 -08:00
Justine Tunney dffee606cf Run host compiler to create dlopen helper 2023-11-15 20:58:46 -08:00
tkchia ddc08dc974 [metal] Make deathstar.com draw onto both VGA and serial consoles (#955)
In addition, deathstar.com can now be booted up via UEFI.
2023-11-15 19:40:54 -08:00
Justine Tunney e4584ace81 Get cosmo_dlopen() working better on System Five
Imported functions are now aspected with a trampoline that blocks
signals and changes the thread-local storage register. This means
bigger more complicated libraries can now be imported even though
the whole technique remains fundamentally unsafe.
2023-11-15 10:56:30 -08:00
Justine Tunney 3a470ed356 Remove some exploratory some tests
These were reported as failing on some Apple Arm64 systems.
2023-11-14 21:21:22 -08:00
Justine Tunney 9f9aec013a Do better job documenting platform issues 2023-11-14 18:15:58 -08:00
tkchia eea601f346 [metal] Some minor fixes and tweaks (#933)
* [metal] Ensure DF is clear when calling C from exception handler
* [metal] Mark some internal routines and declarations as `@internal`
* [metal] Fix crash under UEFI when command line string is NULL
* [metal] Fix argc & argv[] setting, & VM page freeing, for UEFI

Part of the memory occupied by the argv[] contents was
erroneously used for page tables & then later erroneously
freed.  The symptom was that argv[0] would show up as an
empty string ("").
2023-11-14 15:26:59 -08:00
Justine Tunney 1c2e7c1333 Introduce SIP_DISABLED compile option for ape-m1.c
Systems that don't use SIP can now build APE Loader with this flag to
get a performance speedup.
2023-11-13 22:04:05 -08:00
Justine Tunney 0283f2772c Fix build in MODE=dbg 2023-11-13 15:13:45 -08:00
Justine Tunney 751d20d98d Fix nsync_mu_unlock_slow_() on Apple Silicon
We torture test dlmalloc() in test/libc/stdio/memory_test.c. That test
was crashing on occasion on Apple M1 microprocessors when dlmalloc was
using *NSYNC locks. It was relatively easy to spot the cause, which is
this one particular compare and swap operation, which needed to change
to use sequentially-consistent ordering rather than an acquire barrier
2023-11-13 11:07:13 -08:00
Justine Tunney 3b15d31247 Fix #include <shared_mutex> 2023-11-13 08:30:17 -08:00
Justine Tunney f047172bd3 Fix uname assignment in Makefile 2023-11-13 05:53:10 -08:00
mattx 5d5b282d12 Inform user when wsl2 interop causes build issues (#952) 2023-11-13 05:29:25 -08:00
Justine Tunney 25a892d6ae Add some platform notes to the README file 2023-11-13 02:26:34 -08:00
Justine Tunney d1e764b3cf Modernize README.md 2023-11-12 22:04:07 -08:00
Paul Kulchenko 5c1fdc9819 Fix session changeset procesing (reverting some of 0d748ad5 changes) (#949)
This removes strdup from Lua SQLite wrapper, as it's applied to binary changeset
strings, thus cutting them short (because of strlen).
2023-11-12 14:25:50 -08:00
Justine Tunney f25beb341c Add architecture flag to zipobj 2023-11-12 09:35:59 -08:00
Justine Tunney bed77186c3 Use simple locks in dlmalloc 2023-11-12 09:00:49 -08:00
Justine Tunney bcf268adf8 Don't modify argument block on MacOS Arm64
Some dynamic library had access to this information somehow and was
crashing when it didn't have the expected structure.
2023-11-12 05:59:03 -08:00
Justine Tunney 0863427b3a Make development more pleasant on MacOS Arm64 2023-11-12 05:42:17 -08:00
Justine Tunney f7cad70da1 Introduce posix tests package 2023-11-12 05:41:48 -08:00
Justine Tunney 48bd3d85df Fix sigaction() return handler address on XNU/BSD 2023-11-12 05:40:06 -08:00
Justine Tunney bd56a9cf51 Rename dlopen() to cosmo_dlopen() 2023-11-12 01:19:04 -08:00
Justine Tunney c6d3802d3a Add more fixes for new cosmocc toolchain
We now have an `#include <cxxabi.h>` header which defines all the APIs
Cosmopolitan's implemented so far. The `cosmocc` README.md file is now
greatly expanded with documentation.
2023-11-11 23:28:19 -08:00
Gautham 95124cacbe Fixes for building superconfigure (#948) 2023-11-11 22:11:11 -08:00
Justine Tunney b320321319 Add build/bootstrap/rollup.com 2023-11-11 19:58:45 -08:00
Justine Tunney 291103ad8d Redesign cosmocc toolchain
The `cosmocc` compiler is now being distributed as a self-contained
toolchain that's path-agnostic and it no longer requires you clone the
Cosmop repo to use it. The bin/ folder has been deleted from the mono
repo. The `fatcosmocc` command has been renamed to `cosmocc`. MacOS
support now works very well.
2023-11-11 14:18:08 -08:00
Justine Tunney 3802428026 Fix missing .ok file make warning 2023-11-11 02:32:22 -08:00
Justine Tunney d0ad2694ed Iterate more on recent changes 2023-11-11 00:28:22 -08:00
Paul Kulchenko 7138399f96 Close Lua state before exiting redbean worker to allow GC to collect (#941) 2023-11-10 18:37:00 -08:00
Justine Tunney cdbd10c9d0 Introduce X86_CHECK() macro 2023-11-10 15:41:55 -08:00
Justine Tunney afbef6c361 Freshen build/bootstrap/mkdeps.com 2023-11-10 12:39:52 -08:00
Justine Tunney 3d3cdcf276 Fix APE uname direction
Fixes #942
2023-11-10 12:34:25 -08:00
Justine Tunney d2f49ca175 Improve mkdeps
Our makefile generator now accepts badly formatted include lines. It's
now more hermetic with better error checking in the cosmo repo, and it
can be configured to not be hermetic at all.
2023-11-10 04:14:27 -08:00
Justine Tunney 241f949540 Use dynamic memory for *NSYNC waiters 2023-11-10 01:42:06 -08:00
Justine Tunney 15af5c2d7e Fix ucontext_t alignment in strict ansi mode
Using `cosmocc -std=c11` was causing `ucontext_t` to become misaligned.
This change also adds the GNU constants on x86_64 for accessing general
registers, so you will not need `#ifdef`s to support both Cosmo and GNU
2023-11-09 12:48:29 -08:00
Justine Tunney b8d1377ae1 Give new wait4() another review pass 2023-11-09 11:23:30 -08:00
Justine Tunney ea28f93a26 Support <isystem> includes in monorepo 2023-11-08 19:14:56 -08:00
Justine Tunney 5330442d85 Avoid APE fork bomb
This change addresses a $PATH resolution issue where APE depends on
uname and uname is an APE program. So sorry to anyone this impacted
we'll get a release out soon.
2023-11-08 11:37:42 -08:00
mataha cc3e3de044 Make args replace ... only at the end of file (#909)
So that the string '...' can be used verbatim elsewhere in the file.
2023-11-08 10:00:52 -08:00
Justine Tunney ac125d3e1f Fix console copy/paste issue
Fixes #936
2023-11-08 09:29:45 -08:00
Justine Tunney 956e68be59 Revert "Use %gs as TLS register when dlopen() is linked"
This reverts commit d71da7fc72.
2023-11-08 01:33:01 -08:00
Justine Tunney d71da7fc72 Use %gs as TLS register when dlopen() is linked
Fixes #938
2023-11-08 01:11:17 -08:00
Justine Tunney e961385e55 Put more thought into i/o polyfills
wait4() is now solid enough to run `make -j100` on Windows. You can now
use MSG_DONTWAIT on Windows. There was a handle leak in accept() that's
been fixed. Our WIN32 overlapped i/o code has been simplified. Priority
class now inherits into subprocesses, so the verynice command will work
and the signal mask will now be inherited by execve() and posix_spawn()
2023-11-07 18:32:35 -08:00
Justine Tunney 736fdb757a Implement raise() with getcontext() / setcontext() 2023-11-05 18:04:36 -08:00
Justine Tunney dd83db9567 Improve makefile for uname 2023-11-05 16:21:09 -08:00
Justine Tunney 23d812f116 Release Cosmopolitan v3.0.2
It's recommended that all users, especially Apple Arm, re-run:

    ape/apeinstall.sh

Within the Cosmopolitan monorepo to refresh your APE loader.
2023-11-05 15:54:47 -08:00
Justine Tunney c39eb244d4 Disable an mprotect() test for now due to SIP 2023-11-05 15:38:16 -08:00
Justine Tunney f63c4d4f52 Use /usr/local/bin/ape on Apple Silicon 2023-11-05 14:52:27 -08:00
Paul Kulchenko b893479417 Add database and statement readonly checks to sqlite in redbean (#914) 2023-11-05 13:29:09 -08:00
Justine Tunney d02cba2451 Mint APE Loader v1.9 2023-11-05 13:11:34 -08:00
Justine Tunney 4cf987ddb1 Fix usleep() definition 2023-11-05 13:06:15 -08:00
Justine Tunney 20c794a353 Add strace to aarch64 vfork() 2023-11-05 13:06:15 -08:00
Gregory Haerr 4f100d2aad Fix stack alignment and auxv for macho APE loader (#931) 2023-11-05 13:06:10 -08:00
Justine Tunney a12ad17291 Get APE Loader working on MacOS with SIP enabled 2023-11-05 01:36:47 -08:00
Justine Tunney 653c7b2f87 Fatten build/bootstrap/echo.com 2023-11-04 21:01:43 -07:00
Justine Tunney d7917ea076 Make win32 i/o signals atomic and longjmp() safe 2023-11-04 20:33:29 -07:00
Justine Tunney 585c86e2a4 Support \n in /zip/.args files 2023-11-04 07:25:20 -07:00
Justine Tunney 48e260e653 Introduce NO_ADDRESS constant 2023-11-03 13:56:17 -07:00
Justine Tunney aa106c9356 Fix Lua test suite regression 2023-11-03 07:01:46 -07:00
Justine Tunney 5e8c928f1a Introduce dlopen() support
Every program built using Cosmopolitan is statically-linked. However
there are some cases, e.g. GUIs and video drivers, where linking the
host platform libraries is desirable. So what we do in such cases is
launch a stub executable using the host platform's libc, and longjmp
back into this executable. The stub executable passes back to us the
platform-specific dlopen() implementation, which we shall then wrap.

Here's the list of platforms that are supported so far:

- x86-64 Linux w/ Glibc
- x86-64 Linux w/ Musl Libc
- x86-64 FreeBSD
- x86-64 Windows
- aarch64 Linux w/ Glibc
- aarch64 MacOS

What this means is your Cosmo programs can call foreign functions on
your host operating system. However, it's important to note that any
foreign library you link won't have the ability to call functions in
your Cosmopolitan program. For example it's now technically possible
that Lua can load a module, however that almost certainly won't work
since the Lua module won't have access to Cosmo's Lua API.

Kudos to @jacereda for figuring out how to do this.
2023-11-03 06:37:18 -07:00
Justine Tunney 1eb6484c9c Rewrite getcwd()
This change addresses a bug that was reported in #923 where bash on
Windows behaved strangely. It turned out that our weak linking of
malloc() caused bash's configure script to favor its own getcwd()
function, which is implemented in the most astonishing way, using
opendir() and readdir() to recursively construct the current path.

This change moves getcwd() into LIBC_STDIO so it can strongly link
malloc(). A new __getcwd() function is now introduced, so all the
low-level runtime services can still use the actual system call. It
provides the Linux Kernel API convention across platforms, and is
overall a higher-quality implementation than what we had before.

In the future, we should probably take a closer look into why bash's
getcwd() polyfill wasn't working as intended on Windows, since there
might be a potential opportunity there to improve our readdir() too.
2023-11-02 13:16:42 -07:00
Justine Tunney a46ec61787 Make cosmocc -dumpmachine work correctly 2023-11-02 09:52:25 -07:00
Justine Tunney 024be3b009 Introduce getifaddrs()
This function was invented by the BSDs (it's not in POSIX.1). It
provides a high-level interface into ioctl(SIOCGIFCONF) which is
comparatively clumsy to use. We already made the ioctls portable
across our entire support vector back in 2021, so this interface
is portable too. See o//tool/viz/getifaddrs.com for our demo app
2023-11-02 08:33:03 -07:00
Justine Tunney 6ca5ab4680 Mention cosmocc-0.0.16 in Makefile 2023-11-01 12:08:50 -07:00
Justine Tunney 55d5d6bbc0 Release Cosmopolitan v3.0.1 2023-11-01 09:23:43 -07:00
Justine Tunney d259e573b6 Remove *NSYNC WIN32 semaphores
This implementation doesn't work as well as WIN32 futexes. This code
path was only added back when we were having issues with set context
however that's been solved so we can go back to the much better code
2023-11-01 07:18:58 -07:00
Justine Tunney 7b284f6bda Fix bugs and regressions in the pledge command
This change gets the pledge (formerly pledge.com) command back in tip
top shape for a 3.0.1 cosmos release. It now runs on all platforms, even
though it's mostly a no-op on ones that lack the kernel security stuff.
The binary footprint is now smaller, since it no longer needs to link
malloc. It's also now able to be built as a fat binary.
2023-11-01 06:08:58 -07:00
Justine Tunney b0e3d89942 Work around qemu-aarch64 bug
Qemu appears to define O_LARGEFILE as having its x86-64 value, which is
an easy mistake to make since this is one of the few magic numbers that
Linux special-cases for AARCH64.
2023-11-01 00:24:48 -07:00
Justine Tunney 0b1acce680 Introduce shm_open() and shm_unlink() 2023-10-31 23:57:52 -07:00
Justine Tunney fadb64a2bf Introduce pthread_rwlock_try{rd,wr}lock
This also changes recursive mutexes to favor cpu over scheduler yield.
2023-10-31 22:13:08 -07:00
Justine Tunney a1e1e821cb Introduce GNU/BSD timeval macros 2023-10-31 21:58:49 -07:00
Justine Tunney 2af7c802b6 Stub out getutline and pututline 2023-10-31 21:58:39 -07:00
Justine Tunney 3b791d2f44 Introduce lgammal, tgammal, erfl, and erfcl
git://git.musl-libc.org/musl
79bdacff83a6bd5b70ff5ae5eb8b6de82c2f7c30
2023-10-31 21:58:29 -07:00
Justine Tunney b4084dd6c6 Introduce libcxx <shared_mutex>
[email protected]:llvm-mirror/libcxx.git
78d6a7767ed57b50122a161b91f59f19c9bd0d19
2023-10-31 21:57:28 -07:00
Justine Tunney ee82f90bba Introduce __cxa_thread_atexit() 2023-10-31 20:04:31 -07:00
Justine Tunney a699cda5c8 Make cosmocc -Wl,--version do the right thing
Our `cosmocc` wrapper script will now report the linker version, the
same way as the `cc` command. The `fatcosmocc` command won't do this
because we wouldn't want programs to parse out the path of the amd64
linker command and use it explicitly.

Fixes #917
2023-10-31 18:20:28 -07:00
Justine Tunney f86ffa1a25 Fix aarch64 build breakage caused by ed17d3008 2023-10-31 18:17:32 -07:00
Justine Tunney a09f62141d Fix bug in login_tty() 2023-10-31 18:03:13 -07:00
tkchia ed17d3008b [metal] Add a uprintf() routine, for non-emergency boot logging (#905)
* [metal] Add a uprintf() routine, for non-emergency boot logging
* [metal] _Really_ push forward timing of VGA TTY initialization
* [metal] Do something useful with uprintf()
* [metal] Locate some ACPI tables, for later hardware detection

Specifically the code now tries to find the ACPI RSDP,
RSDT/XSDT, FADT, & MADT tables, whether in legacy BIOS
bootup mode or in a UEFI bootup.  These are useful for
figuring out how to (re)enable asynchronous interrupts
in legacy 8259 PIC mode.
2023-10-25 14:32:20 -07:00
Justine Tunney 062b2d776e Mention cosmocc v0.0.14 in Makefile
https://justine.lol/cosmocc-0.0.14.zip
https://github.com/ahgamut/superconfigure/releases/tag/z0.0.14
2023-10-16 00:07:33 -07:00
742 changed files with 13124 additions and 5927 deletions

No files matched your search

+53 -18
View File
@@ -73,8 +73,16 @@ MODE := $(m)
endif
endif
UNAME_M = $(shell uname -m)
UNAME_S = $(shell uname -s)
# detect wsl2 running cosmopolitan binaries on the host by checking whether:
# - user ran build/bootstrap/make.com, in which case make's working directory is in wsl
# - user ran make, in which case cocmd.com's working directory is in wsl
ifneq ($(findstring //wsl.localhost/,$(CURDIR) $(shell pwd)),)
$(warning wsl2 interop is enabled)
$(error you need to run sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop')
endif
UNAME_M := $(shell uname -m)
UNAME_S := $(shell uname -s)
# apple still distributes a 17 year old version of gnu make
ifeq ($(MAKE_VERSION), 3.81)
@@ -85,7 +93,7 @@ endif
ifeq ($(TOOLCHAIN),) # if TOOLCHAIN isn't defined
ifeq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","") # if our gcc isn't unbundled
ifneq ($(UNAME_M)-$(UNAME_S), x86_64-Linux) # if this is not amd64 linux
$(error you need to download https://justine.lol/cosmocc-0.0.12.zip and unzip it inside the cosmo directory)
$(error you need to download https://cosmo.zip/pub/cosmocc/cosmocc-0.0.18.zip and unzip it inside the cosmo directory)
endif
endif
endif
@@ -170,19 +178,22 @@ include third_party/puff/puff.mk # │
include libc/elf/elf.mk # │
include ape/ape.mk # │
include libc/fmt/fmt.mk # │
include libc/vga/vga.mk #─┘
include libc/vga/vga.mk # │
include libc/irq/irq.mk #─┘
include libc/calls/calls.mk #─┐
include third_party/nsync/nsync.mk # │
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
include third_party/double-conversion/dc.mk # │ You can issue system calls
include libc/irq/irq.mk # ├──SYSTEMS RUNTIME
include third_party/nsync/nsync.mk # │ You can issue system calls
include libc/runtime/runtime.mk # │
include third_party/double-conversion/dc.mk # │
include libc/crt/crt.mk # │
include third_party/dlmalloc/dlmalloc.mk #─┘
include libc/mem/mem.mk #─┐
include third_party/gdtoa/gdtoa.mk # ├──DYNAMIC RUNTIME
include third_party/nsync/mem/mem.mk # │ You can now use stdio
include libc/proc/proc.mk # │ You can now use threads
include libc/thread/thread.mk # │ You can now use processes
include tool/hello/hello.mk # │ You can finally call malloc()
include libc/dlopen/dlopen.mk # │ You can now use processes
include libc/thread/thread.mk # │ You can finally call malloc()
include tool/hello/hello.mk # │
include third_party/zlib/zlib.mk # │
include libc/stdio/stdio.mk # │
include libc/time/time.mk # │
@@ -218,6 +229,7 @@ include third_party/nsync/testing/testing.mk
include libc/testlib/testlib.mk
include tool/viz/lib/vizlib.mk
include tool/args/args.mk
include test/posix/test.mk
include test/tool/args/test.mk
include third_party/linenoise/linenoise.mk
include third_party/maxmind/maxmind.mk
@@ -326,7 +338,7 @@ o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x)))) $(INCS) $(INCS)
$(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 $@ -s -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)))
@@ -371,9 +383,11 @@ COSMOPOLITAN_OBJECTS = \
THIRD_PARTY_NSYNC_MEM \
LIBC_MEM \
THIRD_PARTY_DLMALLOC \
LIBC_DLOPEN \
LIBC_RUNTIME \
THIRD_PARTY_NSYNC \
LIBC_ELF \
LIBC_IRQ \
LIBC_CALLS \
LIBC_SYSV_CALLS \
LIBC_VGA \
@@ -398,13 +412,14 @@ COSMOPOLITAN_OBJECTS = \
LIBC_NT_KERNEL32 \
LIBC_NEXGEN32E
COSMOPOLITAN_HEADERS = \
COSMOPOLITAN_H_PKGS = \
APE \
LIBC \
LIBC_CALLS \
LIBC_DNS \
LIBC_ELF \
LIBC_FMT \
LIBC_DLOPEN \
LIBC_INTRIN \
LIBC_LOG \
LIBC_MEM \
@@ -429,21 +444,41 @@ COSMOPOLITAN_HEADERS = \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB \
THIRD_PARTY_REGEX
COSMOCC_PKGS = \
$(COSMOPOLITAN_H_PKGS) \
THIRD_PARTY_AARCH64 \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_INTEL
o/$(MODE)/cosmopolitan.a: \
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
o/cosmopolitan.h: \
o/$(MODE)/tool/build/rollup.com \
libc/integral/normalize.inc \
$(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)))
COSMOCC_HDRS = \
$(wildcard libc/integral/*) \
$(foreach x,$(COSMOCC_PKGS),$($(x)_HDRS)) \
$(foreach x,$(COSMOCC_PKGS),$($(x)_INCS))
o/cosmocc.h.txt: Makefile
$(file >$@, $(call uniq,$(COSMOCC_HDRS)))
COSMOPOLITAN_H_ROOT_HDRS = \
libc/integral/normalize.inc \
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS))
o/cosmopolitan.h.txt: Makefile
$(file >$@, $(call uniq,$(COSMOPOLITAN_H_ROOT_HDRS)))
o/cosmopolitan.h: o/cosmopolitan.h.txt \
$(wildcard libc/integral/*) \
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS)) \
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_INCS))
@$(ECHO) '#ifndef __STRICT_ANSI__' >$@
@$(ECHO) '#define _COSMO_SOURCE' >>$@
@$(ECHO) '#endif' >>$@
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >>$@
@$(COMPILE) -AROLLUP -T$@ build/bootstrap/rollup.com @$< >>$@
o/cosmopolitan.html: private .UNSANDBOXED = 1
o/cosmopolitan.html: \
+100 -433
View File
@@ -19,22 +19,17 @@ 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.
You can start by obtaining a release of our `cosmocc` compiler from
<https://cosmo.zip/pub/cosmocc/>.
```sh
sudo mkdir -p /opt
sudo chmod 1777 /opt
git clone https://github.com/jart/cosmopolitan /opt/cosmo
export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"
echo 'PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"' >>~/.profile
ape-install # optionally install a faster systemwide ape loader
cosmocc --update # pull cosmo and rebuild toolchain
mkdir -p cosmocc
cd cosmocc
wget https://cosmo.zip/pub/cosmocc/cosmocc.zip
unzip cosmocc.zip
```
You've now successfully installed your very own cosmos. Now let's build
an example program:
Here's an example program we can write:
```c
// hello.c
@@ -45,26 +40,11 @@ int main() {
}
```
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.
It can be compiled as follows:
```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
cosmocc -o hello hello.c
./hello
```
The Cosmopolitan Libc runtime links some heavyweight troubleshooting
@@ -72,445 +52,119 @@ features by default, which are very useful for developers and admins.
Here's how you can log system calls:
```sh
./hello.com --strace
./hello --strace
```
Here's how you can get a much more verbose log of function calls:
```sh
./hello.com --ftrace
./hello --ftrace
```
If you don't want rich runtime features like the above included, and you
just want libc, and you want smaller simpler programs. In that case, you
can consider using `MODE=tiny`, which is preconfigured by the repo in
[build/config.mk](build/config.mk). Using this mode is much more
effective at reducing binary footprint than the `-Os` flag alone. You
can change your build mode by doing the following:
You can use the Cosmopolitan's toolchain to build conventional open
source projects which use autotools. This strategy normally works:
```sh
export MODE=tiny
cosmocc --update
```
We can also make our program slightly smaller by using the system call
interface directly, which is fine, since Cosmopolitan polyfills these
interfaces across platforms, including Windows. For example:
```c
// hello2.c
#include <unistd.h>
int main() {
write(1, "hello world\n", 12);
}
```
Once compiled, your APE binary should be ~36kb in size.
```sh
export MODE=tiny
cosmocc -Os -o hello2.com hello2.c
./hello2.com
```
But let's say you only care about your binaries running on Linux and you
don't want to use up all this additional space for platforms like WIN32.
In that case, you can try `MODE=tinylinux` for example which will create
executables more on the order of 8kb (similar to Musl Libc).
```sh
export MODE=tinylinux
cosmocc --update
cosmocc -Os -o hello2.com hello2.c
./hello2.com # <-- actually an ELF executable
```
## ARM
Cosmo supports cross-compiling binaries for machines with ARM
microprocessors. For example:
```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
```
If you want to run the `MODE=aarch64` unit tests, you need to have
qemu-aarch64 installed as a binfmt_misc interpreter. It needs to be a
static binary if you want it to work with Landlock Make's security. You
can use the build included in our `third_party/qemu/` folder.
```
doas cp o/third_party/qemu/qemu-aarch64 /usr/bin/qemu-aarch64
doas sh -c "echo ':qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64:CF' > /proc/sys/fs/binfmt_misc/register"
make -j8 m=aarch64
```
Please note that the qemu-aarch64 binfmt_misc interpreter installation
process is *essential* for being able to use the `aarch64-unknown-cosmo`
toolchain to build fat APE binaries on your x86-64 machine.
## AMD64 + ARM64 fat APE binaries
If you've setup the qemu binfmt_misc interpreter, then you can can use
cosmo's toolchains to build fat ape binaries. It works by compiling your
program twice, so you can have a native build for both architectures in
the same file. The two programs are merged together by apelink.com which
also embeds multiple copies of APE loader and multiple symbols tables.
The easiest way to build fat APE is using `fatcosmocc`. This compiler
works by creating a concomitant `.aarch64/foo.o` for every `foo.o` you
compile. The only exception is the C preprocessor mode, which actually
runs x86-64 GCC except with macros like `__x86_64__` undefined.
This toolchain works great for C projects that are written in a portable
way and don't produce architecture-specific artifacts. One example of a
large project that can be easily built is GNU coreutils.
```sh
cd coreutils
fatcosmocc --update ||exit
./configure CC=fatcosmocc \
AR=fatcosmoar \
INSTALL=$(command -v fatcosmoinstall) \
--prefix=/opt/cosmos \
--disable-nls \
--disable-dependency-tracking \
--disable-silent-rules
make -j8
```
You'll then have a bunch of files like `src/ls` which are fat ape
binaries. If you want to run them on Windows, then you simply need to
rename the file so that it has the `.com` suffix. Better yet, consider
making that a symlink (a.k.a. reparse point). The biggest gotcha with
`fatcosmocc` though is ensuring builds don't strip binaries. For
example, Linux's `install -s` command actually understands Windows'
Portable Executable format well enough to remove the MS-DOS stub, which
is where the APE shell script is stored. You need to ensure that
`fatcosmoinstall` is used instead. Especially if your project needs to
install the libraries built by `fatacosmoar` into `/opt/cosmos`.
## Advanced Fat APE Builds
Once you get seriously involved in creating fat APE builds of software
you're going to eventually outgrow `fatcosmocc`. One example is Emacs
which is trickier to build, because it produces architecture-specific
files, and it also depends on shared files, e.g. zoneinfo. Since we like
having everything in a neat little single-file executable container that
doesn't need an "installation wizard", this tutorial will explain how we
manage to accomplish that.
What you're going to do is, instead of using `fatcosmocc`, you're going
to use both the `x86_64-unknown-cosmo-cc` and `aarch64-unknown-cosmo-cc`
toolchains independently, and then run `apelink` and `zip` to manually
build the final files. But there's a few tricks to learn first.
The first trick is to create a symlink on your system called `/zip`.
Cosmopolitan Libc normally uses that as a synthetic folder that lets you
access the assets in your zip executable. But since that's a read-only
file system, your build system should use the normal one.
```sh
doas ln -sf /opt/cosmos /zip
```
Now create a file named `rebuild-fat.sh` which runs the build twice:
```sh
#!/bin/sh
set -ex
export MODE=aarch64
export COSMOS=/opt/cosmos/aarch64
rebuild-cosmos.sh aarch64
export MODE=
export COSMOS=/opt/cosmos/x86_64
rebuild-cosmos.sh x86_64
wall.com 'finished building'
```
Then create a second file `rebuild-cosmos.sh` which runs your build:
```sh
#!/bin/bash
set -ex
ARCH=${1:-x86_64}
export COSMO=${COSMO:-/opt/cosmo}
export COSMOS=${COSMOS:-/opt/cosmos/$ARCH}
export AS=$(command -v $ARCH-unknown-cosmo-as) || exit
export CC=$(command -v $ARCH-unknown-cosmo-cc) || exit
export CXX=$(command -v $ARCH-unknown-cosmo-c++) || exit
export AR=$(command -v $ARCH-unknown-cosmo-ar) || exit
export STRIP=$(command -v $ARCH-unknown-cosmo-strip) || exit
export INSTALL=$(command -v $ARCH-unknown-cosmo-install) || exit
export OBJCOPY=$(command -v $ARCH-unknown-cosmo-objcopy) || exit
export OBJDUMP=$(command -v $ARCH-unknown-cosmo-objdump) || exit
export ADDR2LINE=$(command -v $ARCH-unknown-cosmo-addr2line) || exit
$CC --update
export COSMOPOLITAN_DISABLE_ZIPOS=1
cd ~/vendor/zlib
./configure --prefix=$COSMOS --static
make clean
make -j
make install
cd ~/vendor/ncurses-6.4
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH --disable-shared
make clean
make -j
make install
cd ~/vendor/readline-8.2
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH --disable-shared
make uninstall || true
make clean
make -j
make install
# NOTES:
# 1. You'll need to patch enum { FOO = x } that fails to build into a #define FOO
# 2. You'll need to patch configure.ac so it DOES NOT define USABLE_FIONREAD to 1
# 2. You'll need to patch configure.ac so it DOES NOT define INTERRUPT_INPUT to 1
cd ~/vendor/emacs-28.2
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH \
--without-x --with-threads --without-gnutls --disable-silent-rules --with-file-notification=no
make uninstall || true
make clean
export CC=x86_64-unknown-cosmo-cc
export CXX=x86_64-unknown-cosmo-c++
./configure --prefix=/opt/cosmos/x86_64
make -j
make install
```
Once you've completed this build process, you'll have the ELF files
`/opt/cosmos/x86_64/bin/emacs` and `/opt/cosmos/aarch64/bin/emacs`. Your
next move is to combine them into a single pristine `emacs.com` file.
## Cosmopolitan Source Builds
Cosmopolitan can be compiled from source on any of our supported
platforms. First, you need to download or clone the repository. If
you're not using x86-64 Linux then you'll need cosmocc too.
```sh
cd /zip
COSMO=${COSMO:-/opt/cosmo}
mkdir -p /opt/cosmos/bin
apelink \
-o /opt/cosmos/bin/emacs.com \
-l "$COSMO/o//ape/ape.elf" \
-l "$COSMO/o/aarch64/ape/ape.elf" \
-M "$COSMO/ape/ape-m1.c" \
/opt/cosmos/x86_64/bin/emacs \
/opt/cosmos/aarch64/bin/emacs
cd /zip
zip -r /opt/cosmos/bin/emacs.com \
aarch64/libexec \
x86_64/libexec \
share/terminfo \
$(find share/emacs -type f |
grep -v '\.el.gz$' |
grep -v refcards |
grep -v images)
git clone https://github.com/jart/cosmopolitan cosmo
cd cosmo
mkdir -p o/third_party/gcc
pushd o/third_party/gcc
wget https://cosmo.zip/pub/cosmocc/cosmocc.zip
unzip cosmocc.zip
popd
```
You can now scp your `emacs.com` build to seven operating systems for
two distinct kinds of microprocessors without any dependencies. All the
LISP, zoneinfo, and termcap files it needs are stored inside the ZIP
structure of the binary, which has performance that's equivalent to the
Linux filesystem (even though it decompresses artifacts on the fly!) For
this reason, you might actually find that fat APE Emacs goes faster if
you're using an operating system like Windows where files are go slow.
If you like to use Vim instead of Emacs, then you can build that too.
However Vim's build system makes it a bit harder, since it's configured
to always strip binaries. The `apelink` program needs the symbol tables
to still be there when it creates the fat version. Otherwise tools like
`--ftrace` won't work.
## Monolithic Source Builds
Cosmopolitan can be compiled from source on any Linux distro. First, you
need to download or clone the repository.
It's recommended that you install a systemwide APE Loader. This command
requires `sudo` access to copy the `ape` command to a system folder and
register with binfmt_misc on Linux, for even more performance.
```sh
wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
tar xf cosmopolitan.tar.gz # see releases page
cd cosmopolitan
ape/apeinstall.sh
```
This will build the entire repository and run all the tests:
You can now build the mono repo with any modern version of GNU Make. To
make life easier, we've included one in the cosmocc toolchain, which is
guaranteed to be compatible and furthermore includes our extensions for
doing build system sandboxing.
```sh
build/bootstrap/make.com
o//third_party/gcc/bin/make -j8
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
bin/ape-install
```
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:
build one particular thing. Here's an example of a target that can be
compiled relatively quickly, which is a simple POSIX test that only
depends on core LIBC packages.
```sh
build/bootstrap/make.com o//examples/hello.com
rm -rf o//libc o//test
o//third_party/gcc/bin/make o//test/posix/signal_test.com
o//test/posix/signal_test.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:
list out each individual one. For example if you wanted to build and run
all the unit tests in the `TEST_POSIX` package, you could say:
```sh
build/bootstrap/make.com o//third_party/chibicc
o//third_party/chibicc/chibicc.com --help
o//third_party/gcc/bin/make o//test/posix
```
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
o//third_party/gcc/bin/make m=tiny
```
Here's some other build modes you can try:
You can furthermore cut out the bloat of other operating systems, and
have Cosmopolitan become much more similar to Musl Libc.
```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
o//third_party/gcc/bin/make m=tinylinux
```
For further details, see [//build/config.mk](build/config.mk).
## Cosmopolitan Amalgamation
## Debugging
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:
To print a log of system calls to stderr:
```sh
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-3.0.zip
unzip cosmopolitan-amalgamation-3.0.zip
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
cosmocc -o hello hello.c
./hello --strace
```
You now have a portable program.
To print a log of function calls to stderr:
```sh
./hello.com
bash -c './hello.com' # older zsh/fish workaround (patched in zsh 5.9 and fish 3.3.0)
cosmocc -o hello hello.c
./hello --ftrace
```
If `./hello.com` executed on Linux throws an error about not finding an
interpreter, it should be fixed by running the following command (although
note that it may not survive a system restart):
Both strace and ftrace use the unbreakable kprintf() facility, which is
able to be sent to a file by setting an environment variable.
```sh
sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
export KPRINTF_LOG=log
./hello --strace
```
If the same command produces puzzling errors on WSL or WINE when using
Redbean 2.x, they may be fixed by disabling binfmt_misc:
```sh
sudo sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/status'
```
Since we used the `ape-no-modify-self.o` bootloader (rather than
`ape.o`) your executable will not modify itself when it's run. What
it'll instead do, is extract a 4kb program (the [APE loader](https://justine.lol/apeloader/))
to `${TMPDIR:-${HOME:-.}}` that maps your program into memory without
needing to copy it. The APE loader must be in an executable location
(e.g. not stored on a `noexec` mount) for it to run. See below for
alternatives:
It's possible to install the APE loader systemwide as follows.
```sh
# System-Wide APE Install
# for Linux, Darwin, and BSDs
# 1. Copies APE Loader to /usr/bin/ape
# 2. Registers w/ binfmt_misc too if Linux
bin/ape-install
# System-Wide APE Uninstall
# for Linux, Darwin, and BSDs
bin/ape-uninstall
```
It's also possible to convert APE binaries into the system-local format
by using the `--assimilate` flag. Please note that if binfmt_misc is in
play, you'll need to unregister it temporarily before doing this, since
the assimilate feature is part of the shell script header.
```sh
$ file hello.com
hello.com: DOS/MBR boot sector
./hello.com --assimilate
$ file hello.com
hello.com: ELF 64-bit LSB executable
```
Now that you're up and running with Cosmopolitan Libc and APE, here's
some of the most important troubleshooting tools APE offers that you
should know, in case you encounter any issues:
```sh
./hello.com --strace # log system calls to stderr
./hello.com --ftrace # log function calls to stderr
```
Do you love tiny binaries? If so, you may not be happy with Cosmo adding
heavyweight features like tracing to your binaries by default. In that
case, you may want to consider using our build system:
```sh
make m=tiny
```
Which will cause programs such as `hello.com` and `life.com` to shrink
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>.
## GDB
Here's the recommended `~/.gdbinit` config:
@@ -542,39 +196,52 @@ You normally run the `.com.dbg` file under gdb. If you need to debug the
gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
```
## Alternative Development Environments
## Platform Notes
### MacOS
### Shells
If you're developing on MacOS you can install the GNU compiler
collection for x86_64-elf via homebrew:
If you use zsh and have trouble running APE programs try `sh -c ./prog`
or simply upgrade to zsh 5.9+ (since we patched it two years ago). The
same is the case for Python `subprocess`, old versions of fish, etc.
### Linux
Some Linux systems are configured to launch MZ executables under WINE.
Other distros configure their stock installs so that APE programs will
print "run-detectors: unable to find an interpreter". For example:
```sh
brew install x86_64-elf-gcc
jart@ubuntu:~$ wget https://cosmo.zip/pub/cosmos/bin/dash
jart@ubuntu:~$ chmod +x dash
jart@ubuntu:~$ ./dash
run-detectors: unable to find an interpreter for ./dash
```
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.
You can fix that by registering APE with `binfmt_misc`:
```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
sudo wget -O /usr/bin/ape https://cosmo.zip/pub/cosmos/bin/ape-$(uname -m).elf
sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
sudo sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
```
You should be good now. APE will not only work, it'll launch executables
400µs faster now too. However if things still didn't work out, it's also
possible to disable `binfmt_misc` as follows:
```sh
sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/cli' # remove Ubuntu's MZ interpreter
sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/status' # remove ALL binfmt_misc entries
```
### WSL
It's normally unsafe to use APE in a WSL environment, because it tries
to run MZ executables as WIN32 binaries within the WSL environment. In
order to make it safe to use Cosmopolitan software on WSL, run this:
```sh
sudo sh -c "echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop"
```
## Discord Chatroom
+184 -192
View File
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include <dispatch/dispatch.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <libkern/OSCacheControl.h>
@@ -26,6 +27,7 @@
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/random.h>
#include <sys/uio.h>
@@ -34,7 +36,7 @@
#define pagesz 16384
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 5
#define SYSLIB_VERSION 8
struct Syslib {
int magic;
@@ -60,7 +62,7 @@ struct Syslib {
/* v2 (2023-09-10) */
pthread_t (*pthread_self)(void);
void (*dispatch_release)(dispatch_semaphore_t);
int (*raise)(int);
long (*raise)(int);
int (*pthread_join)(pthread_t, void **);
void (*pthread_yield_np)(void);
int pthread_stack_min;
@@ -91,6 +93,11 @@ struct Syslib {
long (*sem_trywait)(int *);
long (*getrlimit)(int, struct rlimit *);
long (*setrlimit)(int, const struct rlimit *);
// v6 (2023-11-03)
void *(*dlopen)(const char *, int);
void *(*dlsym)(void *, const char *);
int (*dlclose)(void *);
char *(*dlerror)(void);
};
#define ELFCLASS32 1
@@ -225,60 +232,6 @@ static const char *BaseName(const char *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) {
@@ -361,7 +314,7 @@ __attribute__((__noreturn__)) static void Pexit(const char *c, int failed,
static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
if (pathlen + 1 + ps->namelen + 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->name, ps->namelen);
ps->path[pathlen + ps->namelen] = 0;
return !access(ps->path, X_OK);
}
@@ -390,7 +343,7 @@ static char FindCommand(struct PathSearcher *ps) {
/* paths are always 100% taken literally when a slash exists
$ ape foo/bar.com arg1 arg2 */
if (MemChr(ps->name, '/', ps->namelen)) {
if (memchr(ps->name, '/', ps->namelen)) {
return AccessCommand(ps, 0);
}
@@ -476,6 +429,111 @@ static void pthread_jit_write_protect_np_workaround(int enabled) {
Pexit("ape", 0, "failed to set jit write protection");
}
__attribute__((__noinline__)) static long sysret(long rc) {
return rc == -1 ? -errno : rc;
}
static long sys_fork(void) {
return sysret(fork());
}
static long sys_close(int fd) {
return sysret(close(fd));
}
static long sys_raise(int sig) {
return sysret(raise(sig));
}
static long sys_pipe(int pfds[2]) {
return sysret(pipe(pfds));
}
static long sys_munmap(void *addr, size_t size) {
return sysret(munmap(addr, size));
}
static long sys_read(int fd, void *data, size_t size) {
return sysret(read(fd, data, size));
}
static long sys_mprotect(void *data, size_t size, int prot) {
return sysret(mprotect(data, size, prot));
}
static long sys_sigaltstack(const stack_t *ss, stack_t *oss) {
return sysret(sigaltstack(ss, oss));
}
static long sys_getentropy(void *buf, size_t buflen) {
return sysret(getentropy(buf, buflen));
}
static long sys_sem_open(const char *name, int oflags, mode_t mode,
unsigned value) {
return sysret((long)sem_open(name, oflags, mode, value));
}
static long sys_sem_unlink(const char *name) {
return sysret(sem_unlink(name));
}
static long sys_sem_close(sem_t *sem) {
return sysret(sem_close(sem));
}
static long sys_sem_post(sem_t *sem) {
return sysret(sem_post(sem));
}
static long sys_sem_wait(sem_t *sem) {
return sysret(sem_wait(sem));
}
static long sys_sem_trywait(sem_t *sem) {
return sysret(sem_trywait(sem));
}
static long sys_getrlimit(int which, struct rlimit *rlim) {
return sysret(getrlimit(which, rlim));
}
static long sys_setrlimit(int which, const struct rlimit *rlim) {
return sysret(setrlimit(which, rlim));
}
static long sys_write(int fd, const void *data, size_t size) {
return sysret(write(fd, data, size));
}
static long sys_clock_gettime(int clock, struct timespec *ts) {
return sysret(clock_gettime((clockid_t)clock, ts));
}
static long sys_openat(int fd, const char *path, int flags, int mode) {
return sysret(openat(fd, path, flags, mode));
}
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));
}
static long sys_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact) {
return sysret(sigaction(sig, act, oact));
}
static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *errorfds, const struct timespec *timeout,
const sigset_t *sigmask) {
return sysret(pselect(nfds, readfds, writefds, errorfds, timeout, sigmask));
}
__attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
long *sp, struct ElfEhdr *e,
struct ElfPhdr *p,
@@ -542,8 +600,8 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
/* 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);
rc = sys_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)) {
@@ -593,17 +651,47 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
}
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 (wipe) Bzero((void *)(dynbase + a), wipe);
if (prot1 & PROT_EXEC) {
#ifdef SIP_DISABLED
// if sip is disabled then we can load the executable segments
// off the binary into memory without needing to copy anything
// which provides considerably better performance for building
rc = sys_mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz);
if (rc < 0) {
if (rc == -EPERM) {
Pexit(exe, rc,
"map(exec) failed because SIP (System Integrity Protection) "
"is enabled, but APE Loader was compiled with SIP_DISABLED");
} else {
Pexit(exe, rc, "map(exec) failed");
}
}
#else
// the issue is that if sip is enabled then, attempting to map
// it with exec permission will cause xnu to phone home a hash
// of the entire file to apple intelligence as a one time cost
// which is literally minutes for executables holding big data
// since there's no public apple api for detecting sip we read
// as the default strategy which is slow but it works for both
rc = sys_mmap(addr, size, (prot1 = PROT_READ | PROT_WRITE),
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
if (rc < 0) Pexit(exe, rc, "prog mmap anon");
rc = pread(fd, addr, p[i].p_filesz, p[i].p_offset & -pagesz);
if (rc != p[i].p_filesz) Pexit(exe, -errno, "prog pread");
#endif
} else {
rc = sys_mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz);
if (rc < 0) Pexit(exe, rc, "prog mmap");
}
if (wipe) memset((void *)(dynbase + a), 0, wipe);
if (prot2 != prot1) {
rc = mprotect(addr, size, prot2);
rc = sys_mprotect(addr, size, prot2);
if (rc < 0) Pexit(exe, rc, "prog mprotect");
}
/* allocate extra bss */
if (c > b) {
flags |= MAP_ANONYMOUS;
rc = (long)mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0);
rc = sys_mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0);
if (rc < 0) Pexit(exe, rc, "extra bss mmap");
}
} else {
@@ -611,7 +699,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz));
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_memsz;
flags |= MAP_ANONYMOUS;
rc = (long)mmap(addr, size, prot, flags, -1, 0);
rc = sys_mmap(addr, size, prot, flags, -1, 0);
if (rc < 0) Pexit(exe, rc, "bss mmap");
}
}
@@ -708,7 +796,7 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
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,
memmove(p + i, p + i + 1,
(e->e_phnum - (i + 1)) * sizeof(struct ElfPhdr));
}
--e->e_phnum;
@@ -736,7 +824,7 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
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,
memmove(p + i + 1, p + i + 2,
(e->e_phnum - (i + 2)) * sizeof(struct ElfPhdr));
}
--e->e_phnum;
@@ -780,107 +868,6 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
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_close(int fd) {
return sysret(close(fd));
}
static long sys_pipe(int pfds[2]) {
return sysret(pipe(pfds));
}
static long sys_munmap(void *addr, size_t size) {
return sysret(munmap(addr, size));
}
static long sys_read(int fd, void *data, size_t size) {
return sysret(read(fd, data, size));
}
static long sys_mprotect(void *data, size_t size, int prot) {
return sysret(mprotect(data, size, prot));
}
static long sys_sigaltstack(const stack_t *ss, stack_t *oss) {
return sysret(sigaltstack(ss, oss));
}
static long sys_getentropy(void *buf, size_t buflen) {
return sysret(getentropy(buf, buflen));
}
static long sys_sem_open(const char *name, int oflags, mode_t mode,
unsigned value) {
return sysret((long)sem_open(name, oflags, mode, value));
}
static long sys_sem_unlink(const char *name) {
return sysret(sem_unlink(name));
}
static long sys_sem_close(sem_t *sem) {
return sysret(sem_close(sem));
}
static long sys_sem_post(sem_t *sem) {
return sysret(sem_post(sem));
}
static long sys_sem_wait(sem_t *sem) {
return sysret(sem_wait(sem));
}
static long sys_sem_trywait(sem_t *sem) {
return sysret(sem_trywait(sem));
}
static long sys_getrlimit(int which, struct rlimit *rlim) {
return sysret(getrlimit(which, rlim));
}
static long sys_setrlimit(int which, const struct rlimit *rlim) {
return sysret(setrlimit(which, rlim));
}
static long sys_write(int fd, const void *data, size_t size) {
return sysret(write(fd, data, size));
}
static long sys_clock_gettime(int clock, struct timespec *ts) {
return sysret(clock_gettime((clockid_t)clock, ts));
}
static long sys_openat(int fd, const char *path, int flags, int mode) {
return sysret(openat(fd, path, flags, mode));
}
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));
}
static long sys_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact) {
return sysret(sigaction(sig, act, oact));
}
static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *errorfds, const struct timespec *timeout,
const sigset_t *sigmask) {
return sysret(pselect(nfds, readfds, writefds, errorfds, timeout, sigmask));
}
int main(int argc, char **argv, char **envp) {
unsigned i;
int c, n, fd, rc;
@@ -904,6 +891,7 @@ int main(int argc, char **argv, char **envp) {
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.sys_icache_invalidate = sys_icache_invalidate;
M->lib.pthread_create = pthread_create;
M->lib.pthread_exit = pthread_exit;
M->lib.pthread_kill = pthread_kill;
@@ -915,7 +903,7 @@ int main(int argc, char **argv, char **envp) {
M->lib.dispatch_walltime = dispatch_walltime;
M->lib.pthread_self = pthread_self;
M->lib.dispatch_release = dispatch_release;
M->lib.raise = raise;
M->lib.raise = sys_raise;
M->lib.pthread_join = pthread_join;
M->lib.pthread_yield_np = pthread_yield_np;
M->lib.pthread_stack_min = PTHREAD_STACK_MIN;
@@ -943,6 +931,10 @@ int main(int argc, char **argv, char **envp) {
M->lib.sem_trywait = sys_sem_trywait;
M->lib.getrlimit = sys_getrlimit;
M->lib.setrlimit = sys_setrlimit;
M->lib.dlopen = dlopen;
M->lib.dlsym = dlsym;
M->lib.dlclose = dlclose;
M->lib.dlerror = dlerror;
/* getenv("_") is close enough to at_execfn */
execfn = argc > 0 ? argv[0] : 0;
@@ -956,6 +948,21 @@ int main(int argc, char **argv, char **envp) {
sp = (long *)(argv - 1);
auxv = (long *)(envp + i + 1);
/* create new bottom of stack for spawned program
system v abi aligns this on a 16-byte boundary
grows down the alloc by poking the guard pages */
n = (auxv - sp + AUXV_WORDS + 1) * sizeof(long);
sp2 = (long *)__builtin_alloca(n);
if ((long)sp2 & 15) ++sp2;
for (; n > 0; n -= pagesz) {
((char *)sp2)[n - 1] = 0;
}
memmove(sp2, sp, (auxv - sp) * sizeof(long));
argv = (char **)(sp2 + 1);
envp = (char **)(sp2 + 1 + argc + 1);
auxv = sp2 + (auxv - sp);
sp = sp2;
/* interpret command line arguments */
if ((M->ps.literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
/* if the first argument is a hyphen then we give the user the
@@ -968,7 +975,7 @@ int main(int argc, char **argv, char **envp) {
} else if (argc < 2) {
Emit("usage: ape PROG [ARGV1,ARGV2,...]\n"
" ape - PROG [ARGV0,ARGV1,...]\n"
"actually portable executable loader silicon 1.8\n"
"actually portable executable loader silicon 1.9\n"
"copyright 2023 justine alexandra roberts tunney\n"
"https://justine.lol/ape.html\n");
_exit(1);
@@ -978,21 +985,6 @@ int main(int argc, char **argv, char **envp) {
argv = (char **)((sp += 1) + 1);
}
/* create new bottom of stack for spawned program
system v abi aligns this on a 16-byte boundary
grows down the alloc by poking the guard pages */
n = (auxv - sp + AUXV_WORDS + 1) * sizeof(long);
sp2 = (long *)__builtin_alloca(n);
if ((long)sp2 & 15) ++sp2;
for (; n > 0; n -= pagesz) {
((char *)sp2)[n - 1] = 0;
}
MemMove(sp2, sp, (auxv - sp) * sizeof(long));
argv = (char **)(sp2 + 1);
envp = (char **)(sp2 + 1 + argc + 1);
auxv = sp2 + (auxv - sp);
sp = sp2;
/* allocate ephemeral memory for reading file */
n = sizeof(union ElfEhdrBuf);
ebuf = (union ElfEhdrBuf *)__builtin_alloca(n);
@@ -1003,10 +995,10 @@ int main(int argc, char **argv, char **envp) {
/* 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, ebuf->buf, sizeof(ebuf->buf))) < 0) {
Pexit(exe, -1, "read");
} else if ((fd = sys_openat(AT_FDCWD, exe, O_RDONLY, 0)) < 0) {
Pexit(exe, fd, "open");
} else if ((rc = sys_read(fd, ebuf->buf, sizeof(ebuf->buf))) < 0) {
Pexit(exe, rc, "read");
} else if ((unsigned long)rc < sizeof(ebuf->ehdr)) {
Pexit(exe, 0, "too small");
}
@@ -1019,8 +1011,8 @@ int main(int argc, char **argv, char **envp) {
}
/* generate some hard random data */
if (getentropy(M->rando, sizeof(M->rando))) {
Pexit(argv[0], -1, "getentropy");
if ((rc = sys_getentropy(M->rando, sizeof(M->rando))) < 0) {
Pexit(argv[0], rc, "getentropy");
}
/* ape intended behavior
+15 -11
View File
@@ -592,7 +592,9 @@ ape_disk:
#ifdef APE_IS_SHELL_SCRIPT
apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii "m=\"$(uname -m)\"\n"
.ascii "m=$(/bin/uname -m 2>/dev/null) || "
.ascii "m=$(/usr/bin/uname -m 2>/dev/null) || "
.ascii "m=x86_64\n"
.ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n"
// Until all operating systems can be updated to support APE,
@@ -615,15 +617,15 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii APE_VERSION_STR
.ascii "\"\n"
.ascii "[ -x \"$t\" ] || {\n"
.ascii "mkdir -p \"${t%/*}\" &&\n"
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
.ascii "/bin/mkdir -p \"${t%/*}\" &&\n"
.ascii "/bin/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 "/bin/dd if=\"$t.$$\""
.ascii " of=\"$t.$$\""
.ascii " skip=5"
.ascii " count=8"
@@ -631,8 +633,8 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii " conv=notrunc"
.ascii " 2>/dev/null\n"
#endif /* SupportsXnu() */
.ascii "chmod 755 \"$t.$$\"\n"
.ascii "mv -f \"$t.$$\" \"$t\"\n"
.ascii "/bin/chmod 755 \"$t.$$\"\n"
.ascii "/bin/mv -f \"$t.$$\" \"$t\"\n"
.ascii "}\n"
.ascii "exec \"$t\" \"$o\" \"$@\"\n"
.ascii "}\n"
@@ -648,9 +650,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.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 "/bin/mkdir -p \"${t%/*}\" 2>/dev/null\n"
.ascii "/bin/cp -f \"$o\" \"$t.$$\" &&\n"
.ascii "/bin/mv -f \"$t.$$\" \"$t\" || exit 120\n"
.ascii "o=\"$t\"\n"
.ascii "}\n"
#endif /* APE_NO_MODIFY_SELF */
@@ -681,7 +683,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii "exec 7<&-\n"
#if SupportsXnu()
.ascii "[ -d /Applications ] && "
.ascii "dd if=\"$o\""
.ascii "/bin/dd if=\"$o\""
.ascii " of=\"$o\""
.ascii " bs=8"
.ascii " skip="
@@ -710,7 +712,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
// because they need to be in the first 4096 bytes
.section .emushprologue,"a",@progbits
emush: .ascii "\n@\n#'\"\n"
.ascii "s=\"$(uname -s)\"\n"
.ascii "s=$(/bin/uname -s 2>/dev/null) || "
.ascii "s=$(/usr/bin/uname -s 2>/dev/null) || "
.ascii "s=Darwin\n"
// our script is running on a non-x86_64 architecture
// 1. `dd` out the appropriate blink vm blob
// 2. gunzip the blink virtual machine executable
+1 -1
View File
@@ -2,7 +2,7 @@
#define COSMOPOLITAN_APE_APE_H_
#define APE_VERSION_MAJOR 1
#define APE_VERSION_MINOR 8
#define APE_VERSION_MINOR 9
#define APE_VERSION_STR APE_VERSION_STR_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
#define APE_VERSION_NOTE APE_VERSION_NOTE_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
-1
View File
@@ -1 +0,0 @@
../bin/ape-install
+148
View File
@@ -0,0 +1,148 @@
#!/bin/sh
PROG=${0##*/}
MODE=${MODE:-$m}
TMPDIR=${TMPDIR:-/tmp}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ ! -f ape/loader.c ]; then
cd "$COSMO" || exit
fi
if [ "$(id -u)" -eq 0 ]; then
SUDO=
else
SUDO=sudo
fi
echo "Actually Portable Executable (APE) Installer" >&2
echo "Author: Justine Tunney <[email protected]>" >&2
# special installation process for apple silicon
if [ "$(uname -s)" = "Darwin" ] && [ "$(uname -m)" = "arm64" ]; then
echo "cc -O -o $TMPDIR/ape.$$ ape/ape-m1.c" >&2
cc -O -o "$TMPDIR/ape.$$" ape/ape-m1.c || exit
if [ ! -d /usr/local/bin ]; then
echo "$SUDO mkdir -p /usr/local/bin" >&2
$SUDO mkdir -p /usr/local/bin || exit
fi
echo "$SUDO mv -f $TMPDIR/ape.$$ /usr/local/bin/ape" >&2
$SUDO mv -f "$TMPDIR/ape.$$" /usr/local/bin/ape || exit
exit
fi
################################################################################
# INSTALL APE LOADER SYSTEMWIDE
if [ -f o/depend ] && make -j8 o//ape; then
echo "successfully recompiled ape loader" >&2
elif [ -x o//ape/ape.elf ] && [ -x o//ape/ape.macho ]; then
echo "using ape loader you compiled earlier" >&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
echo "using prebuilt ape loader from cosmo repo" >&2
mkdir -p o//ape || exit
cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit
cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit
else
echo "no cosmopolitan libc repository here" >&2
echo "fetching ape loader from justine.lol" >&2
mkdir -p o//ape || exit
if command -v wget >/dev/null 2>&1; then
wget -qO o//ape/ape.elf https://justine.lol/ape.elf || exit
wget -qO o//ape/ape.macho https://justine.lol/ape.macho || exit
else
curl -Rso o//ape/ape.elf https://justine.lol/ape.elf || exit
curl -Rso o//ape/ape.macho https://justine.lol/ape.macho || exit
fi
chmod +x o//ape/ape.elf || exit
chmod +x o//ape/ape.macho || exit
fi
if [ "$(uname -s)" = "Darwin" ]; then
if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then
echo >&2
echo "installing o//ape/ape.macho to /usr/bin/ape" >&2
echo "$SUDO cp -f o//ape/ape.macho /usr/bin/ape" >&2
$SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit
echo "done" >&2
fi
else
if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then
echo >&2
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
$SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit
echo "done" >&2
fi
fi
################################################################################
# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY)
if [ x"$(uname -s)" = xLinux ]; then
if [ -e /proc/sys/fs/binfmt_misc/APE ]; then
echo >&2
echo it looks like APE is already registered with binfmt_misc >&2
echo To reinstall please run ape/apeuninstall.sh first >&2
echo please check that it is mapped to ape not /bin/sh >&2
echo cat /proc/sys/fs/binfmt_misc/APE >&2
cat /proc/sys/fs/binfmt_misc/APE >&2
exit
fi
if ! [ -e /proc/sys/fs/binfmt_misc ]; then
echo >&2
echo loading binfmt_misc into your kernel >&2
echo you may need to edit configs to persist across reboot >&2
echo $SUDO modprobe binfmt_misc >&2
$SUDO modprobe binfmt_misc || exit
echo done >&2
fi
if ! [ -e /proc/sys/fs/binfmt_misc/register ]; then
echo >&2
echo mounting binfmt_misc into your kernel >&2
echo you may need to edit configs to persist across reboot >&2
echo $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc >&2
$SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc || exit
echo done >&2
fi
echo >&2
echo registering APE with binfmt_misc >&2
echo you may need to edit configs to persist across reboot >&2
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
echo done >&2
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
echo >&2
echo enabling binfmt_misc >&2
echo you may need to edit configs to persist across reboot >&2
echo $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' >&2
$SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' || exit
echo done >&2
fi
fi
################################################################################
{
echo
echo "------------------------------------------------------------------"
echo
echo "APE INSTALL COMPLETE"
echo
echo "If you decide to uninstall APE later on"
echo "you may do so using ape/apeuninstall.sh"
echo
echo "Enjoy your APE loader (>'.')>"
echo
} >&2
-1
View File
@@ -1 +0,0 @@
../bin/ape-uninstall
+64
View File
@@ -0,0 +1,64 @@
#!/bin/sh
PROG=${0##*/}
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ ! -f ape/loader.c ]; then
cd "$COSMO" || exit
fi
if [ "$UID" = "0" ]; then
SUDO=
else
SUDO=sudo
fi
{
echo
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
echo "You may then use ape/apeinstall.sh to reinstall it"
echo
} >&2
set -ex
for f in /proc/sys/fs/binfmt_misc/APE*; do
if [ -f $f ]; then
$SUDO sh -c "echo -1 >$f" || exit
fi
done
# system installation
if [ -f /usr/bin/ape ]; then
$SUDO rm -f /usr/bin/ape
fi
if [ -f /usr/local/bin/ape ]; then
$SUDO rm -f /usr/local/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-1.6 \
.ape-1.7 \
.ape-1.8 \
.ape-1.9 \
.ape-blink-0.9.2 \
.ape-blink-1.0.0; do
rm -f \
~/$x \
/tmp/$x \
o/tmp/$x \
"${TMPDIR:-/tmp}/$x"
done
+5
View File
@@ -947,6 +947,11 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
os = OPENBSD;
}
/* xnu passes auxv as an array of strings */
if (os == XNU) {
*auxv = 0;
}
/* detect netbsd and find end of words */
pagesz = 0;
for (ap = auxv; ap[0]; ap += 2) {
+2
View File
@@ -23,6 +23,7 @@
#ifdef __aarch64__
_start: mov x1,sp
and sp,x1,#-16
mov x29,0
bl ApeLoader
.endfn _start,globl
@@ -33,6 +34,7 @@ XnuEntrypoint:
mov $_HOSTXNU,%dl // xnu's not unix!
ElfEntrypoint:
mov %rsp,%rsi // save real stack
andq $-16,%rsp // force SSE alignment
call ApeLoader
.endfn ElfEntrypoint,globl
.endfn XnuEntrypoint,globl
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-addr2line"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-1
View File
@@ -1 +0,0 @@
apecopy
-21
View File
@@ -1,21 +0,0 @@
#!/bin/sh
PROG=${0##*/}
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
fatal_error() {
echo "$PROG: $1" >&2
exit 1
}
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
if [ ! -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-ar" ]; then
fatal_error "you need to run: aarch64-unknown-cosmo-cc --update"
fi
exec "$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-ar" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-as"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-nm"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-objcopy"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-objdump"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-strip"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-134
View File
@@ -1,134 +0,0 @@
#!/bin/sh
PROG=${0##*/}
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ ! -f ape/loader.c ]; then
cd "$COSMO" || exit
fi
if [ "$(id -u)" -eq 0 ]; then
SUDO=
else
SUDO=sudo
fi
echo "Actually Portable Executable (APE) Installer" >&2
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
elif [ -x o//ape/ape.elf ] && [ -x o//ape/ape.macho ]; then
echo "using ape loader you compiled earlier" >&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
echo "using prebuilt ape loader from cosmo repo" >&2
mkdir -p o//ape || exit
cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit
cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit
else
echo "no cosmopolitan libc repository here" >&2
echo "fetching ape loader from justine.lol" >&2
mkdir -p o//ape || exit
if command -v wget >/dev/null 2>&1; then
wget -qO o//ape/ape.elf https://justine.lol/ape.elf || exit
wget -qO o//ape/ape.macho https://justine.lol/ape.macho || exit
else
curl -Rso o//ape/ape.elf https://justine.lol/ape.elf || exit
curl -Rso o//ape/ape.macho https://justine.lol/ape.macho || exit
fi
chmod +x o//ape/ape.elf || exit
chmod +x o//ape/ape.macho || exit
fi
if [ "$(uname -s)" = "Darwin" ]; then
if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then
echo >&2
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
$SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit
echo "done" >&2
fi
else
if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then
echo >&2
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
$SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit
echo "done" >&2
fi
fi
################################################################################
# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY)
if [ x"$(uname -s)" = xLinux ]; then
if [ -e /proc/sys/fs/binfmt_misc/APE ]; then
echo >&2
echo it looks like APE is already registered with binfmt_misc >&2
echo To reinstall please run ape/apeuninstall.sh first >&2
echo please check that it is mapped to ape not /bin/sh >&2
echo cat /proc/sys/fs/binfmt_misc/APE >&2
cat /proc/sys/fs/binfmt_misc/APE >&2
exit
fi
if ! [ -e /proc/sys/fs/binfmt_misc ]; then
echo >&2
echo loading binfmt_misc into your kernel >&2
echo you may need to edit configs to persist across reboot >&2
echo $SUDO modprobe binfmt_misc >&2
$SUDO modprobe binfmt_misc || exit
echo done >&2
fi
if ! [ -e /proc/sys/fs/binfmt_misc/register ]; then
echo >&2
echo mounting binfmt_misc into your kernel >&2
echo you may need to edit configs to persist across reboot >&2
echo $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc >&2
$SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc || exit
echo done >&2
fi
echo >&2
echo registering APE with binfmt_misc >&2
echo you may need to edit configs to persist across reboot >&2
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
echo done >&2
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
echo >&2
echo enabling binfmt_misc >&2
echo you may need to edit configs to persist across reboot >&2
echo $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' >&2
$SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' || exit
echo done >&2
fi
fi
################################################################################
{
echo
echo "------------------------------------------------------------------"
echo
echo "APE INSTALL COMPLETE"
echo
echo "If you decide to uninstall APE later on"
echo "you may do so using ape/apeuninstall.sh"
echo
echo "Enjoy your APE loader (>'.')>"
echo
} >&2
-60
View File
@@ -1,60 +0,0 @@
#!/bin/sh
PROG=${0##*/}
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ ! -f ape/loader.c ]; then
cd "$COSMO" || exit
fi
if [ "$UID" = "0" ]; then
SUDO=
else
SUDO=sudo
fi
{
echo
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
echo "You may then use ape/apeinstall.sh to reinstall it"
echo
} >&2
set -ex
for f in /proc/sys/fs/binfmt_misc/APE*; do
if [ -f $f ]; then
$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-1.6 \
.ape-1.7 \
.ape-1.8 \
.ape-blink-0.9.2 \
.ape-blink-1.0.0; do
rm -f \
~/$x \
/tmp/$x \
o/tmp/$x \
"${TMPDIR:-/tmp}/$x"
done
-102
View File
@@ -1,102 +0,0 @@
#!/bin/sh
PROG=${0##*/}
COSMO=${COSMO:-/opt/cosmo}
if [ x"$1" = x"--version" ]; then
cat <<EOF
$PROG 0.1
Copyright (c) 2023 Justine Alexandra Roberts Tunney
Cosmopolitan Libc and LLVM libcxx/compiler-rt are subject to non-GPL
notice licenses, e.g. ISC, MIT, etc. Your compiled programs must embed
our copyright notices. This toolchain is configured to do so default.
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
For more information, see the Cosmopolitan LICENSE files.
Copyright (C) 2019 Free Software Foundation, Inc.
This launches GNU GCC/Binutils subprocesses, which is free software; see
Cosmopolitan's third_party/gcc/ for source code and copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
EOF
exit
fi
if [ x"$1" = x"--help" ]; then
cat <<EOF
Usage: $PROG INPUT OUTPUT
Converts an executable linked by cosmocc to the Actually Portable
Executable file format. See $PROG --version for other details.
EOF
exit
fi
fatal_error() {
echo "$PROG: fatal error: $1" >&2
echo "operation terminated." >&2
exit 1
}
CROSS=1
ARCH=${PROG%%-*} # split(prog, '-')[0]
if [ x"$ARCH" = x"$PROG" ]; then
ARCH=x86_64
CROSS=0
fi
if [ x"$ARCH" = x"x86_64" ]; then
MODE=${MODE:-$m}
else
MODE=${MODE:-${m:-$ARCH}}
fi
if [ $CROSS -eq 0 ]; then
COSMOS=${COSMOS:-/opt/cosmos}
else
COSMOS=${COSMOS:-/opt/cosmos/$ARCH}
fi
if [ x"$ARCH" = x"x86_64" ]; then
OBJCOPYFLAGS="-S -O binary"
elif [ x"$ARCH" = x"aarch64" ]; then
OBJCOPYFLAGS="-S"
else
fatal_error "$ARCH: unsupported architecture"
fi
if [ ! -d "$COSMO" ]; then
fatal_error "you need to clone cosmopolitan to your $COSMO directory"
fi
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
if [ ! -f "$COSMO/o//tool/build/zipcopy.com" ] ||
[ ! -f "$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" ]; then
if [ $CROSS -eq 0 ]; then
fatal_error "you need to run: cosmocc --update"
else
fatal_error "you need to run: $ARCH-unknown-cosmo-cosmocc --update"
fi
fi
INPUT=$1
OUTPUT=$2
if [ ! -f "$INPUT" ]; then
fatal_error "$INPUT: missing input and output arguments"
elif [ ! -f "$INPUT" ]; then
fatal_error "$INPUT: no such file"
elif [ ! -f "$INPUT" ]; then
fatal_error "$INPUT: missing output argument"
elif [ x"$INPUT" = x"$OUTPUT" ]; then
fatal_error "$INPUT: input and output file can't be the same"
fi
"$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" \
$OBJCOPYFLAGS \
"$INPUT" \
"$OUTPUT" || exit
"$COSMO/o//tool/build/zipcopy.com" \
"$INPUT" \
"$OUTPUT" || exit
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
COSMO=${COSMO:-/opt/cosmo}
exec "$COSMO/o//tool/build/apelink.com" "$@"
-31
View File
@@ -1,31 +0,0 @@
#!/bin/sh
COSMO=${COSMO:-/opt/cosmo}
set -- -apifCe "$@"
if [ -n "$ADDR2LINE" ]; then
exec "$ADDR2LINE" "$@"
fi
find_addr2line() {
if [ -x o/third_party/gcc/bin/$1-linux-cosmo-addr2line ]; then
ADDR2LINE=o/third_party/gcc/bin/$1-linux-cosmo-addr2line
elif [ -x o/third_party/gcc/bin/$1-linux-musl-addr2line ]; then
ADDR2LINE=o/third_party/gcc/bin/$1-linux-musl-addr2line
elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-addr2line" ]; then
ADDR2LINE="$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-addr2line"
elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-musl-addr2line" ]; then
ADDR2LINE="$COSMO/o/third_party/gcc/bin/$1-linux-musl-addr2line"
else
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
exit 1
fi
}
for ARCH in x86_64 aarch64; do
find_addr2line $ARCH
"$ADDR2LINE" "$@" 2>/dev/null && exit
done
echo "error: addr2line failed" >&2
exit 1
-381
View File
@@ -1,381 +0,0 @@
#!/bin/sh
#
# cosmopolitan c/c++ compiler
#
# getting started
#
# sudo chmod 1777 /opt # sticky bit isn't required
# git clone https://github.com/jart/cosmopolitan /opt/cosmo
# export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"
# echo 'export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"' >>~/.profile
# ape-install # optionally install a faster systemwide ape loader
# cosmocc --update # pull and rebuild toolchain artifacts
#
# getting started synopsis
#
# cosmocc -o hello.com hello.c
# ./foo.com
# ./foo.com --strace
# ./foo.com --ftrace
#
# how to build a project like lua 5.4.6
#
# make all test CC=cosmocc
# src/lua -e 'print("hi")'
# make install INSTALL_TOP=/opt/cosmos
# apecopy src/lua src/lua.com # convert to portable ape binary
#
# how to cross compile a project like lua 5.4.6
#
# aarch64-unknown-cosmo-cc --update
# make clean all test CC=aarch64-unknown-cosmo-cc AR='aarch64-unknown-cosmo-ar rc' -j8
# qemu-aarch64 src/lua -e 'print("hi")'
# make install INSTALL_TOP=/opt/cosmos/aarch64
#
# building in tiny mode
#
# export MODE=tiny
# cosmocc --update
# cosmocc -Os -o foo.com foo.c
#
# building in tiniest mode (linux only)
#
# export MODE=tinylinux
# cosmocc --update
# cosmocc -Os -o foo.com foo.c
#
# hardening programs with memory safety
#
# export MODE=asan
# cosmocc --update
# cosmocc -o foo.com foo.c
#
# detecting this environment
#
# - `__COSMOCC__` is defined when this compiler is in play
# - `__COSMOPOLITAN__` is always defined by Cosmopolitan Libc
#
# some notes on this compiler
#
# - the underlying compiler itself is gcc
# - we use cosmopoiltan libc rather than glibc
# - we use llvm's compiler-rt and libcxx runtimes
# - we patched gcc so switch case can have symbols
# - our scanf() implementation is somewhat troubled
#
# compiler flags that aren't supported
#
# - `-r` partial linking not implemented yet (todo)
# - `-S` you need to put your assembly behind #ifdefs instead
# - `-fexceptions` cosmopolitan doesn't support c++ exceptions yet
# - `-frtti` cosmopolitan doesn't support c++ runtime reflection yet
# - `-mred-zone` the system v red zone doesn't exist on windows and metal
# - `-fpic`, '-fPIC', `-shared`, `-pie`, etc. no shared object support yet
# - `-fsanitize=thread` cosmopolitan doesn't have thread sanitizer runtime yet
# - `-fomit-frame-pointer` is partially supported (apple forbids full removal)
#
# for further details, run `man gcc`
PROG=${0##*/}
COSMO=${COSMO:-/opt/cosmo}
GCC_VERSION=11.2.0
if [ "$1" = "--version" ]; then
cat <<EOF
$PROG (GCC) $GCC_VERSION
Copyright (c) 2023 Justine Alexandra Roberts Tunney
Cosmopolitan Libc and LLVM libcxx/compiler-rt are subject to non-GPL
notice licenses, e.g. ISC, MIT, etc. Your compiled programs must embed
our copyright notices. This toolchain is configured to do so default.
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
For more information, see the Cosmopolitan LICENSE files.
Copyright (C) 2019 Free Software Foundation, Inc.
This launches GNU GCC/Binutils subprocesses, which is free software; see
Cosmopolitan's third_party/gcc/ for source code and copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
EOF
exit
fi
fatal_error() {
echo "$PROG: fatal error: $1" >&2
echo "compilation terminated." >&2
exit 1
}
log_command() {
if [ -n "$BUILDLOG" ]; then
printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>"$BUILDLOG"
fi
}
ORIGINAL="$0 $*"
PLATFORM="-D__COSMOPOLITAN__ -D__COSMOCC__"
PREDEF="-include libc/integral/normalize.inc"
CFLAGS="-fportcosmo -fno-dwarf2-cfi-asm -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-semantic-interposition"
CPPFLAGS="-fno-pie -nostdinc -fno-math-errno -iquote $COSMO"
LDFLAGS="-static -no-pie -nostdlib -fuse-ld=bfd"
APEFLAGS="-Wl,--gc-sections"
PRECIOUS="-fno-omit-frame-pointer"
CROSS=1
ARCH=${PROG%%-*} # split(prog, '-')[0]
if [ x"$ARCH" = x"$PROG" ]; then
ARCH=x86_64
CROSS=0
fi
if [ x"$ARCH" = x"x86_64" ]; then
MODE=${MODE:-$m}
else
MODE=${MODE:-${m:-$ARCH}}
fi
if [ $CROSS -eq 0 ]; then
COSMOS=${COSMOS:-/opt/cosmos}
else
COSMOS=${COSMOS:-/opt/cosmos/$ARCH}
fi
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
CC="$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-gcc"
CRT="$COSMO/o/$MODE/libc/crt/crt.o"
LDLIBS="$COSMO/o/$MODE/cosmopolitan.a"
CPPFLAGS="$CPPFLAGS -isystem $COSMOS/include -isystem $COSMO/libc/isystem"
LDFLAGS="$LDFLAGS -L$COSMOS/lib"
if [ x"$PROG" != x"${PROG%++}" ]; then
CC="$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-g++"
CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit"
LDLIBS="$COSMO/o/$MODE/third_party/libcxx/libcxx.a $LDLIBS"
fi
PAGESZ=4096
if [ x"$ARCH" = x"x86_64" ]; then
OBJCOPYFLAGS="-S -O binary"
CRT="$COSMO/o/$MODE/ape/ape-no-modify-self.o $CRT"
CPPFLAGS="$CPPFLAGS -mno-red-zone"
CFLAGS="$CFLAGS -mno-tls-direct-seg-refs"
LDFLAGS="$LDFLAGS -Wl,-T,$COSMO/o/$MODE/ape/ape.lds"
if [ x"$MODE" = x"aarch64" ]; then
fatal_error '$MODE must not be aarch64 when using x86_64 cross compiler'
elif [ x"$MODE" != x"${MODE#* }" ]; then
fatal_error '$MODE must not contain hyphens when targeting x86_64'
fi
elif [ x"$ARCH" = x"aarch64" ]; then
OBJCOPYFLAGS="-S"
PAGESZ=16384
CFLAGS="$CFLAGS -ffixed-x18 -ffixed-x28 -mno-outline-atomics"
LDFLAGS="$LDFLAGS -Wl,-T,$COSMO/o/$MODE/ape/aarch64.lds"
if [ x"$MODE" != x"aarch64" ] && [ x"$MODE" = x"${MODE#aarch64-*}" ]; then
fatal_error '$MODE must be either "aarch64" or "aarch64-FOO" when using aarch64 cross compiler'
fi
else
fatal_error "$ARCH: unsupported architecture"
fi
LDFLAGS="$LDFLAGS -Wl,-z,common-page-size=$PAGESZ -Wl,-z,max-page-size=16384"
if [ ! -d "$COSMO" ]; then
fatal_error "you need to clone cosmopolitan to your $COSMO directory"
fi
if [ "$1" = "--update" ]; then
cd $COSMO || exit
echo "building cosmo host toolchain..." >&2
make --silent -j toolchain MODE= ARCH=x86_64 || exit
echo "building cosmo target (MODE=$MODE) toolchain..." >&2
make --silent -j toolchain MODE="$MODE" || exit
echo "setting up your cosmos..." >&2
mkdir -p "$COSMOS/lib" || exit
for lib in c dl gcc_s m pthread resolv rt dl z stdc++; do
if [ ! -f "$COSMOS/lib/lib${lib}.a" ]; then
printf '\041\074\141\162\143\150\076\012' >"$COSMOS/lib/lib${lib}.a" || exit
fi
done
echo "successfully updated your cosmo toolchain" >&2
exit
fi
if [ ! -f "$COSMOS/lib/libc.a" ] ||
[ ! -f "$COSMO/o/$MODE/cosmopolitan.a" ]; then
fatal_error "you need to run: $PROG --update"
fi
OPT=
FIRST=1
OUTPUT=
SFLAG=0
INTENT=ld
GOT_SOME=0
NEED_OUTPUT=
RELOCATABLE=0
for x; do
if [ $FIRST -eq 1 ]; then
set --
FIRST=0
fi
if [ -n "$NEED_OUTPUT" ]; then
NEED_OUTPUT=
OUTPUT=$x
set -- "$@" "$x"
continue
fi
if [ x"$x" = x"-" ] || # is an argument
[ x"$x" = x"${x#-*}" ]; then # !startswith(x, "-")
GOT_SOME=1
elif [ x"$x" = x"-static-libstdc++" ]; then
continue
elif [ x"$x" = x"-static-libgcc" ]; then
continue
elif [ x"$x" != x"${x#-O}" ]; then
OPT=$x
elif [ x"$x" = x"-c" ]; then
INTENT=cc
elif [ x"$x" = x"-s" ]; then
SFLAG=1
continue
elif [ x"$x" = x"-r" ]; then
RELOCATABLE=1
elif [ x"$x" = x"-E" ]; then
INTENT=cpp
elif [ x"$x" = x"-o" ]; then
NEED_OUTPUT=1
elif [ x"$x" = x"-mcosmo" ]; then
CPPFLAGS="$CPPFLAGS -D_COSMO_SOURCE"
continue
elif [ x"$x" != x"${x#-o}" ]; then
OUTPUT=${x#-o}
elif [ x"$x" = x"-fpic" ]; then
continue
elif [ x"$x" = x"-fPIC" ]; then
continue
elif [ x"$x" = x"-r" ] ||
[ x"$x" = x"-pie" ] ||
[ x"$x" = x"-frtti" ] ||
[ x"$x" = x"-shared" ] ||
[ x"$x" = x"-nostdlib" ] ||
[ x"$x" = x"-mred-zone" ] ||
[ x"$x" = x"-fexceptions" ] ||
[ x"$x" = x"-fsanitize=thread" ]; then
echo "$PROG: $x not supported" >&2
exit 1
elif [ x"$x" = x"-fsanitize=all" ] ||
[ x"$x" = x"-fsanitize=address" ] ||
[ x"$x" = x"-fsanitize=undefined" ]; then
echo "$PROG: use cosmo MODE=dbg or MODE=asan rather than passing $x" >&2
exit 1
elif [ x"$x" = x"-fomit-frame-pointer" ]; then
# Quoth Apple "The frame pointer register must always address a
# valid frame record. Some functions — such as leaf functions or
# tail calls — may opt not to create an entry in this list. As a
# result, stack traces are always meaningful, even without debug
# information."
set -- "$@" -momit-leaf-frame-pointer -foptimize-sibling-calls
continue
elif [ x"$x" != x"${x#-Werror}" ] || \
[ x"$x" = x"-pedantic-errors" ]; then
# this toolchain is intended for building other people's code
# elevating warnings into errors, should only be done by devs
continue
elif [ x"$x" = x"-march=native" ]; then
if [ $CROSS -eq 0 ]; then
set -- "$@" $("$COSMO/o//tool/build/march-native.com")
else
fatal_error "-march=native can't be used when cross compiling"
fi
continue
elif [ x"$x" = x"-dumpversion" ]; then
echo $GCC_VERSION
exit 0
fi
set -- "$@" "$x"
done
if [ "$GOT_SOME" -eq 0 ]; then
fatal_error "no input files"
fi
if [ $RELOCATABLE -eq 1 ]; then
LDFLAGS="$LDFLAGS -r"
fi
if [ x"$MODE" = x"nox87" ]; then
CPPFLAGS="$CPPFLAGS -mlong-double-64"
fi
# support --ftrace unless optimizing for size
if [ x"$OPT" != x"-Os" ] && # $OPT != -Os
[ x"${MODE%tiny}" = x"${MODE}" ]; then # $MODE not in (tiny, aarch64-tiny)
if [ x"$ARCH" = x"x86_64" ]; then
CFLAGS="$CFLAGS -fpatchable-function-entry=18,16"
elif [ x"$ARCH" = x"aarch64" ]; then
CFLAGS="$CFLAGS -fpatchable-function-entry=7,6"
fi
fi
# ask compiler to generate sanitization code in debug mode
if [ x"$MODE" != x"${MODE%*dbg}" ]; then # endswith($MODE, "dbg")
if [ x"$ARCH" = x"x86_64" ]; then
CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
else
CPPFLAGS="$CPPFLAGS -fsanitize=undefined"
fi
fi
# ask compiler to generate memory safety code in asan mode
if [ x"$MODE" != x"${MODE%*asan}" ]; then # endswith($MODE, "asan")
if [ x"$ARCH" = x"x86_64" ]; then
CPPFLAGS="$CPPFLAGS -fsanitize=address"
else
fatal_error "address sanitizer not supported on non-x86 yet"
fi
fi
# maximize frame pointers unless optimizing for size
if [ x"$OPT" != x"-Os" ] && # $OPT != "-Os"
[ x"$MODE" != x"${MODE%tiny}" ]; then # endswith($MODE, "tiny")
CFLAGS="$CFLAGS -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer"
fi
if [ $INTENT = cpp ]; then
set -- "$CC" $PLATFORM $CPPFLAGS "$@"
elif [ $INTENT = cc ]; then
set -- "$CC" $PLATFORM $PREDEF $CFLAGS $CPPFLAGS "$@" $PRECIOUS
else
set -- "$CC" $PLATFORM $PREDEF $CFLAGS $CPPFLAGS $CRT "$@" $LDFLAGS $LDLIBS $PRECIOUS
fi
log_command "$@"
"$@" || exit
if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then
if [ $INTENT = cc ] || [ $INTENT = ld ]; then
"$COSMO/o//tool/build/fixupobj.com" \
"$OUTPUT" || exit
fi
if [ $INTENT = ld ]; then
if [ x"$OUTPUT" != x"${OUTPUT%.com}" ] ||
[ x"$OUTPUT" != x"${OUTPUT%.exe}" ]; then
# cosmocc -o foo.com ...
# -> foo.com (ape)
# -> foo.com.dbg (elf)
mv -f "$OUTPUT" "$OUTPUT.dbg" || exit
"$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" \
$OBJCOPYFLAGS \
"$OUTPUT.dbg" \
"$OUTPUT" || exit
"$COSMO/o//tool/build/zipcopy.com" \
"$OUTPUT.dbg" \
"$OUTPUT" || exit
elif [ $SFLAG -eq 1 ]; then
"$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-strip" \
"$OUTPUT" || exit
fi
fi
fi
-1
View File
@@ -1 +0,0 @@
fatcosmocc
-1
View File
@@ -1 +0,0 @@
fatcosmoar
-1
View File
@@ -1 +0,0 @@
fatcosmocc
-1
View File
@@ -1 +0,0 @@
fatcosmocc
-1
View File
@@ -1 +0,0 @@
fatcosmoinstall
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-addr2line"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-1
View File
@@ -1 +0,0 @@
apecopy
-22
View File
@@ -1,22 +0,0 @@
#!/bin/sh
PROG=${0##*/}
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
fatal_error() {
echo "$PROG: $1" >&2
exit 1
}
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
if [ ! -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar" ]; then
fatal_error "you need to run: x86_64-unknown-cosmo-cc --update"
fi
exec "$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-as"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-1
View File
@@ -1 +0,0 @@
cosmocc
-1
View File
@@ -1 +0,0 @@
cosmocc
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-nm"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-objcopy"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-objdump"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
BRAND=musl
else
BRAND=cosmo
fi
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-strip"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
exit 1
fi
exec "$TOOL" "$@"
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.
BIN
View File
Binary file not shown.
+2 -1
View File
@@ -222,7 +222,8 @@ DEFAULT_CPPFLAGS += \
-D_COSMO_SOURCE \
-DMODE='"$(MODE)"' \
-nostdinc \
-iquote .
-iquote. \
-isystem libc/isystem
DEFAULT_CFLAGS = \
-std=gnu2x
-1
View File
@@ -17,7 +17,6 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/tty/tty.h"
#include "libc/fmt/fmt.h"
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
+1
View File
@@ -19,6 +19,7 @@
#include "dsp/tty/tty.h"
#include "libc/mem/arraylist2.internal.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/x/x.h"
/* TODO(jart): DELETE */
+56
View File
@@ -0,0 +1,56 @@
#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/dlopen/dlfcn.h"
#include "libc/fmt/itoa.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/runtime.h"
/**
* @fileoverview cosmopolitan dynamic runtime linking demo
*
* Our cosmo_dlopen() interface currently supports:
*
* - x86-64 Linux w/ Glibc
* - x86-64 Linux w/ Musl Libc
* - x86-64 FreeBSD
* - x86-64 Windows
* - x86-64 NetBSD
* - aarch64 Linux w/ Glibc
* - aarch64 Linux w/ Musl Libc
* - aarch64 MacOS
*
*/
int main(int argc, char **argv, char **envp) {
// open the host system's zlib library
void *libc = cosmo_dlopen("libz.so", RTLD_LAZY);
if (!libc) {
tinyprint(2, cosmo_dlerror(), "\n", NULL);
exit(1);
}
// load crc() function address
unsigned (*crc32)(unsigned, void *, int) = cosmo_dlsym(libc, "crc32");
if (!crc32) {
tinyprint(2, cosmo_dlerror(), "\n", NULL);
exit(1);
}
// compute a checksum and print the result
char ibuf[12];
FormatInt32(ibuf, crc32(0, "hi", 2));
tinyprint(1, "crc(hi) = ", ibuf, "\n", NULL);
// mop up
cosmo_dlclose(libc);
exit(0);
}
+3 -2
View File
@@ -43,9 +43,11 @@ EXAMPLES_DIRECTDEPS = \
DSP_SCALE \
DSP_TTY \
LIBC_CALLS \
LIBC_DLOPEN \
LIBC_DNS \
LIBC_FMT \
LIBC_INTRIN \
LIBC_IRQ \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
@@ -91,14 +93,13 @@ EXAMPLES_DIRECTDEPS = \
THIRD_PARTY_VQSORT \
THIRD_PARTY_XED \
THIRD_PARTY_ZLIB \
TOOL_ARGS \
TOOL_BUILD_LIB \
TOOL_VIZ_LIB
EXAMPLES_DEPS := \
$(call uniq,$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x))))
$(EXAMPLES_OBJS): override CFLAGS += -isystem libc/isystem
o/$(MODE)/examples/examples.pkg: \
$(EXAMPLES_OBJS) \
$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x)_A).pkg)
+2 -37
View File
@@ -7,8 +7,9 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#ifdef __COSMOCC__
#ifndef _COSMO_SOURCE
#define _COSMO_SOURCE
#endif
#include <assert.h>
#include <cosmo.h>
#include <errno.h>
@@ -22,42 +23,6 @@
#include <sys/auxv.h>
#include <sys/socket.h>
#include <time.h>
#else
#include "libc/assert.h"
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/pledge.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/consts/tcp.h"
#include "libc/sysv/consts/timer.h"
#include "libc/thread/thread.h"
#include "libc/thread/thread2.h"
#include "net/http/http.h"
#endif
/**
* @fileoverview greenbean lightweight threaded web server
-1
View File
@@ -9,7 +9,6 @@
#endif
#include "libc/runtime/runtime.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "third_party/hiredis/hiredis.h"
-1
View File
@@ -62,7 +62,6 @@ Contact: [email protected]\"\n\
#include "libc/calls/termios.h"
#include "libc/calls/weirdtypes.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/log/log.h"
#include "libc/mem/alg.h"
#include "libc/mem/arraylist2.internal.h"
-1
View File
@@ -19,7 +19,6 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/inttypes.h"
+31
View File
@@ -0,0 +1,31 @@
#include <stdio.h>
#define PARSE_AND_PRINT(type, scan_fmt, print_fmt, str) \
do { \
type val; int ret; \
ret = sscanf(str, scan_fmt, &val); \
printf("\"%s\" => " print_fmt " = %d\n", str, val, ret); \
} while (0)
int main()
{
PARSE_AND_PRINT(float, "%f", "%f", "0.3715");
PARSE_AND_PRINT(float, "%f", "%f", ".3715");
PARSE_AND_PRINT(float, "%f", "%f", "3715");
PARSE_AND_PRINT(float, "%f", "%f", "111.11");
PARSE_AND_PRINT(float, "%f", "%f", "-2.22");
PARSE_AND_PRINT(float, "%f", "%f", "Nan");
PARSE_AND_PRINT(float, "%f", "%f", "nAn(2)");
PARSE_AND_PRINT(float, "%f", "%f", "-NAN(_asdfZXCV1234_)");
PARSE_AND_PRINT(float, "%f", "%f", "-nan");
PARSE_AND_PRINT(float, "%f", "%f", "+nan");
PARSE_AND_PRINT(float, "%f", "%f", "inF");
PARSE_AND_PRINT(float, "%f", "%f", "iNfINiTy");
PARSE_AND_PRINT(float, "%f", "%f", "+inf");
PARSE_AND_PRINT(float, "%f", "%f", "-inf");
PARSE_AND_PRINT(float, "%f", "%f", "0X1.BC70A3D70A3D7P+6");
PARSE_AND_PRINT(float, "%f", "%f", "1.18973e+4932zzz");
PARSE_AND_PRINT(float, "%f", "%.10f", " -0.0000000123junk");
PARSE_AND_PRINT(float, "%f", "%f", "junk");
return 0;
}
-1
View File
@@ -33,7 +33,6 @@
*/
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
-1
View File
@@ -12,7 +12,6 @@
#include "libc/calls/struct/timeval.h"
#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"
-1
View File
@@ -11,7 +11,6 @@
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/gc.h"
-1
View File
@@ -8,7 +8,6 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/stdio/append.h"
-1
View File
@@ -15,7 +15,6 @@
#include "libc/calls/struct/sigset.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
-1
View File
@@ -122,7 +122,6 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/limits.h"
#include "libc/log/log.h"
+2
View File
@@ -26,6 +26,8 @@
__static_yoink("vga_console");
__static_yoink("_idt");
__static_yoink("_AcpiMadtFlags");
__static_yoink("_AcpiBootFlags");
__static_yoink("EfiMain");
int main(int argc, char *argv[]) {
-1
View File
@@ -11,7 +11,6 @@
#include "libc/calls/struct/timespec.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/append.h"
#include "libc/stdio/stdio.h"
+10 -7
View File
@@ -14,7 +14,8 @@
#define _ASSERT_H
COSMOPOLITAN_C_START_
void __assert_fail(const char *, const char *, int) wontreturn relegated;
void __assert_fail(const char *, const char *, int);
void unassert(const char *, const char *, int);
#ifdef NDEBUG
#define assert(x) ((void)0)
@@ -31,12 +32,14 @@ void __assert_fail(const char *, const char *, int) wontreturn relegated;
#ifndef NDEBUG
#define unassert(x) __assert_macro(x, #x)
#define npassert(x) __assert_macro(x, #x)
#define __assert_macro(x, s) \
({ \
if (__builtin_expect(!(x), 0)) { \
__assert_fail(s, __FILE__, __LINE__); \
} \
(void)0; \
#define __assert_macro(x, s) \
({ \
if (__builtin_expect(!(x), 0)) { \
(unassert)(s, __FILE__, __LINE__); \
__asm__("nop"); \
__builtin_unreachable(); \
} \
(void)0; \
})
#else
#define npassert(x) \
@@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ Copyright 2023 Justine Alexandra Roberts Tunney │
│ │
│ Permission to use, copy, modify, and/or distribute this software for │
│ any purpose with or without fee is hereby granted, provided that the │
@@ -16,24 +16,13 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/fmt/conv.h"
#include "libc/fmt/itoa.h"
#include "libc/limits.h"
#include "libc/mem/reverse.internal.h"
#include "libc/calls/struct/cpuset.h"
#include "libc/intrin/popcnt.h"
/**
* Converts unsigned 64-bit integer to octal string.
* @param a needs at least 24 bytes
* @return bytes written w/o nul
*/
dontinline size_t uint64toarray_radix8(uint64_t i, char a[hasatleast 24]) {
size_t j;
j = 0;
do {
a[j++] = i % 8 + '0';
i /= 8;
} while (i > 0);
a[j] = '\0';
reverse(a, j);
return j;
int CPU_COUNT_S(size_t size, const cpu_set_t *set) {
int i, c = 0;
for (i = 0; i < size / sizeof(*set->__bits); i++) {
c += popcnt(set->__bits[i]);
}
return c;
}
+3 -2
View File
@@ -23,6 +23,7 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/describebacktrace.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
/**
* Handles assert() failure.
@@ -31,8 +32,8 @@ void __assert_fail(const char *expr, const char *file, int line) {
char ibuf[12];
sigset_t m = __sig_block();
FormatInt32(ibuf, line);
tinyprint(2, file, ":", ibuf, ": assert(", expr, ") failed (",
program_invocation_short_name, " ",
tinyprint(2, file, ":", ibuf, ": \e[31;1massert(", expr,
") failed\e[0m (cosmoaddr2line ", FindDebugBinary(), " ",
DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL);
__sig_unblock(m);
abort();
+10 -7
View File
@@ -158,6 +158,8 @@ int setregid(unsigned, unsigned);
int setreuid(unsigned, unsigned);
int setsid(void);
int setuid(unsigned);
int shm_open(const char *, int, unsigned);
int shm_unlink(const char *);
int sigignore(int);
int siginterrupt(int, int);
int symlink(const char *, const char *);
@@ -166,7 +168,7 @@ int truncate(const char *, int64_t);
int ttyname_r(int, char *, size_t);
int unlink(const char *);
int unlinkat(int, const char *, int);
int usleep(unsigned);
int usleep(uint64_t);
int vfork(void) returnstwice;
int wait(int *);
int waitpid(int, int *, int);
@@ -199,7 +201,6 @@ int setresuid(unsigned, unsigned, unsigned);
int getresgid(unsigned *, unsigned *, unsigned *);
int getresuid(unsigned *, unsigned *, unsigned *);
char *get_current_dir_name(void) __wur;
int sync_file_range(int, int64_t, int64_t, unsigned);
ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned);
int memfd_create(const char *, unsigned int);
int execvpe(const char *, char *const[], char *const[]);
@@ -211,36 +212,38 @@ int madvise(void *, uint64_t, int);
#ifdef _COSMO_SOURCE
bool32 fdexists(int);
bool32 fileexists(const char *);
bool32 ischardev(int);
bool32 isdirectory(const char *);
bool32 isexecutable(const char *);
bool32 isregularfile(const char *);
bool32 issymlink(const char *);
bool32 ischardev(int);
char *commandv(const char *, char *, size_t);
int __getcwd(char *, size_t);
int clone(void *, void *, size_t, int, void *, void *, void *, void *);
int fadvise(int, uint64_t, uint64_t, int);
int makedirs(const char *, unsigned);
int pivot_root(const char *, const char *);
int pledge(const char *, const char *);
int seccomp(unsigned, unsigned, void *);
int sys_iopl(int);
int sys_ioprio_get(int, int);
int sys_ioprio_set(int, int, int);
int sys_mlock(const void *, size_t);
int sys_mlock2(const void *, size_t, int);
int sys_mlockall(int);
int sys_personality(uint64_t);
int sys_munlock(const void *, size_t);
int sys_munlockall(void);
int sys_personality(uint64_t);
int sys_ptrace(int, ...);
int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
int sys_ioprio_get(int, int);
int sys_ioprio_set(int, int, int);
int tmpfd(void);
int touch(const char *, unsigned);
int unveil(const char *, const char *);
long ptrace(int, ...);
int fadvise(int, uint64_t, uint64_t, int);
ssize_t copyfd(int, int, size_t);
ssize_t readansi(int, char *, size_t);
ssize_t tinyprint(int, const char *, ...) nullterminated();
void shm_path_np(const char *, char[hasatleast 78]);
#endif /* _COSMO_SOURCE */
int __wifstopped(int) pureconst;
+4 -2
View File
@@ -99,8 +99,6 @@ o//libc/calls/prctl.o: \
# we always want -Os because:
# it's early runtime mandatory and quite huge without it
o//libc/calls/getcwd.greg.o \
o//libc/calls/getcwd-nt.greg.o \
o//libc/calls/getcwd-xnu.greg.o \
o//libc/calls/statfs2cosmo.o: private \
CFLAGS += \
-Os
@@ -145,6 +143,10 @@ o/$(MODE)/libc/calls/tailcontext.o: libc/calls/tailcontext.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/calls/stackjump.o: libc/calls/stackjump.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/calls/sched_yield.o: libc/calls/sched_yield.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/calls/uname.o: libc/integral/normalize.inc
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
@@ -17,14 +17,11 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/posixthread.internal.h"
#ifdef __x86_64__
textwindows int _check_cancel(void) {
int _check_cancel(void) {
if (_weaken(_pthread_cancel_ack) && //
_pthread_self() && !(_pthread_self()->pt_flags & PT_NOCANCEL) &&
atomic_load_explicit(&_pthread_self()->pt_canceled,
@@ -33,15 +30,3 @@ textwindows int _check_cancel(void) {
}
return 0;
}
textwindows int _check_signal(bool restartable) {
int status;
if (_check_cancel() == -1) return -1;
if (!_weaken(__sig_check)) return 0;
if (!(status = _weaken(__sig_check)())) return 0;
if (_check_cancel() == -1) return -1;
if (status == 2 && restartable) return 0;
return eintr();
}
#endif /* __x86_64__ */
+35
View File
@@ -0,0 +1,35 @@
/*-*- 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 2023 Justine Alexandra Roberts Tunney │
│ │
│ Permission to use, copy, modify, and/or distribute this software for │
│ any purpose with or without fee is hereby granted, provided that the │
│ above copyright notice and this permission notice appear in all copies. │
│ │
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#ifdef __x86_64__
textwindows int _check_signal(bool restartable) {
int status;
if (_check_cancel() == -1) return -1;
if (!_weaken(__sig_check)) return 0;
if (!(status = _weaken(__sig_check)())) return 0;
if (_check_cancel() == -1) return -1;
if (status == 2 && restartable) return 0;
return eintr();
}
#endif /* __x86_64__ */
+5 -1
View File
@@ -40,7 +40,11 @@ static dontinline int __clk_tck_init(void) {
size_t len;
struct clockinfo_netbsd clock;
if (IsWindows()) {
x = 1000;
// MSVC defines CLK_TCK as 1000 but 1ms is obviously not the
// scheduling quantum Windows actually uses. If we define it
// as 30 rather than 1000, then clock_nanosleep is much more
// accurately able to predict the duration of its busy waits
x = 30;
} else if (IsXnu() || IsOpenbsd()) {
x = 100;
} else if (IsFreebsd()) {
+12 -6
View File
@@ -25,14 +25,20 @@
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
static int sys_clock_getres_poly(int clock, struct timespec *ts, int64_t real) {
static int sys_clock_getres_poly(int clock, struct timespec *ts, int64_t real,
int64_t real_coarse, int64_t boot) {
ts->tv_sec = 0;
if (clock == CLOCK_REALTIME) {
ts->tv_sec = 0;
ts->tv_nsec = real;
return 0;
} else if (clock == CLOCK_REALTIME_COARSE) {
ts->tv_nsec = real_coarse;
return 0;
} else if (clock == CLOCK_MONOTONIC) {
ts->tv_sec = 0;
ts->tv_nsec = 1;
ts->tv_nsec = 10;
return 0;
} else if (clock == CLOCK_BOOTTIME) {
ts->tv_nsec = boot;
return 0;
} else {
return einval();
@@ -40,11 +46,11 @@ static int sys_clock_getres_poly(int clock, struct timespec *ts, int64_t real) {
}
static int sys_clock_getres_nt(int clock, struct timespec *ts) {
return sys_clock_getres_poly(clock, ts, 100);
return sys_clock_getres_poly(clock, ts, 100, 1000000, 1000000);
}
static int sys_clock_getres_xnu(int clock, struct timespec *ts) {
return sys_clock_getres_poly(clock, ts, 1000);
return sys_clock_getres_poly(clock, ts, 1000, 1000, 1000);
}
/**
+50 -15
View File
@@ -18,26 +18,61 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/wintime.internal.h"
#include "libc/nt/struct/filetime.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/consts/clock.h"
#define _CLOCK_REALTIME 0
#define _CLOCK_MONOTONIC 1
#define _CLOCK_REALTIME_COARSE 2
#define _CLOCK_BOOTTIME 3
static struct {
uint64_t base;
uint64_t freq;
} g_winclock;
textwindows int sys_clock_gettime_nt(int clock, struct timespec *ts) {
uint64_t t;
struct NtFileTime ft;
if (clock == CLOCK_REALTIME) {
if (!ts) return 0;
GetSystemTimeAsFileTime(&ft);
*ts = FileTimeToTimeSpec(ft);
return 0;
} else if (clock == CLOCK_MONOTONIC) {
if (!ts) return 0;
return sys_clock_gettime_mono(ts);
} else if (clock == CLOCK_BOOTTIME) {
if (ts) *ts = timespec_frommillis(GetTickCount64());
return 0;
} else {
return -EINVAL;
switch (clock) {
case _CLOCK_REALTIME:
if (ts) {
GetSystemTimePreciseAsFileTime(&ft);
*ts = FileTimeToTimeSpec(ft);
}
return 0;
case _CLOCK_REALTIME_COARSE:
if (ts) {
GetSystemTimeAsFileTime(&ft);
*ts = FileTimeToTimeSpec(ft);
}
return 0;
case _CLOCK_MONOTONIC:
if (ts) {
QueryPerformanceCounter(&t);
t = ((t - g_winclock.base) * 1000000000) / g_winclock.freq;
*ts = timespec_fromnanos(t);
}
return 0;
case _CLOCK_BOOTTIME:
if (ts) {
*ts = timespec_frommillis(GetTickCount64());
}
return 0;
default:
return -EINVAL;
}
}
static textstartup void winclock_init() {
if (IsWindows()) {
QueryPerformanceCounter(&g_winclock.base);
QueryPerformanceFrequency(&g_winclock.freq);
}
}
const void *const winclock_ctor[] initarray = {
winclock_init,
};
+13 -3
View File
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/cp.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/dce.h"
@@ -27,6 +28,7 @@
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/clktck.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/timer.h"
#include "libc/sysv/errfuns.h"
@@ -108,9 +110,17 @@ static int cosmo_clock_nanosleep(int clock, int flags,
}
// spin through final scheduling quantum
do unassert(!clock_gettime(time_clock, &now));
while (timespec_cmp(now, deadline) < 0);
return 0;
int rc = 0;
ftrace_enabled(-1);
do {
if (_check_cancel()) {
rc = -1;
break;
}
unassert(!clock_gettime(time_clock, &now));
} while (timespec_cmp(now, deadline) < 0);
ftrace_enabled(+1);
return rc;
}
/**
+4 -3
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
@@ -37,13 +38,12 @@
* @raise EBADF on OpenBSD if `first` is greater than highest fd
* @raise EINVAL if flags are bad or first is greater than last
* @raise EMFILE if a weird race condition happens on Linux
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EINTR possibly on OpenBSD
* @raise ENOMEM on Linux maybe
*/
int closefrom(int first) {
int rc, err;
(void)err;
int rc;
BLOCK_CANCELATION;
if (first < 0) {
// consistent with openbsd
// freebsd allows this but it's dangerous
@@ -58,6 +58,7 @@ int closefrom(int first) {
} else {
rc = enosys();
}
ALLOW_CANCELATION;
STRACE("closefrom(%d) → %d% m", first, rc);
return rc;
}
+1 -1
View File
@@ -44,7 +44,7 @@ ssize_t copyfd(int in, int out, size_t n) {
if (dw != dr) {
// POSIX requires atomic IO up to PIPE_BUF
// The minimum permissible PIPE_BUF is 512
abort();
notpossible;
}
}
return i;
+3 -5
View File
@@ -91,11 +91,9 @@ textwindows int GetNtOpenFlags(int flags, int mode, uint32_t *out_perm,
// Be as generous as possible in sharing file access. Not doing this
// you'll quickly find yourself no longer able to administer Windows
if (flags & _O_EXCL) {
share = kNtFileShareExclusive;
} else {
share = kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
}
// and we need this to be the case even in O_EXCL mode otherwise the
// shm_open_test.c won't behave consistently on Windows like on UNIX
share = kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
// These POSIX to WIN32 mappings are relatively straightforward.
if (flags & _O_EXCL) {
+2
View File
@@ -18,6 +18,8 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/limits.h"
#include "libc/str/str.h"
textwindows int sys_faccessat_nt(int dirfd, const char *path, int mode,
uint32_t flags) {
+2
View File
@@ -17,8 +17,10 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/limits.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
textwindows int sys_fchmodat_nt(int dirfd, const char *path, uint32_t mode,
int flags) {
+6 -1
View File
@@ -29,6 +29,11 @@
/**
* Blocks until kernel flushes non-metadata buffers for fd to disk.
*
* NOTE: For `IsXnu()` it's recommended that `fcntl(F_FULLFSYNC)` be
* favored instead of this function, and if that fails, the fallback
* path should call `fsync()` see the SQLite codebase. In the future
* Cosmopolitan might do this automatically.
*
* @return 0 on success, or -1 w/ errno
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EROFS if `fd` is on a read-only filesystem e.g. /zip
@@ -37,8 +42,8 @@
* @raise EBADF if `fd` isn't an open file
* @raise EINTR if signal was delivered
* @raise EIO if an i/o error happened
* @see sync(), fsync(), sync_file_range()
* @see __nosync to secretly disable
* @see sync(), fsync()
* @cancelationpoint
* @asyncsignalsafe
*/
@@ -20,13 +20,17 @@
#include "libc/atomic.h"
#include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/cosmo.h"
#include "libc/dce.h"
#include "libc/elf/def.h"
#include "libc/elf/tinyelf.internal.h"
#include "libc/errno.h"
#include "libc/intrin/bits.h"
#include "libc/macros.internal.h"
#include "libc/intrin/directmap.internal.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
@@ -38,24 +42,57 @@ static struct {
char buf[PATH_MAX];
} g_comdbg;
static const char *kDbgExts[] = {
".dbg",
".com.dbg",
#ifdef __aarch64__
".aarch64.elf",
#elif defined(__powerpc64__)
".ppc64.elf",
#endif
};
static int GetElfMachine(void) {
#ifdef __x86_64__
return EM_NEXGEN32E;
#elif defined(__aarch64__)
return EM_AARCH64;
#elif defined(__powerpc64__)
return EM_PPC64;
#elif defined(__riscv)
return EM_RISCV;
#elif defined(__s390x__)
return EM_S390;
#else
#error "unsupported architecture"
#endif
}
static bool IsMyDebugBinary(const char *path) {
void *map;
int64_t size;
uintptr_t value;
bool res = false;
int fd, e = errno;
struct DirectMap dm;
BLOCK_CANCELATION;
if ((fd = open(path, O_RDONLY | O_CLOEXEC, 0)) != -1) {
// sanity test that this .com.dbg file (1) is an elf image, and (2)
// contains the same number of bytes of code as our .com executable
// which is currently running in memory.
if ((size = lseek(fd, 0, SEEK_END)) != -1 &&
(map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) {
if (READ32LE((char *)map) == READ32LE("\177ELF") &&
GetElfSymbolValue(map, "_etext", &value)) {
(dm = sys_mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)).addr !=
MAP_FAILED) {
if (READ32LE((char *)dm.addr) == READ32LE("\177ELF") &&
((Elf64_Ehdr *)dm.addr)->e_machine == GetElfMachine() &&
GetElfSymbolValue(dm.addr, "_etext", &value)) {
res = !_etext || value == (uintptr_t)_etext;
}
munmap(map, size);
if (!IsWindows()) {
sys_munmap(dm.addr, size);
} else {
CloseHandle(dm.maphandle);
UnmapViewOfFile(dm.addr);
}
}
close(fd);
}
@@ -65,20 +102,21 @@ static bool IsMyDebugBinary(const char *path) {
}
static void FindDebugBinaryInit(void) {
char *p = GetProgramExecutableName();
size_t n = strlen(p);
if ((n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) ||
IsMyDebugBinary(p)) {
g_comdbg.res = p;
} else if (n + 4 < ARRAYLEN(g_comdbg.buf)) {
mempcpy(mempcpy(g_comdbg.buf, p, n), ".dbg", 5);
const char *comdbg;
if ((comdbg = getenv("COMDBG")) && IsMyDebugBinary(comdbg)) {
g_comdbg.res = comdbg;
return;
}
char *prog = GetProgramExecutableName();
for (int i = 0; i < ARRAYLEN(kDbgExts); ++i) {
strlcpy(g_comdbg.buf, prog, sizeof(g_comdbg.buf));
strlcat(g_comdbg.buf, kDbgExts[i], sizeof(g_comdbg.buf));
if (IsMyDebugBinary(g_comdbg.buf)) {
g_comdbg.res = g_comdbg.buf;
return;
}
}
if (!g_comdbg.res) {
g_comdbg.res = getenv("COMDBG");
}
g_comdbg.res = prog;
}
/**
+1 -1
View File
@@ -37,8 +37,8 @@
* @raise EBADF if `fd` isn't an open file
* @raise EINTR if signal was delivered
* @raise EIO if an i/o error happened
* @see fdatasync(), sync_file_range()
* @see __nosync to secretly disable
* @see fdatasync()
* @cancelationpoint
* @asyncsignalsafe
*/
-6
View File
@@ -20,12 +20,6 @@
// Gets machine state.
//
// This function goes 14x slower if sigaction() has ever been used to
// install a signal handling function. If you don't care about signal
// safety and just want fast fibers, then you may override the global
// variable `__interruptible` to disable the sigprocmask() calls, for
// pure userspace context switching.
//
// @return 0 on success, or -1 w/ errno
// @see makecontext()
// @see swapcontext()
-84
View File
@@ -1,84 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │
│ Permission to use, copy, modify, and/or distribute this software for │
│ any purpose with or without fee is hereby granted, provided that the │
│ above copyright notice and this permission notice appear in all copies. │
│ │
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/str/utf16.h"
#include "libc/sysv/errfuns.h"
textwindows char *sys_getcwd_nt(char *buf, size_t size) {
uint64_t w;
wint_t x, y;
uint32_t n, i, j;
char16_t p[PATH_MAX];
if ((n = GetCurrentDirectory(ARRAYLEN(p), p))) {
if (4 + n + 1 <= size && 4 + n + 1 <= ARRAYLEN(p)) {
tprecode16to8(buf, size, p);
i = 0;
j = 0;
if (n >= 3 && isalpha(p[0]) && p[1] == ':' && p[2] == '\\') {
// turn c:\... into \c\...
p[1] = p[0];
p[0] = '\\';
} else if (n >= 7 && p[0] == '\\' && p[1] == '\\' && p[2] == '?' &&
p[3] == '\\' && isalpha(p[4]) && p[5] == ':' && p[6] == '\\') {
// turn \\?\c:\... into \c\...
buf[j++] = '/';
buf[j++] = p[4];
buf[j++] = '/';
i += 7;
}
while (i < n) {
x = p[i++] & 0xffff;
if (!IsUcs2(x)) {
if (i < n) {
y = p[i++] & 0xffff;
x = MergeUtf16(x, y);
} else {
x = 0xfffd;
}
}
if (x < 0200) {
if (x == '\\') {
x = '/';
}
w = x;
} else {
w = tpenc(x);
}
do {
if (j < size) {
buf[j++] = w;
}
w >>= 8;
} while (w);
}
if (j < size) {
buf[j] = 0;
return buf;
}
}
erange();
return NULL;
} else {
__winerr();
return NULL;
}
}
+137 -64
View File
@@ -16,81 +16,154 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/log/backtrace.internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/files.h"
#include "libc/stdio/sysparam.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
/**
* Returns current working directory, e.g.
*
* const char *dirname = gc(getcwd(0,0)); // if malloc is linked
* const char *dirname = getcwd(alloca(PATH_MAX),PATH_MAX);
*
* @param buf is where UTF-8 NUL-terminated path string gets written,
* which may be NULL to ask this function to malloc a buffer
* @param size is number of bytes available in buf, e.g. PATH_MAX+1,
* which may be 0 if buf is NULL
* @return buf containing system-normative path or NULL w/ errno
* @error ERANGE, EINVAL, ENOMEM
*/
char *getcwd(char *buf, size_t size) {
char *p, *r;
if (buf) {
p = buf;
if (!size) {
einval();
STRACE("getcwd(%p, %'zu) %m", buf, size);
return 0;
}
} else if (_weaken(malloc)) {
unassert(!__vforked);
if (!size) size = PATH_MAX;
if (!(p = _weaken(malloc)(size))) {
STRACE("getcwd(%p, %'zu) %m", buf, size);
return 0;
}
} else {
einval();
STRACE("getcwd() needs buf≠0 or __static_yoink(\"malloc\")");
return 0;
}
*p = '\0';
if (!IsWindows()) {
if (IsMetal()) {
r = size >= 5 ? strcpy(p, "/zip") : 0;
} else if (IsXnu()) {
r = sys_getcwd_xnu(p, size);
} else if (sys_getcwd(p, size) != (void *)-1) {
r = p;
} else {
r = 0;
}
} else {
r = sys_getcwd_nt(p, size);
}
if (!buf) {
if (!r) {
if (_weaken(free)) {
_weaken(free)(p);
}
} else {
if (_weaken(realloc)) {
if ((p = _weaken(realloc)(r, strlen(r) + 1))) {
r = p;
#define XNU_F_GETPATH 50
#define XNU_MAXPATHLEN 1024
static int sys_getcwd_xnu(char *res, size_t size) {
int fd, len, rc = -1;
union metastat st[2];
char buf[XNU_MAXPATHLEN];
if ((fd = __sys_openat_nc(AT_FDCWD, ".", O_RDONLY | O_DIRECTORY, 0)) != -1) {
if (__sys_fstat(fd, &st[0]) != -1) {
if (st[0].xnu.st_dev && st[0].xnu.st_ino) {
if (__sys_fcntl(fd, XNU_F_GETPATH, (uintptr_t)buf) != -1) {
if (__sys_fstatat(AT_FDCWD, buf, &st[1], 0) != -1) {
if (st[0].xnu.st_dev == st[1].xnu.st_dev &&
st[0].xnu.st_ino == st[1].xnu.st_ino) {
if ((len = strlen(buf)) < size) {
memcpy(res, buf, (rc = len + 1));
} else {
erange();
}
} else {
einval();
}
}
}
} else {
einval();
}
}
sys_close(fd);
}
STRACE("getcwd(%p, %'zu) → %#s", buf, size, r);
return r;
return rc;
}
static int sys_getcwd_metal(char *buf, size_t size) {
if (size >= 5) {
strcpy(buf, "/zip");
return 5;
} else {
return erange();
}
}
static inline int IsAlpha(int c) {
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}
static dontinline textwindows int sys_getcwd_nt(char *buf, size_t size) {
// get current directory from the system
char16_t p16[PATH_MAX];
uint32_t n = GetCurrentDirectory(PATH_MAX, p16);
if (!n) return eacces(); // system call failed
if (n >= PATH_MAX) return erange(); // not enough room?!?
// convert utf-16 to utf-8
// we can't modify `buf` until we're certain of success
char p8[PATH_MAX], *p = p8;
n = tprecode16to8(p, PATH_MAX, p16).ax;
if (n >= PATH_MAX) return erange(); // utf-8 explosion
// turn \\?\c:\... into c:\...
if (p[0] == '\\' && //
p[1] == '\\' && //
p[2] == '?' && //
p[3] == '\\' && //
IsAlpha(p[4]) && //
p[5] == ':' && //
p[6] == '\\') {
p += 4;
n -= 4;
}
// turn c:\... into \c\...
if (IsAlpha(p[0]) && //
p[1] == ':' && //
p[2] == '\\') {
p[1] = p[0];
p[0] = '\\';
}
// we now know the final length
// check if the user supplied a buffer large enough
if (n >= size) {
return erange();
}
// copy bytes converting backslashes to slash
for (int i = 0; i < n; ++i) {
int c = p[i];
if (c == '\\') {
c = '/';
}
buf[i] = c;
}
// return number of bytes including nul
buf[n++] = 0;
return n;
}
/**
* Returns current working directory.
*
* Cosmo provides this function to address the shortcomings of getcwd().
* First, this function doesn't link malloc(). Secondly, this offers the
* Linux and NetBSD's getcwd() API across platforms since it's the best.
*
* @param buf receives utf-8 path and isn't modified on error
* @param size is byte capacity of `buf`
* @return bytes copied including nul on success, or -1 w/ errno
* @raise EACCES if the current directory path couldn't be accessed
* @raise ERANGE if `size` wasn't big enough for path and nul byte
* @raise EFAULT if `buf` points to invalid memory
*/
int __getcwd(char *buf, size_t size) {
int rc;
if (IsLinux() || IsNetbsd()) {
rc = sys_getcwd(buf, size);
} else if (IsXnu()) {
rc = sys_getcwd_xnu(buf, size);
} else if (IsWindows()) {
rc = sys_getcwd_nt(buf, size);
} else if (IsFreebsd() || IsOpenbsd()) {
if (sys_getcwd(buf, size) != -1) {
rc = strlen(buf) + 1;
} else if (SupportsFreebsd() && (errno == ENOMEM || errno == EINVAL)) {
rc = erange();
} else {
rc = -1;
}
} else {
rc = sys_getcwd_metal(buf, size);
}
STRACE("getcwd([%#hhs], %'zu) → %d% m", rc != -1 ? buf : "n/a", size, rc);
return rc;
}
+3 -2
View File
@@ -86,8 +86,9 @@ static inline void InitProgramExecutableNameImpl(void) {
if (q[0] == '.' && q[1] == '/') {
q += 2;
}
if (getcwd(p, e - p - 1 - 4)) { // for / and .com
while (*p) ++p;
int got = __getcwd(p, e - p - 1 - 4); // for / and .com
if (got != -1) {
p += got - 1;
*p++ = '/';
}
}
+1
View File
@@ -23,6 +23,7 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/consts/rlimit.h"
+7 -4
View File
@@ -5,6 +5,7 @@
#include "libc/calls/struct/sigval.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/stdbool.h"
#define kSigactionMinRva 8 /* >SIG_{ERR,DFL,IGN,...} */
@@ -31,10 +32,6 @@ int64_t GetConsoleOutputHandle(void);
int IsWindowsExecutable(int64_t, const char16_t *);
void InterceptTerminalCommands(const char *, size_t);
forceinline int64_t __getfdhandleactual(int fd) {
return g_fds.p[fd].handle;
}
forceinline bool __isfdopen(int fd) {
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
}
@@ -50,6 +47,12 @@ int _park_norestart(uint32_t, uint64_t);
int _park_restartable(uint32_t, uint64_t);
int sys_openat_metal(int, const char *, int, unsigned);
#ifdef __x86_64__
bool __iswsl1(void);
#else
#define __iswsl1() false
#endif
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_ */
+1 -1
View File
@@ -75,7 +75,7 @@ static int ioctl_default(int fd, unsigned long request, void *arg) {
return sys_ioctl(fd, request, arg);
} else if (__isfdopen(fd)) {
if (g_fds.p[fd].kind == kFdSocket) {
handle = __getfdhandleactual(fd);
handle = g_fds.p[fd].handle;
if ((rc = _weaken(__sys_ioctlsocket_nt)(handle, request, arg)) != -1) {
return rc;
} else {
+2 -1
View File
@@ -25,5 +25,6 @@
bool IsApeLoadable(char buf[8]) {
return READ32LE(buf) == READ32LE("\177ELF") ||
READ64LE(buf) == READ64LE("MZqFpD='") ||
READ64LE(buf) == READ64LE("JTqFpD='");
READ64LE(buf) == READ64LE("jartsr='") ||
READ64LE(buf) == READ64LE("APEDBG='");
}
+1 -1
View File
@@ -56,6 +56,6 @@ bool32 ischardev(int fd) {
} else {
return __isfdkind(fd, kFdConsole) || __isfdkind(fd, kFdDevNull) ||
(__isfdkind(fd, kFdFile) &&
GetFileType(__getfdhandleactual(fd)) == kNtFileTypeChar);
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
}
}
+2
View File
@@ -18,9 +18,11 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/limits.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/str/str.h"
textwindows int sys_linkat_nt(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) {
+2
View File
@@ -30,6 +30,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/metalfile.internal.h"
#include "libc/intrin/directmap.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/weaken.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
@@ -74,6 +75,7 @@ textstartup void InitializeMetalFile(void) {
memcpy(copied_base, (void *)(BANE + IMAGE_BASE_PHYSICAL), size);
__ape_com_base = copied_base;
__ape_com_size = size;
KINFOF("%s @ %p,+%#zx", APE_COM_NAME, copied_base, size);
}
}
+2 -2
View File
@@ -27,12 +27,12 @@
#include "libc/macros.internal.h"
#include "libc/calls/metalfile.internal.h"
.init.start 101,_init_metalfile
.init.start 102,_init_metalfile
push %rdi
push %rsi
call InitializeMetalFile
pop %rsi
pop %rdi
.init.end 101,_init_metalfile
.init.end 102,_init_metalfile
APE_COM_NAME:
.endobj APE_COM_NAME,globl,hidden
+1
View File
@@ -19,6 +19,7 @@
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
textwindows int sys_mkdirat_nt(int dirfd, const char *path, uint32_t mode) {
char16_t path16[PATH_MAX];
+26 -25
View File
@@ -16,11 +16,17 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/mem/mem.h"
#include "libc/nt/files.h"
#include "libc/proc/ntspawn.h"
#include "libc/str/str.h"
#include "libc/str/thompike.h"
#include "libc/str/utf16.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#define APPEND(c) \
@@ -54,6 +60,12 @@ static inline int IsAlpha(int c) {
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}
static bool LooksLikeCosmoDrivePath(const char *s) {
return s[0] == '/' && //
IsAlpha(s[1]) && //
s[2] == '/';
}
// Converts System V argv to Windows-style command line.
//
// Escaping is performed and it's designed to round-trip with
@@ -68,20 +80,31 @@ static inline int IsAlpha(int c) {
// @see libc/runtime/getdosargv.c
// @asyncsignalsafe
textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
char *arg;
int slashes, n;
bool needsquote;
size_t i, j, k, s;
char argbuf[PATH_MAX];
for (k = i = 0; argv[i]; ++i) {
if (i) APPEND(u' ');
if ((needsquote = NeedsQuotes(argv[i]))) APPEND(u'"');
if (LooksLikeCosmoDrivePath(argv[i]) &&
strlcpy(argbuf, argv[i], PATH_MAX) < PATH_MAX) {
mungentpath(argbuf);
arg = argbuf;
} else {
arg = argv[i];
}
if ((needsquote = NeedsQuotes(arg))) {
APPEND(u'"');
}
for (slashes = j = 0;;) {
wint_t x = argv[i][j++] & 255;
wint_t x = arg[j++] & 255;
if (x >= 0300) {
n = ThomPikeLen(x);
x = ThomPikeByte(x);
while (--n) {
wint_t y;
if ((y = argv[i][j++] & 255)) {
if ((y = arg[j++] & 255)) {
x = ThomPikeMerge(x, y);
} else {
x = 0;
@@ -90,28 +113,6 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
}
}
if (!x) break;
if (x == '/' || x == '\\') {
if (!i) {
// turn / into \ for first argv[i]
x = '\\';
// turn \c\... into c:\ for first argv[i]
if (k == 2 && IsAlpha(cmdline[1]) && cmdline[0] == '\\') {
cmdline[0] = cmdline[1];
cmdline[1] = ':';
}
} else {
// turn stuff like `less /c/...`
// into `less c:/...`
// turn stuff like `more <"/c/..."`
// into `more <"c:/..."`
if (k > 3 && IsAlpha(cmdline[k - 1]) &&
(cmdline[k - 2] == '/' || cmdline[k - 2] == '\\') &&
(cmdline[k - 3] == '"' || cmdline[k - 3] == ' ')) {
cmdline[k - 2] = cmdline[k - 1];
cmdline[k - 1] = ':';
}
}
}
if (x == '\\') {
++slashes;
} else if (x == '"') {
Loaded 100 of 742 files, more files were not shown because too many files have changed in this diff. Show more