Compare commits

..
221 Commits
Author SHA1 Message Date
Justine Tunney 3093f0e467 Release Cosmopolitan v3.4.0 2024-06-05 03:07:03 -07:00
Justine Tunney 3609f65de3 Make malloc() go 200x faster
If pthread_create() is linked into the binary, then the cosmo runtime
will create an independent dlmalloc arena for each core. Whenever the
malloc() function is used it will index `g_heaps[sched_getcpu() / 2]`
to find the arena with the greatest hyperthread / numa locality. This
may be configured via an environment variable. For example if you say
`export COSMOPOLITAN_HEAP_COUNT=1` then you can restore the old ways.
Your process may be configured to have anywhere between 1 - 128 heaps

We need this revision because it makes multithreaded C++ applications
faster. For example, an HTTP server I'm working on that makes extreme
use of the STL went from 16k to 2000k requests per second, after this
change was made. To understand why, try out the malloc_test benchmark
which calls malloc() + realloc() in a loop across many threads, which
sees a a 250x improvement in process clock time and 200x on wall time

The tradeoff is this adds ~25ns of latency to individual malloc calls
compared to MODE=tiny, once the cosmo runtime has transitioned into a
fully multi-threaded state. If you don't need malloc() to be scalable
then cosmo provides many options for you. For starters the heap count
variable above can be set to put the process back in single heap mode
plus you can go even faster still, if you include tinymalloc.inc like
many of the programs in tool/build/.. are already doing since that'll
shave tens of kb off your binary footprint too. Theres also MODE=tiny
which is configured to use just 1 plain old dlmalloc arena by default

Another tradeoff is we need more memory now (except in MODE=tiny), to
track the provenance of memory allocation. This is so allocations can
be freely shared across threads, and because OSes can reschedule code
to different CPUs at any time.
2024-06-05 02:02:14 -07:00
Justine Tunney 9906f299bb Refactor and improve CTL and other code 2024-06-04 05:45:48 -07:00
Justine Tunney 1d8f37a2f0 Fix the MODE=tiny builds 2024-06-03 10:36:38 -07:00
Justine Tunney e677460d14 Delete .vscode folder
It hasn't been maintained in years. I'm tired of the root level of our
project having an advertisement for Microsoft Visual Studio Code. Your
preferred editor should be Emacs or Vim.
2024-06-03 09:40:45 -07:00
Justine Tunney 4937843f70 Introduce Cosmopolitan Templates Library (CTL) 2024-06-03 09:21:59 -07:00
Justine Tunney b003888696 Make __demangle() heap 10% more compact 2024-06-02 16:18:55 -07:00
Justine Tunney 2ca491dc56 Write more __demangle() tests 2024-06-02 07:37:15 -07:00
Justine Tunney 9aa353d88b Document __demangle() and fix a const func ptr bug 2024-06-02 04:15:48 -07:00
Justine Tunney c67faf61df Delete some unintentional code 2024-06-01 20:36:58 -07:00
Justine Tunney 165c6b37e2 Add C++ demangling to privileged runtime
Cosmo will now print C++ symbols correctly in --ftrace logs and
backtraces. Doing this required reducing the memory requirement
of the __demangle() function by 3x. This was accomplished using
16-bit indices and 16-bit malloc granularity. That puts a limit
on the longest symbol we can successfully decode, which I think
would be around 6553 characters long, given a 65536-byte buffer
2024-06-01 20:10:58 -07:00
Jōshin dcd626edf8 Add .git-blame-ignore-revs
If you follow the directions in that file then git blame will ignore the
listed commits. A commit should only go in that file if its only changes
were to formatting, particularly on a large part of the codebase (like a
change to .clang-format getting applied to the repo.)

Cribbed from here:

https://www.stefanjudis.com/today-i-learned/how-to-exclude-commits-from-git-blame/
2024-06-01 20:10:48 -07:00
Jōshin f032b5570b Run clang-format (#1197) 2024-06-01 16:30:43 -04:00
Justine Tunney ea081b262c Add some noexcept annotations 2024-06-01 03:19:53 -07:00
Justine Tunney fae1c32267 Encode ±INFINITY as ±1e5000
The V8 behavior of encoding infinity as null doesn't make sense to me.
Using ±1e5000 is better, because JSON.parse decodes it as INFINITY and
the information is preserved. This could be a breaking change for some
2024-06-01 03:19:50 -07:00
Justine Tunney 9b6718ac99 Improve backtraces
We're now able to rewind the instruction pointer in x86 backtraces. This
helps ensure addr2line cannot print information about unrelated adjacent
code. I've restored -fno-schedule-insns2 in most cases because it really
does cause unpredictable breakage for backtraces.
2024-05-30 15:23:11 -07:00
Justine Tunney cd672e251f Improve crash signal reporting on Windows
This change fixes a bug where exiting a crash signal handler on Windows
after adding the signal to uc_sigmask, but not correcting the CPU state
would cause the signal handler to loop infinitely, causing process hang

Another issue is that very tiny programs, that don't link posix signals
would not have their SIGILL / SIGSEGV / etc. status reported to Cosmo's
bash shell when terminating on crash. That's fixed by a tiny handler in
WinMain() that knows how to map WIN32 crash codes to the POSIX flavors.
2024-05-30 14:04:10 -07:00
Justine Tunney 500a47bc2f Fix undefined behavior in unit test
Fixes #1194
2024-05-29 20:31:46 -07:00
Justine Tunney e4d25d68e4 Drop support for Windows 8
Microsoft caused some very gentle breakages for Cosmopolitan. They
removed the version information from the PEB which caused uname to
report WINDOWS 0.0.0. We should have called GetVersionExW but that
doesn't really exist anymore either. Windows policy is now to give
whatever version we used in ape/ape.S. Windows8 has been EOL since
2023-01-10 so lets avoid our modern executables being relegated to
legacy infrastructure. Requiring Windows 10+ going forward lets us
remove runtime compatibility bloat from the codebase. Further note
Cosmopolitan maintains a Windows Vista branch on GitHub, so anyone
preferring the older versions, can still have a future with Cosmo.

Another neat thing this fixes is UTF-8 support in the console. The
changes Microsoft made broke the if statement that enabled UTF8 in
terminals. This explains why bug reports had broken arrows. In the
future this should be less of an issue, since the PEB code is gone
which means we more strictly conform to only Microsoft's WIN32 API
2024-05-29 19:37:47 -07:00
Justine Tunney f31a98d50a Fix bug with realpath() on Windows 2024-05-29 18:47:01 -07:00
Justine Tunney 2816df59b2 Increase tinymalloc granularity 2024-05-29 18:26:01 -07:00
Justine Tunney a05ce3ad9d Support avx512f + vpclmulqdq crc32() acceleration
Cosmo's _Cz_crc32() function now goes 73 GiB/s on Threadripper. This
will significantly improve the performance of the PKZIP file format.
This algorithm is also used by apelink, to create deterministic ids.
2024-05-29 10:13:37 -07:00
Justine Tunney 7c8df05042 Improve -march=native micro-architecture detection 2024-05-29 10:12:49 -07:00
Justine Tunney 4c77acdfcf Add LoadZipArgs() to <cosmo.h> 2024-05-29 10:12:20 -07:00
Justine Tunney b74b974cfd Introduce #include <tinygetopt.h>
The normal getopt() function is bloated because it links printf(). This
change exports the original authentic bsd getopt function, that cosmo's
always used internally so cosmocc users don't need to include internals
2024-05-29 10:11:17 -07:00
Justine Tunney 07cef612c3 Make dlmalloc 2.4x faster for multithreading
This change adds a TLS freelist for small dynamic memory allocations.
Cosmopolitan's TIB is now 512 bytes in size. Single-threaded malloc()
performance isn't impacted by this, until pthread_create() is called.
Single-threaded programs may also want to consider using:

    #include "libc/mem/tinymalloc.inc"

Which will shave 30k off the executable size and sometimes go faster.
2024-05-28 11:18:34 -07:00
Justine Tunney deaef81463 Favor siginfo_t over struct siginfo 2024-05-28 02:34:17 -07:00
Justine Tunney c638eabfe0 Fix compiler warning 2024-05-27 02:23:24 -07:00
Justine Tunney 8e68384e15 Upgrade to 2022-era LLVM LIBCXX 2024-05-27 02:12:27 -07:00
Justine Tunney 2f4ca71f26 Release Cosmopolitan v3.3.10 2024-05-26 22:13:45 -07:00
Justine Tunney 07004ebf04 Upgrade to superconfigure z0.0.42 2024-05-26 22:12:25 -07:00
Justine Tunney 086d7006da Improve crash handler on XNU
This avoids an issue where a crash signal could cause the MacOS process
to freeze and consume all CPU rather than dying as it rightfully should
2024-05-26 18:42:09 -07:00
Gavin Hayes 0a51241f7a ntspawn: fix initializing NtStartupInfoEx (#1190) 2024-05-26 20:54:09 -04:00
Justine Tunney c68f6599e5 Fix definition of getpeername on FreeBSD
We were using the COMPAT magic number, which was recently removed.
2024-05-26 17:03:22 -07:00
Justine Tunney af3f62a71a Ensure io requests are always capped at 0x7ffff000
This gives us the Linux behavior across platforms.

Fixes #1189
2024-05-26 16:53:13 -07:00
Justine Tunney 6cf9b9e0fc Release Cosmopolitan v3.3.9 2024-05-26 15:28:03 -07:00
Justine Tunney 1d4b452839 Refactor some code 2024-05-26 06:03:50 -07:00
Justine Tunney c2db3b703a Introduce --timelog=FILE flag to GNU Make 2024-05-25 14:50:20 -07:00
Justine Tunney edb03b89d8 Make stdin unbuffered when appropriate 2024-05-25 07:57:13 -07:00
Justine Tunney 7724664b13 Release Cosmopolitan v3.3.8 2024-05-25 05:59:20 -07:00
Justine Tunney 1df4296208 Fix stdio for character device regression
Caused by ed93fc3dd7
2024-05-25 05:58:09 -07:00
Justine Tunney ce9aeb2aed Release Cosmopolitan v3.3.7 2024-05-24 19:37:21 -07:00
Justine Tunney ed93fc3dd7 Fix fread() with 2gb+ sizes 2024-05-24 19:28:23 -07:00
Justine Tunney 5f61d273e4 Add hwap constants to sys/auxv.h 2024-05-24 11:44:44 -07:00
Justine Tunney bf3531de81 Make crash reports reliable in multithreaded case 2024-05-24 11:44:44 -07:00
Justine Tunney 3b0ea2db4d Remove -fno-schedule-insns2
This was originally added when we were using the mcount hooking
technique, to prevent the nop from floating above the frame pointer
creation. Now we use a better codegen technique for hooking so it's no
longer needed to sacrifice performance by using this flag.
2024-05-24 11:44:44 -07:00
Justine Tunney f029375d39 Introduce MAP_HUGETLB 2024-05-24 11:44:44 -07:00
Justine Tunney 9b87dd2b87 Refactor some code 2024-05-24 11:44:44 -07:00
Jōshin 787b04f752 Run all BLAKE2B256 test vectors (#1185) 2024-05-24 10:59:23 -07:00
Jōshin 0768807935 Rename python -> python3 (closes #1144) (#1187)
When we removed the com suffix from ape binaries, we broke the build for
ape's python for any case-insensitive file system, i.e. Windows and XNU,
because there is a third_party/python/Python that gets mirrored in the o
directory with the python object files and clashes with the binary name.
This patch hacks around this by renaming the binary to "python3" so that
it no longer clashes with that directory.
2024-05-24 10:56:33 -07:00
Justine Tunney 0b59f01b43 Put confstr() in unistd.h
Fixes #1184
2024-05-21 15:35:06 -07:00
Justine Tunney cf70a44756 Support shebang on Windows
Fixes #1010
2024-05-20 22:11:42 -07:00
Justine Tunney a52792c59f Add some missing build dependencies 2024-05-20 17:23:25 -07:00
Jōshin 65c9b28e99 Fix buffer overflow in os.tmpname (#1180)
At least on macOS, `strlen(getenv("TMPDIR"))` is 50. We now allow a /tmp
that takes up to 120 or so bytes to spell. Instead of overflowing, we do
a bounds check and the function fails successfully on even longer /tmps.

Fixes #1108 (os.tmpname crashes redbean)
2024-05-20 03:46:27 -04:00
Jōshin 4292348707 Import libbsd readpassphrase (#1182)
Included from:

https://gitlab.freedesktop.org/libbsd/libbsd

At commit 04a24db27ad1572f766bad772cdd9c146e6d9cf0.
2024-05-20 03:37:30 -04:00
Jōshin 2ec20b6c4c Fix #922 (Duplicated line) (#1178) 2024-05-20 00:33:50 -07:00
Jōshin 47183551d6 Fix sleb64 (#1179)
Fixes #920
2024-05-20 00:33:17 -07:00
Jōshin 42891e82bb Fix #959 (typo in cosmocc --version) 2024-05-18 15:20:27 -07:00
Gavin Hayes 624119ea38 Fix NT accept/connect not initializing with SO_UPDATE_*_CONTEXT (#1164) 2024-05-17 02:45:30 -07:00
Justine Tunney 2f3c6e7cc3 Revert "Remove zlib namespacing (#1142)"
This reverts commit 5488f0b2ca which was a
good experiment to try, that didn't work out due to #1176

Fixes #1176
2024-05-14 20:45:23 -07:00
Justine Tunney 13b9ecd537 Remove outdated restriction on -Werror on cosmocc
This was a good idea back when we were only using it to build various
open source projects. However it no longer makes sense that many more
people are depending on cosmocc, to develop new software. Our tooling
shouldn't be making these kinds of decisions for the user.
2024-05-09 14:03:51 -07:00
Justine Tunney 6659981457 Release Cosmopolitan v3.3.6 2024-05-08 04:20:22 -07:00
Justine Tunney ae2a7ac844 Fix thread-local storage bugs on aarch64
This change fixes an issue where .tbss memory might not be initialized.
2024-05-08 04:20:22 -07:00
Justine Tunney 793393a341 Polyfill SA_RESETHAND on MacOS ARM64
This change solves the XNU crash loop mystery. Apple's documentation
claims to support this feature, but they only define the constant in
their header files. The kernel acknowledges thi SA_RESETHAND bit, by
clearing it from the sa_flags state, returns zero, and does nothing.
2024-05-08 04:20:22 -07:00
Justine Tunney 952b9009e8 Avoid crash looping on AARCH64 2024-05-08 04:20:22 -07:00
Jōshin 8f18b3ad65 Reapply apeinstall.sh binfmt flags (#1171)
7d31fc3 made it safe to register ape with the binfmt P flag. Older files
will still get their paths passed via argv[0] and everything should just
work. This also restores the F flag that was rolled back alongside the P
flag; this seems like a good idea to me now. It makes it so /usr/bin/ape
is kind of part of the kernel; simply replacing the file will not change
the loader used. The binfmt will have to be reregistered as well.

ape/apeinstall.sh will already nag you if there's an existing binfmt for
ape. It might be nice to make it actually replace the registration.

This reverts commit df648fb174.
2024-05-08 01:48:48 -04:00
Jōshin 56e0fd9d1d Use latest cosmocc (#1175) 2024-05-08 00:08:26 -04:00
Justine Tunney df68a6362b Release Cosmopolitan v3.3.5 2024-05-07 18:18:10 -07:00
Justine Tunney 19c81863a3 Improve crash backtrace reliability
We're now able to pretty print a C++ backtrace upon crashing in pretty
much any runtime execution scenario. The default pledge sandbox policy
on Linux is now to return EPERM. If you call pledge and have debugging
functions linked (e.g. GetSymbolTable) then the symbol table shall get
loaded before any security policy is put in place. This change updates
build/bootstrap/fixupobj too and fixes some other sneaky build errors.
2024-05-07 18:10:28 -07:00
Jōshin 7d31fc311a Loaders rewrite argv[0] for old binaries (#1170)
For this to work, a loader has to be able to tell the difference between
an ‘old’ and a ‘new’ binary. This is achieved via a repurposing of ELF’s
e_flags field. We previously tried to use the padding in e_ident for it,
but binutils was resetting it to zero in e.g. strip.

This introduces one new ELF flag for cosmopolitan binaries. It is called
`EF_APE_MODERN`. We choose 0x101ca75, "lol cat 5".

It should now be safe to install the ape loader binfmt registration with
the `P` flag.
2024-05-07 20:42:18 -04:00
Justine Tunney 57c0b065c8 Make old C++ demangler asynchronous signal safe
It's now possible to safely print C++ backtraces from signal handlers.
This symbol demangler doesn't need malloc, tls, or even static memory.
Additionally, this change makes it 2x faster and adds test cases. It's
almost as performant and accurate as the libcxxabi implementation now.
2024-05-07 03:41:33 -07:00
Justine Tunney a6ecbb747d Introduce libc/mem/tinymalloc.inc
This allocator shaves ~20kb off single-threaded tool programs and is
slightly faster than proper malloc for simple non-demanding programs
2024-05-07 03:19:49 -07:00
Justine Tunney 3bf95ae7ec Invent tool for renaming ELF object symbols 2024-05-07 03:19:49 -07:00
Justine Tunney 5fd7b07fac Improve AVX512 feature detection 2024-05-07 03:19:49 -07:00
Jōshin 317c8bc312 Update MODE=tiny time zone list (#1167)
I took one canonical IANA zone ID from each of the different colored
regions in this article, except those that do not observe DST and do
not have a Google office. See the "Time in Europe" Wikipedia article.

As to which canonical ID to use, this was somewhat arbitrary. Brussels
was obvious, as the de facto capital of the EU. For the rest, I mostly
just went with lexicographic ordering of the most recognizable options.

I've sorted the American zones. This Keeps the U.S. ones together but
does everything alphabetically otherwise. I've added the remaining
Canadian zones These have DST (and Newfoundland is off by a half-
hour from a UTC interval) so they cannot use Etc/. The Pacific/ zones
are sort of sorted. The Chathan Islands have been added. This is the
last of the zones I believe with a non-integer hour offset from UTC.
2024-05-06 16:48:49 -07:00
Jōshin 2a1f352622 Tell vim not to mess with ape.S 2024-05-06 15:36:35 -07:00
Justine Tunney 06d916b449 Add VirtualAlloc2 WIN32 API 2024-05-04 23:26:40 -07:00
Justine Tunney 9ea64725b6 Fix build error 2024-05-04 23:23:56 -07:00
Justine Tunney f9fc7eb49f Fix MODE=dbg build errors 2024-05-04 23:20:12 -07:00
Justine Tunney b0df6c1fce Implement proper time zone support
Cosmopolitan now supports 104 time zones. They're embedded inside any
binary that links the localtime() function. Doing so adds about 100kb
to the binary size. This change also gets time zones working properly
on Windows for the first time. It's not needed to have /etc/localtime
exist on Windows, since we can get this information from WIN32. We're
also now updated to the latest version of Paul Eggert's TZ library.
2024-05-04 23:06:37 -07:00
Justine Tunney d5ebb1fa5b Add MapViewOfFile3 WIN32 API 2024-05-04 12:25:41 -07:00
Justine Tunney 130fd66f9e Release Cosmopolitan v3.3.4 2024-05-03 09:25:02 -07:00
Justine Tunney 8a44f913ae Delete flaky tests
Signals are extremely difficult to unit test reliably. This is why
functions like sigsuspend() exist. When testing something else and
portably it becomes impossible without access to kernel internals.

OpenMP flakes in QEMU on one of my workstations. I don't think the
support is production worthy, because there's been issues on MacOS
additionally. It works great for every experiment I've used it for
though. However a flaky test is worse than no test at all. So it's
removed until someone takes an interest in productionizing it.
2024-05-03 09:11:04 -07:00
Gautham 5488f0b2ca Remove zlib namespacing (#1142)
We have an optimized version of zlib from the Chromium project.
We need it for a lot of our libc services. It would be nice to export
this to user applications if we can, since projects like llamafile are
already depending on it under the private namespace, to avoid
needing to link zlib twice.
2024-05-03 08:07:25 -07:00
Gavin Hayes deff138e7e recvfrom: don't convert address if addrsize is 0 (#1153) 2024-05-03 08:03:57 -07:00
Gavin Hayes b6e40a3a58 Add /dev/(u)random on NT (#1163) 2024-05-03 07:59:51 -07:00
Cadence Ember 8f6bc9dabc Let signals interrupt fgets unless SA_RESTART set (#1152) 2024-05-03 07:49:41 -07:00
Justine Tunney 181cd4cbe8 Add sysctlbyname() for MacOS 2024-05-02 23:21:43 -07:00
Justine Tunney 5c6877b02b Introduce support for trapping math
The feenableexcept() and fedisableexcept() APIs are now provided which
let you detect when NaNs appear the moment it happens from anywhere in
your program. Tests have also been added for the mission critical math
functions expf() and erff(), whose perfect operation has been assured.
See examples/trapping.c to see how to use this powerful functionality.
2024-04-30 13:38:43 -07:00
Justine Tunney 403bc25412 Make MXCSR editable by signal handlers on Windows
It's now possible to recover from floating point exception traps.
2024-04-30 13:38:43 -07:00
Matt Colyer 3bcd40be12 Fix regression in apeinstall.sh (#1161)
This should have been a part of a6baba1.
2024-04-29 20:40:38 -07:00
Paul Kulchenko fcfdd26b72 Fix wrong parameter type in redbean documentation (#1162) 2024-04-29 20:09:25 -04:00
Justine Tunney 2b00ee8723 Fix errno.h documentation typos
Closes #1156
2024-04-28 22:57:21 -07:00
Justine Tunney ff2b6fc0b0 Add munlock() and mlock2() to pledge 2024-04-28 16:53:23 -07:00
Justine Tunney 0eef971494 Add much of C11 threads.h API 2024-04-28 07:04:08 -07:00
Gavin Hayes 2bfd6b37c1 Various paginate improvements (#1148)
* start on improving __paginate

* make __paginate more robust

* add __paginate_file

* cleanup __paginate unlinking
2024-04-26 23:12:25 -04:00
Gavin Hayes 69db501c68 Fix fork locking on win32 (#1141)
* Fix fork locking on win32

- __enable_threads / set __threaded in __proc_setup as threads are required for
  win32 subprocess management
- move mmi/fds locking out of pthread_atfork.c into fork.c so it's done anytime
  __threaded is set instead of being dependent of pthreads
- explicitly yoink _pthread_onfork_prepare, _pthread_onfork_parent, and
  _pthread_onfork_child in pthread_create.c so they are linked in in-case they
  are separated from _pthread_atfork

Big Thanks to @dfyz for help with locating the issue, testing, and devising a fix!

* fix child processes not being able to open files, initialize all necessary locks on fork
2024-04-25 23:01:27 -04:00
Jōshin 6e6fc38935 Apply clang-format update to repo (#1154)
Commit bc6c183 introduced a bunch of discrepancies between what files
look like in the repo and what clang-format says they should look like.
However, there were already a few discrepancies prior to that. Most of
these discrepancies seemed to be unintentional, but a few of them were
load-bearing (e.g., a #include that violated header ordering needing
something to have been #defined by a 'later' #include.)

I opted to take what I hope is a relatively smooth-brained approach: I
reverted the .clang-format change, ran clang-format on the whole repo,
reapplied the .clang-format change, reran clang-format again, and then
reverted the commit that contained the first run. Thus the full effect
of this PR should only be to apply the changed formatting rules to the
repo, and from skimming the results, this seems to be the case.

My work can be checked by applying the short, manual commits, and then
rerunning the command listed in the autogenerated commits (those whose
messages I have prefixed auto:) and seeing if your results agree.

It might be that the other diffs should be fixed at some point but I'm
leaving that aside for now.

fd '\.c(c|pp)?$' --print0| xargs -0 clang-format -i
2024-04-25 10:38:00 -07:00
Jōshin 342d0c81e5 vim spells the c++ filetype 'cpp' 2024-04-24 13:56:37 -07:00
Jōshin cec4c04aa1 Remove .com logic from GetProgramExecutableName (#1134)
The `com` parameter to `TryPath` was always 1, so there was no reason to
have it. This patch changes the logic to be as though `com` was 0, which
provides a possible answer to the TODO question -- the answer is no.

If we never care about appending `.com`, then `CopyWithCwd` doesn't need
to return anything beyond a boolean success value.
2024-04-23 22:07:19 -04:00
Alexey Izbyshev f8c0186221 Fix calling __dns_parse with potentially too large rlen
__res_send returns the full answer length even if it didn't fit the
buffer, but __dns_parse expects the length of the filled part of the
buffer.

Analogous to Musl commit 77327ed064bd57b0e1865cd0e0364057ff4a53b4 which
fixed the only other __dns_parse call site.
2024-04-23 09:36:07 -07:00
Quentin Rameau 6992d8c195 Remove arbitrary limit from DNS result parsing
The name resolution would abort when getting more than 63 records per
request, due to what seems to be a left-over from the original code.
This check was non-breaking but spurious prior to TCP fallback
support, since any 512-byte packet with more than 63 records was
necessarily malformed. But now, it wrongly rejects valid results.

Reported by Daniel Stefanik in Alpine Linux aports issue 15320.
2024-04-23 09:33:02 -07:00
Justine Tunney 1a6b4ab627 Import mntent bug fixes from Musl Libc
f314e133929b6379eccc632bef32eaebb66a7335
Author: Rich Felker <[email protected]>
Date:   Thu Nov 16 12:55:21 2023 -0500

    mntent: fields are delimited only by tabs or spaces, not general whitespace

    this matters because the kernel-provided mtab only escapes tabs,
    spaces, newlines, and backslashes. it leaves carriage returns, form
    feeds, and vertical tabs literal.

commit ee1d39bc1573c1ae49ee6b658938b56bbef95a6c
Author: q66 <[email protected]>
Date:   Thu Nov 9 20:48:44 2023 +0100

    mntent: unescape octal sequences

    As entries in mtab are delimited by spaces, whitespace characters
    are escaped as octal sequences. When reading them out, we have to
    unescape these sequences to get the proper string.
2024-04-23 09:29:56 -07:00
Justine Tunney 9e848abad9 Add missing Musl license headers 2024-04-23 09:29:46 -07:00
Justine Tunney 223eb358c4 Import compiler warning fix from Musl 2024-04-23 09:29:28 -07:00
Szabolcs Nagy ea3cc4ea0b math: fix fma(x,y,0) when x*y rounds to -0
if x!=0, y!=0, z==0 then

  fma(x,y,z) == x*y

in all rounding modes, while adding z can ruin the sign of 0 if x*y
rounds to -0.
2024-04-23 09:22:33 -07:00
Paul Kulchenko 01267ea0f5 Update GetRemoteAddr documentation to clarify that it may return nil. (#1149) 2024-04-22 01:55:08 -04:00
Justine Tunney bc6c18368f Update .clang-format 2024-04-19 17:11:08 -07:00
Jōshin 06839ab301 Change loop bound on uuidv4 test (#1143)
A half second (on my machine) is too long for a unit test. 1000
iterations is probably still overkill, but 0.01 seconds is fine.

Also made `y` local.
2024-04-12 12:22:34 -04:00
BONNAURE Olivier 39dde41516 [Redbean] Add UuidV4 method (#1140) 2024-04-12 11:10:27 -04:00
Jōshin 3e16e59f72 Move store after __asan_unpoison in __zipos_alloc (#1135)
Previously, the atomic store looked like it was happening while the
struct's memory was still poisoned. I was unable to observe any issues
with this, but this change seems to make the code more obviously correct
(at the cost of a redundant atomic store to zeroed space in case the map
needed to be extended.)
2024-04-10 23:04:03 -04:00
Justine Tunney cf9a1f7f33 Fix MODE=optlinux build 2024-04-06 21:02:19 -07:00
Justine Tunney 49a32136f8 Upgrade the One True Awk 2024-04-06 19:21:48 -07:00
Justine Tunney b9d6e6e348 Standardize on -fsigned-char
MaGuess on Discord pointed out the fact that cosmocc contradicts itself
on the signedness of `char`. It's up to each platform to choose one, so
the cosmo platform shall choose signed. The rationale is it makes the C
language syntax more internally similar. `char` should be `signed char`
for the same reason `int` means `signed int`. It's recommended that you
still assume `char` could go either way since that's portable thinking.
But if you want to assume we'll always have signed char, that's ok too.
2024-03-30 21:46:08 -07:00
Justine Tunney b431ca4449 Upgrade to cosmocc v3.3.3 2024-03-30 20:17:14 -07:00
Justine Tunney 98d06b23cc Release Cosmopolitan v3.3.3 2024-03-30 19:24:04 -07:00
Justine Tunney 9ff65cff63 Fix ZipOS extraction of ZIP64 assets 2024-03-30 19:00:40 -07:00
Justine Tunney bef2cb05ff Fix AVX512_BF16 2024-03-26 00:00:46 -07:00
mierenhoop 43885a76e4 Fix binary formatting for integers 2 and 3 (#1123) 2024-03-25 21:11:09 -07:00
Justine Tunney 74a85087de Support -S in cosmocross
You can now run commands like `x86_64-unknown-cosmo-c++ -S` when using
your cosmocc toolchain. Please note the S flag isn't supported for the
cosmocc command itself.
2024-03-24 15:49:55 -07:00
Justine Tunney 045632a743 Make fixupobj work on Windows
This fixes a regression with recent cosmocc toolchain releases that
causes fixupobj to fail with "ifunc ftruncate #1 failed" on Windows
2024-03-24 03:14:25 -07:00
Justine Tunney 9a10adac35 Remove .com from README 2024-03-22 19:38:38 -07:00
Justine Tunney 0c12c26e1d Update Emacs config 2024-03-22 19:27:11 -07:00
Justine Tunney 40b7da8422 Speed up fmaf() on x86 2024-03-22 19:26:56 -07:00
Justine Tunney 640668931d Clarify MacOS supported versions
We technically support versions much earlier, possibly dating back to
2018 or earlier, but they're not officially supported since I have no
way of testing them.

Closes #1129
2024-03-22 19:25:07 -07:00
Justine Tunney 1c34088ba0 Ignore -pie and -fpie in cosmocc
Fixes #1126
2024-03-22 03:55:01 -07:00
Justine Tunney bb92347158 Add deprecated stubs for _bsf / _bsr 2024-03-05 09:45:51 -08:00
Justine Tunney 8bfd56b59e Rename _bsr/_bsf to bsr/bsf
Now that these functions are behind _COSMO_SOURCE there's no reason for
having the ugly underscore anymore. To use these functions, you need to
pass -mcosmo to cosmocc.
2024-03-04 17:33:26 -08:00
Justine Tunney a6baba1b07 Stop using .com extension in monorepo
The WIN32 CreateProcess() function does not require an .exe or .com
suffix in order to spawn an executable. Now that we have Cosmo bash
we're no longer so dependent on the cmd.exe prompt.
2024-03-03 03:12:19 -08:00
Justine Tunney c8383f25b4 Release Cosmopolitan v3.3.2 2024-02-27 09:15:59 -08:00
Justine Tunney 64a9e6fe56 Fix compiler runtime for _Float16 type 2024-02-27 09:06:23 -08:00
Justine Tunney 0ef36489c8 Walk back most uses of __STRICT_ANSI__ 2024-02-27 04:09:49 -08:00
Justine Tunney 7c7bf4bb90 Release Cosmopolitan v3.3.1 2024-02-27 00:31:36 -08:00
Justine Tunney 592f6ebc20 Make quality improvements
- Write some more unit tests
- memcpy() on ARM is now faster
- Address the Musl complex math FIXME comments
- Some libm funcs like pow() now support setting errno
- Import the latest and greatest math functions from ARM
- Use more accurate atan2f() and log1pf() implementations
- atoi() and atol() will no longer saturate or clobber errno
2024-02-25 19:08:43 -08:00
Justine Tunney af8f2bd19f Shave 4kb off each binary 2024-02-25 11:11:34 -08:00
Justine Tunney 38bceaeb8f Give up on making clock_nanosleep() precise
Multiple projects I care about make the assumption that this isn't a
system call that sleeps for a particular number of nanonseconds, but
rather a function that parks processes on kernel scheduler quantums.
Anyone who wants the old behavior should use cosmo_clock_nanosleep()
2024-02-24 10:17:47 -08:00
Ivan Komarov 99f0491f04 Fix invalid XNU binaries generated by apelink in some edge cases (#1106)
* Fix `if...fi` generation in the generated APE shell script

A shell will fail with a syntax error on an empty `if` or `else` body.
That is, neither of these is allowed:

    # Empty `if`
    if [ ... ]; then
    fi

    # Empty `else`
    if [ ... ]; then
    ...
    else
    fi

There were two places where `apelink` could generate problematic `if`'s:

1. The XNU shell generation for aarch64 binaries when no loaders (either
   binary or source) are provided. They can't assimilate, so the resulting
   `else` body becomes empty.
   There is actually a code path guarded by the `gotsome` variable that
   inserts an extra `true` in this case, but the variable was never
   initialized, so in practice this code path didn't activate in my
   tests. This is fixed by initializing the variable.
2. The loader extraction code when no loaders are provided and XNU
   support is requested. This is fixed by adding a simliar code path
   that prevents an empty body from being generated.

* Update the apelink manual after commit d53c335

The `-s` option changed its meaning, but the docs weren't updated.
2024-02-23 08:11:27 -08:00
Justine Tunney e72a88ea70 Make fixups for libcrypt 2024-02-23 07:39:44 -08:00
Ivan Komarov 9b4701b3bc Don't include <crypt.h> from <stdlib.h> (#1112) 2024-02-23 07:18:35 -08:00
Ivan Komarov f7ff515961 *scanf() fixes to make TeX work (#1109)
* Fix reading the same symbol twice when using `{f,}scanf()`

PR #924 appears to use `unget()` subtly incorrectly when parsing
floating point numbers. The rest of the code only uses `unget()`
immediately followed by `goto Done;` to return back the symbol that
can't possibly belong to the directive we're processing.

With floating-point, however, the ungot characters could very well
be valid for the *next* directive, so we will essentially read them
twice. It can't be seen in `sscanf()` tests because `unget()` is a
no-op there, but the test I added for `fscanf()` fails like this:

        ...
        EXPECT_EQ(0xDEAD, i1)
                need 57005 (or 0xdead) =
                 got 908973 (or 0x000ddead)
        ...
        EXPECT_EQ(0xBEEF, i2)
                need 48879 (or 0xbeef) =
                 got 769775 (or 0x000bbeef)

This means we read 0xDDEAD instead of 0xDEAD and 0xBBEEF instead of
0xBEEF. I checked that both musl and glibc read 0xDEAD/0xBEEF, as
expected.

Fix the failing test by removing the unneeded `unget()` calls.

* Don't read invalid floating-point numbers in `*scanf()`

Currently, we just ignore any errors from `strtod()`. They can
happen either because no valid float can be parsed at all, or
because the state machine recognizes only a prefix of a valid
floating-point number.

Fix this by making sure `strtod()` parses everything we recognized,
provided it's non-empty. This requires to pop the last character
off the FP buffer, which is supposed to be parsed by the next
`*scanf()` directive.

* Make `%c` parsing in `*scanf()` respect the C standard

Currently, `%c`-style directives always succeed even if there
are actually fewer characters in the input than requested.

Before the fix, the added test fails like this:

        ...
        EXPECT_EQ(2, sscanf("ab", "%c %c %c", &c2, &c3, &c4))
                need 2 (or 0x02 or '\2' or ENOENT) =
                 got 3 (or 0x03 or '\3' or ESRCH)
        ...
        EXPECT_EQ(0, sscanf("abcd", "%5c", s2))
                need 0 (or 0x0 or '\0') =
                 got 1 (or 0x01 or '\1' or EPERM)

musl and glibc pass this test.
2024-02-23 07:15:30 -08:00
Justine Tunney 3afe3a3646 Fix broken link 2024-02-23 07:11:44 -08:00
Justine Tunney b4faaa7c57 Relax style guide 2024-02-23 06:55:37 -08:00
Justine Tunney c4991e53ac Document copyright policy exceptions 2024-02-23 06:53:46 -08:00
Justine Tunney ad3944a3b6 Support any HTTP method
It's now possible to use redbean Fetch() with arbitrary HTTP methods,
e.g. LIST which is used by Hashicorp. There's an eight char limit and
uppercase canonicalization still happens. This change also includes a
better function for launching a browser tab, that won't deadlock on a
headless workstation running Debian.

Closes #1107
2024-02-22 14:12:18 -08:00
Justine Tunney 29eac8e2a2 Fix regression in logger functions
The recent release broke things so that the logger wasn't logging by
default. This ensures that `__log_file` initializes in correct order
2024-02-22 14:08:20 -08:00
Justine Tunney a5a3e78fcf Make ftrace/strace C APIs work with cosmocc 2024-02-22 12:13:16 -08:00
Justine Tunney e9a756e78b Make --ftrace more crash proof with foreign code
Sometimes we need to interact with code that wasn't compiled using
`-fno-omit-frame-pointer`. For example, if a function pointer gets
passed and called by a foreign function, linked by cosmo_dlopen().
Function call tracing will now detect backtrace pointer corruption
and simply reduce the indentation level back to zero, as a result.
2024-02-22 11:06:31 -08:00
Justine Tunney 38af54a2dd Fix GCC version in cosmocc wrapper script
See #1111
2024-02-21 19:16:39 -08:00
Justine Tunney 77a92f517b Introduce getcpu() system call from glibc 2024-02-21 18:17:20 -08:00
Justine Tunney 3eb405e0e2 Resurrect <windows.h> as <windowsesque.h> 2024-02-21 16:41:11 -08:00
Justine Tunney 68b9479f0c Make cosmo.h work a little better 2024-02-21 16:40:09 -08:00
Justine Tunney d9df41c4d5 Add example email to CONTRIBUTING.md 2024-02-21 16:36:52 -08:00
Justine Tunney fc3c536ec2 Make --ftrace work better with cosmocc
This change causes cosmocc to use -fno-inline-functions-called-once by
default, unless -Os or -finline-functions-called-once is defined. This
is important since I believe it generally makes code go faster, and it
most importantly makes --ftrace output much more understandable, since
the trace will be more likely to reflect the actual shape of the code.
We've always used this flag in the mono repo when ftracing is enabled,
but it slipped my mind to incorporate this into the cosmocc toolchain.
2024-02-21 13:20:21 -08:00
Justine Tunney 77ddf4cb07 Fix fixupobj regression on MacOS ARM64 2024-02-21 12:13:54 -08:00
Justine Tunney 4d018306b3 Fix MODE=optlinux build 2024-02-20 14:24:56 -08:00
Justine Tunney b3bb93d1d9 Fix MODE=opt build 2024-02-20 14:12:12 -08:00
Justine Tunney 980af27bbf Fix documentation build 2024-02-20 13:40:46 -08:00
Justine Tunney 957c61cbbf Release Cosmopolitan v3.3
This change upgrades to GCC 12.3 and GNU binutils 2.42. The GNU linker
appears to have changed things so that only a single de-duplicated str
table is present in the binary, and it gets placed wherever the linker
wants, regardless of what the linker script says. To cope with that we
need to stop using .ident to embed licenses. As such, this change does
significant work to revamp how third party licenses are defined in the
codebase, using `.section .notice,"aR",@progbits`.

This new GCC 12.3 toolchain has support for GNU indirect functions. It
lets us support __target_clones__ for the first time. This is used for
optimizing the performance of libc string functions such as strlen and
friends so far on x86, by ensuring AVX systems favor a second codepath
that uses VEX encoding. It shaves some latency off certain operations.
It's a useful feature to have for scientific computing for the reasons
explained by the test/libcxx/openmp_test.cc example which compiles for
fifteen different microarchitectures. Thanks to the upgrades, it's now
also possible to use newer instruction sets, such as AVX512FP16, VNNI.

Cosmo now uses the %gs register on x86 by default for TLS. Doing it is
helpful for any program that links `cosmo_dlopen()`. Such programs had
to recompile their binaries at startup to change the TLS instructions.
That's not great, since it means every page in the executable needs to
be faulted. The work of rewriting TLS-related x86 opcodes, is moved to
fixupobj.com instead. This is great news for MacOS x86 users, since we
previously needed to morph the binary every time for that platform but
now that's no longer necessary. The only platforms where we need fixup
of TLS x86 opcodes at runtime are now Windows, OpenBSD, and NetBSD. On
Windows we morph TLS to point deeper into the TIB, based on a TlsAlloc
assignment, and on OpenBSD/NetBSD we morph %gs back into %fs since the
kernels do not allow us to specify a value for the %gs register.

OpenBSD users are now required to use APE Loader to run Cosmo binaries
and assimilation is no longer possible. OpenBSD kernel needs to change
to allow programs to specify a value for the %gs register, or it needs
to stop marking executable pages loaded by the kernel as mimmutable().

This release fixes __constructor__, .ctor, .init_array, and lastly the
.preinit_array so they behave the exact same way as glibc.

We no longer use hex constants to define math.h symbols like M_PI.
2024-02-20 13:27:59 -08:00
BONNAURE Olivier d3ff48c63f [Redbean] Feature / OnError(status, message) hook (#1103) 2024-02-14 01:55:50 -08:00
Justine Tunney 2ab9e9f7fd Make improvements
- Introduce portable sched_getcpu() api
- Support GCC's __target_clones__ feature
- Make fma() go faster on x86 in default mode
- Remove some asan checks from core libraries
- WinMain() now ensures $HOME and $USER are defined
2024-02-12 10:23:00 -08:00
Ivan Komarov d5225a693b libc headers: make <complex.h> work, add struct ipv6_mreq (#1100)
1. `libc/isystem/complex.h` (included when you do `#include <complex.h>`)
   defines `_COMPLEX_H`, and then proceeds to include `libc/complex.h`,
   which contains the actual complex-related declarations. However, they
   are *also* guarded by `_COMPLEX_H` and hence effectively ignored.
   Fix this by changing `_COMPLEX_H` to `COSMOPOLITAN_LIBC_COMPLEX_H_`,
   which is consistent with what the other headers (such as `math.h`) do.
2. Cosmopolitan could only support IPv4 multicast requests for sockets,
   since a declaration for `struct ipv6_mreq` was missing. Add support
   for IPv6, too, by adding the missing declaration.
2024-02-05 17:22:56 -05:00
Paul Kulchenko c72904b2f6 Fix redbean Fetch redirect with relative URL (#1034) 2024-02-02 10:02:29 -05:00
Justine Tunney 616717fa82 Fine tune OpenMP some more 2024-01-30 06:30:24 -08:00
Justine Tunney 369aebfc48 Make improvements
- Let OpenMP be usable via cosmocc
- Let libunwind be usable via cosmocc
- Make X86_HAVE(AVXVNNI) work correctly
- Avoid using MAP_GROWSDOWN on qemu-aarch64
- Introduce in6addr_any and in6addr_loopback
- Have thread stacks use MAP_GROWSDOWN by default
- Ask OpenMP to not use filesystem to manage threads
- Make NI_MAXHOST and NI_MAXSERV available w/o _GNU_SOURCE
2024-01-29 16:31:58 -08:00
Justine Tunney 5f8e9f14c1 Add OpenMP support 2024-01-28 22:39:02 -08:00
Justine Tunney c1e18e7903 Restore MODE=dbg support
We recently broke MODE=dbg support when we added C++ exception support.
This change adds the missing UBSAN interfaces, needed to get it working
again. Some of the ASAN checking in the SJLJ guts needed to be disabled
since I doubt anyone's combined the two features until now.
2024-01-26 23:07:18 -08:00
Justine Tunney f27808c4d2 Remove feature for embedding blink in ape scripts
Embedding Blink builds in Cosmo executables was a failed experiment. It
turned out to be easier than expected to let the mono repo have support
for multiple architectures. Blink still works great; it's supported and
recommended; just please use it as a separate program. For example, you
can use Blink to run Cosmo binaries on architectures like i486 / s390x.
2024-01-26 22:30:56 -08:00
Justine Tunney 2719080986 Add program for printing Windows network dev info 2024-01-26 22:29:23 -08:00
Trung Nguyen 33418f6742 libc: Fix __cxa_thread_atexit prototype (#1088)
The first parameter should be a function pointer.

Otherwise, this would conflict with the definition provided by
`libcxxabi`.
2024-01-22 10:23:28 -08:00
Trung Nguyen 83a8686c06 tool/cosmocc: Properly handle dependency output (#1091)
a2753de contains some regressions, causing `fixupobj` to be
inappropriately suppressed when `-MD` or `-MMD` is passed.

This commit reverts most changes by a2753de, and:
- Treats all invocations of the compiler with `-M` and `-MM` as with the
`cpp` intent, since these flags imply `-E`.
- Handle the dependency output path specified by `-MF`.
  + This is trivial for `cosmocross` since the script does not throw
  objects to and from temporary directories.
  + For `cosmocc`, the file names are calculated based on the `-MF`
  value provided by the user. If this flag is not specified, the script
  generates the file name based on the output file using GCC rules.
  Then, before calling the real compilers, an additional `-MF` flag is
  passed to override the dependency outputs with mangled file names.
2024-01-22 10:22:16 -08:00
Justine Tunney 8ab3a545c6 Increase build memory quota
If you install qemu-user from apt then glibc links a lot of address
space bloat that causes pthread_create() to ENOMEM (a.k.a. EAGAIN).
Boosting the virtual memory quota from 512m to 2048m will hopefully
future proof the build for the future, as Linux distros get fatter.
Please note this only applies to MODE=aarch64 on x86_64 builds when
you're using QEMU from Debian/Ubuntu rather than installing the one
cosmo provides in third_party/qemu/qemu-aarch64.gz. This change may
also be useful to people who are using the host compiler toolchain.
2024-01-22 10:02:30 -08:00
Justine Tunney 8ebe2e9020 Fix assertion error in pthread_create() 2024-01-22 10:02:30 -08:00
BONNAURE Olivier 51cd83f674 Add Curve25519 method in help.txt + add new specs file (#1096) 2024-01-21 06:58:48 -08:00
Justine Tunney 39b0a9c03e Fix scanf() %n off by one at eof
Fixes #1094
2024-01-20 15:06:16 -08:00
Justine Tunney d50064a779 Add Curve25519() API to Redbean 2024-01-20 01:06:19 -08:00
Justine Tunney 1226eb7a5e Fix gcc warning 2024-01-18 16:48:02 -08:00
Trung Nguyen 8834dde0c2 libcxx: Add missing implementation source files (#1089)
Added the implementation for `std::bad_any_cast` from upstream
`any.cpp`, and `std::bad_variant_access` from upstream `variant.cpp`.

This fixes missing `vtable` and `typeinfo` symbols when trying to link
code referencing these exception types.
2024-01-18 08:20:25 -08:00
Justine Tunney 1ef63eb206 Retire third_party/quickjs/
QuickJS cosmocc binaries are now being distributed on
https://bellard.org/quickjs/
2024-01-17 12:35:46 -08:00
Brian 08793aa143 Make ... optional in .args (#1086) 2024-01-15 16:20:50 -08:00
Trung Nguyen 6db1200a7e libc: Fix cxxabi.h header (#1087)
- `__cxa_*` runtime functions are expected to be in the `abi` namespace,
which is currently an alias for `__cxxabiv1`.
- Rely on the header provided by `libcxxabi` for functions that we do
not implement ourselves anymore.
2024-01-15 11:50:38 -08:00
Trung Nguyen a2753de7fd tool/cosmocc: Do not run fixupobj for text output (#1084)
Some compiler flags (such as -E or -MM) instruct GCC to only run the
preprocessor and produce certain text files.

In this case, we do not want to run `fixupobj` and make the tool fail
because the input is not an ELF64 binary.
2024-01-15 07:16:13 -08:00
Jōshin 6715b670b1 Skip the CAS on new_pos < 0 (#1080) 2024-01-12 21:08:28 -08:00
Justine Tunney fd75fd1467 Make std::pair trivial 2024-01-09 09:51:59 -08:00
Justine Tunney 5d80e8dbf6 Add more Intel microarchitectures 2024-01-09 01:54:26 -08:00
Justine Tunney eeb20775d2 Add dontthrow attribute to most libc functions
This will help C++ code that uses exceptions to be tinier. For example,
this change shaves away 1000 lines of assembly code from LLVM's libcxx,
which is 0.7% of all assembly instructions in the entire library.
2024-01-09 01:26:03 -08:00
Justine Tunney cb19e172da Release Cosmopolitan v3.2.4 2024-01-08 19:37:59 -08:00
Jōshin df648fb174 Revert apeinstall.sh binfmt flags (#1072)
The P flag breaks backwards compatibility with older binaries. The idea
is to revert this commit after that break has been resolved.
2024-01-08 14:21:21 -08:00
Justine Tunney 9a6af92bed Fix libcxxabi tests in MODE=tiny and MODE=rel
See #1076
2024-01-08 13:49:06 -08:00
Justine Tunney 6ab01716ce Fix aarch64 setjmp abi
We now store values in jmp_buf where the compiler wants them to be. This
fixes code that calls __builtin_setjmp() and __builtin_longjmp() such as
libunwind. All libcxxabi tests are now passing on ARM64.

See #1076
2024-01-08 13:26:28 -08:00
Justine Tunney 21093044c0 Rebuild build/bootstrap/chmod.com 2024-01-08 12:22:12 -08:00
Justine Tunney b8a9fbbd01 Review catch_multi_level_pointer test failure
This test was was failing on GitHub Actions because GA uses Linux and
Linux supports resource usage accounting. Cosmo's compile.com program
imposes CPU, memory and file size limits on both the compiler and the
test programs themselves.

See #1076
2024-01-08 12:10:29 -08:00
Justine Tunney 81ce2e4cbc Call thread finalizers on exit()
While we don't call POSIX thread key destructors from exit(), we do need
to call these, since C++ uses it for TLS object destructors.

See #1076
2024-01-08 11:45:02 -08:00
Justine Tunney 07db3004d6 Disable libcxxabi/test/guard_threaded_test
It works, but exceeds the CPU quota granted to tests, by a lot.
2024-01-08 11:19:09 -08:00
Trung Nguyen b0566348b2 third_party/libcxxabi: Add test suite (#1076)
Added the `libcxxabi` test suite as found in LLVM 17.0.6.

Some tests that do not apply to the current configuration of
comsopolitan are not added. These include:
- `backtrace_test`, `forced_unwind*`: Use unwind function unsupported in
SjLj mode.
- `noexception*`: Designed to test `libcxxabi` in no exceptions mode.

Some tests are added but not enabled due to bugs specific to GCC or
cosmopolitan. These are clearly indicated in the `BUILD.mk` file.
2024-01-08 10:50:06 -08:00
Justine Tunney 8fb24a8f88 Turn exceptions back off by default 2024-01-08 10:47:42 -08:00
Justine Tunney a4b455185b Bring back gc() function
Renaming gc() to _gc() was a mistake since the better thing to do is put
it behind the _COSMO_SOURCE macro. We need this change because I haven't
wanted to use my amazing garbage collector ever since we renamed it. You
now need to define _COSMO_SOURCE yourself when using amalgamation header
and cosmocc users need to pass the -mcosmo flag to get the gc() function

Some other issues relating to cancelation have been fixed along the way.
We're also now putting cosmocc in a folder named `.cosmocc` so it can be
more safely excluded by grep --exclude-dir=.cosmocc --exclude-dir=o etc.
2024-01-08 10:26:28 -08:00
Jōshin 6cb0354e19 mkofs improvements
- Always use $PWD/o. if it doesn't exist, say how to create it.

- return 2 on unsupported platforms.
2024-01-08 17:23:09 +00:00
Trung Nguyen b580080af1 tool/cosmocc: Allow exceptions and rtti (#1074)
With `libunwind` and `libcxxabi` included in `libcosmo`, we can now
allow users to build C++ applications with exceptions and RTTI enabled.

The default is still disabling these two to avoid bloating the binary.

Closes #1065
2024-01-08 08:47:53 -08:00
Trung Nguyen 8b33204f37 Add LLVM libcxxabi (#1063)
* third_party: Add libcxxabi

Added libcxxabi from LLVM 17.0.6
The library implements the Itanium C++ exception handling ABI.

* third_party/libcxxabi: Enable __cxa_thread_atexit

Enable `__cxa_thread_atexit` from libcxxabi.
`__cxa_thread_atexit_impl` is still implemented by the cosmo libc.
The original `__cxa_thread_atexit` has been removed.

* third_party/libcxx: Build with exceptions

Build libcxx with exceptions enabled.

- Removed `_LIBCPP_NO_EXCEPTIONS` from `__config`.
- Switched the exception implementation to `libcxxabi`. These two files
are taken from the same `libcxx` version as mentioned in `README.cosmo`.
- Removed `new_handler_fallback` in favor of `libcxxabi` implementation.
- Enable `-fexceptions` and `-frtti` for `libcxx`.
- Removed `THIRD_PARTY_LIBCXX` dependency from `libcxxabi` and
`libunwind`. These libraries do not use any runtime `libcxx` functions,
just headers.

* libc: Remove remaining redundant cxa functions

- `__cxa_pure_virtual` in `libcxxabi` is also a stub similar to the
existing one.
- `__cxa_guard_*` from `libcxxabi` is used instead of the ones from
Android.

Now there should be no more duplicate implementations.
`__cxa_thread_atexit_impl`, `__cxa_atexit`, and related supporting
functions, are still left to other libraries as in `libcxxabi`.

`libcxxabi` is also now added to `cosmopolitan.a` to make up for the
removed functions.

Affected in-tree libraries (`third_party/double-conversion`) have been
updated.
2024-01-08 08:45:10 -08:00
Trung Nguyen 94bab1618d Add fixes to libunwind (#1069) 2024-01-08 08:31:13 -08:00
Jōshin cafea9a0a5 Flesh out tool/zsh/mkofs
It now prevents double-mounting.

Also adds vim filetype modelines.
2024-01-08 05:18:18 +00:00
Jōshin 16099801cc zsh mkofs tool 2024-01-08 03:43:09 +00:00
Justine Tunney 4cd02c29ed Release Cosmopolitan v3.2.3 2024-01-07 12:39:09 -08:00
Justine Tunney 5ae2554c10 Have cosmo_dlopen() request -z execstack on Linux
The AMD HIP SDK for Linux ships prebuilt DSOs with an RWX PT_GNU_STACK
since old versions of GCC made it nearly impossible to build artifacts
where that wasn't the case, however modern glibc systems will flat out
refuse to link RWX DSOs from an execuatble that uses PT_GNU_STACK = RW
2024-01-07 11:37:18 -08:00
Justine Tunney 531ac85923 Disable Python test_resource
It fails strangely on some Linux systems due to constraints imposed by
the build system. We'll try to learn more about this later on.
2024-01-07 11:36:31 -08:00
Jōshin 8d9fcb5e5a Fix ape-m1.c usage
It's not about `$0` anymore.
2024-01-07 10:35:50 -05:00
Jōshin aa37a327ea Make $prog.ape more reliable on Apple Silicon (#1071)
Now it doesn't matter what argv `$prog.ape` is invoked with. We just get
our executable path the Apple way.
2024-01-07 07:13:20 -08:00
Justine Tunney c4205f8305 Remove lingering dlopen thunk 2024-01-07 02:14:41 -08:00
Justine Tunney b3fb6cff43 Add /dev/fd support to Windows
GNU bash needs this functionality, otherwise it can't do <(cmd...).
2024-01-06 18:20:21 -08:00
Jōshin 2e5f662dfe mmake: different cosmocc regime
Now that cosmocc is unpacked into a version-specific directory under
cosmocc/, it makes more sense to put the versions in /opt/cosmocc and
maintain a symlink to the currently active one.
2024-01-06 19:14:13 -05:00
Justine Tunney 5e7137097d Make breaking change to cosmo_dlsym()
The cosmo_dlsym() function now returns the raw function address. You
need to call cosmo_dltramp() on the result, to make it safe to call.
This change is important, because cosmo_dltramp() magic can't always
work; for some tricky functions, you need to translate ABIs by hand.
2024-01-06 15:45:26 -08:00
Justine Tunney f224a55d57 Fix MODE=dbg build
Fixes #1067
2024-01-06 15:22:19 -08:00
Justine Tunney 0c51995b2b Add missing sha256sum.c file 2024-01-06 14:47:14 -08:00
Jōshin a9f23ccd17 Fix download-cosmocc.sh on Mac (#1066)
shasum behaves enough like sha256sum to work in this case.
2024-01-06 14:46:31 -08:00
Justine Tunney 57d1bf7a9c Clarify CONTRIBUTING.md 2024-01-06 14:18:01 -08:00
Justine Tunney ce17ed60df Support -MF and -MT in cosmocc 2024-01-06 12:10:06 -08:00
Jōshin d27a47b0e2 Bugfix: ape --help should exit 0 (#1060) 2024-01-06 12:07:32 -08:00
Jōshin 390335eb45 apeinstall/uninstall.sh can use doas (#1062) 2024-01-06 12:06:21 -08:00
Jōshin 492a8f4f53 Fix make o/aarch64/ape on aarch64 (#1064) 2024-01-06 11:42:39 -08:00
Jōshin 636bc4007b Enable argv[0] tests in more places (#1061)
Now we do them for assimilated binaries (except on OpenBSD or XNU
non-Silicon), for XnuSilicon, and for binaries with the preserve-
argv[0] auxv flag set. We check whether to pass the argv[0] value
at the test site rather than the Child site. We move a lot of the
test initialization into Child in the non-child case, in order to
get at the pre-init value of `__program_executable_name`. Finally,
we print out info about what we are skipping.
2024-01-06 11:42:03 -08:00
Trung Nguyen b09096691a third_party: Add libunwind (#1053)
Added libunwind from LLVM 17.0.6.
The library includes functions required for C++ exception handling.
2024-01-06 15:04:30 +07:00
6015 changed files with 447267 additions and 204736 deletions

No files matched your search

+2
View File
@@ -6,6 +6,8 @@ AlignConsecutiveMacros: true
AlignConsecutiveDeclarations: false
AlwaysBreakBeforeMultilineStrings: false
AllowShortFunctionsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
KeepEmptyLinesAtTheStartOfBlocks: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
IncludeBlocks: Merge
+23
View File
@@ -0,0 +1,23 @@
# Run this command to always ignore formatting commits in git blame
# git config blame.ignoreRevsFile .git-blame-ignore-revs
# Ran clang-format
f032b5570b4cd87c6bb4abb54c0b98e69c939955
# Applied clang-format update to repo
6e6fc38935054db0534d5af4fb99c6193305b946
# revert retabbing
2b315626f3af765cdfbc61114647412cdb798b3a
# more modeline errata
3a8e01a77a7c97af0b16fb1651b230cee7f7d4c6
# fix more vi modelines
2fc507c98f53a76718f61f9a36602f86b5ac0cc9
# flip et/noet in modelines
e16a7d8f3b8f906c3ef76e79f57f3adfc7f25186
# fix vi modelines
394d998315f613a888cc6b6c051d4163bdf5cd6f
# clang-format
c0eacf2eb1e1c0b3bd4f71f12fef258f5b249c3f
# ape-m1 formatting cleanup
da8baf2aa5ce93b958aca90a0ae69f537806324b
# Run clang-format on most sources
369f9740de4534c28d0e81ab2afc99decbb9a3e6
+1 -1
View File
@@ -2,7 +2,7 @@
/o
/cosmocc
/.prompt.jtlp
/.cosmocc
# TODO: Find some way to have Python write to o/
__pycache__
-109
View File
@@ -1,109 +0,0 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}"
],
"cStandard": "c11",
"cppStandard": "c++11",
"forcedInclude": ["${workspaceFolder}/.vscode/vscode.h"],
"defines": [
"libcesque=",
"pureconst=",
"paramsnonnull(x)=",
"alignas(x)",
"alignof(x)",
"artificial=",
"__wur=",
"mayalias=",
"forceinline=",
"forcealign(x)=",
"scanfesque(x)=",
"strftimeesque(x)=",
"wontreturn=",
"textreal=",
"mallocesque=",
"callocesque=",
"vallocesque=",
"reallocesque=",
"strlenesque=",
"memcpyesque=",
"hasatleast=",
"noinline=",
"textexit=",
"returnstwice=",
"textwindows=",
"privileged=",
"dontinstrument=",
"nodebuginfo=",
"interruptfn=",
"optimizespeed=",
"forcealignargpointer=",
"dontasan=",
"dontubsan=",
"donothing=",
"nosideeffect=",
"unreachable=",,
"notpossible=",
"thatispacked=",
"dontthrow=",
"nocallback=",
"relegated=",
"hidden=",
"textstartup=",
"initarray=",
"returnsnonnull=",
"returnspointerwithnoaliases=",
"printfesque(x)=",
"attributeallocsize(x)=",
"returnsaligned(x)=",
"attributeallocalign(x)=",
"nullterminated(x)="
]
},
{
"name": "Linux",
"includePath": [
"${workspaceFolder}"
],
"cStandard": "gnu17",
"compilerPath": "${workspaceFolder}/o/third_party/gcc/bin/x86_64-linux-musl-gcc",
"compilerArgs": [
"-Wall",
"-Werror",
"-fdebug-prefix-map=${workspaceFolder}=",
"-frecord-gcc-switches",
"-Wa,-W",
"-Wa,-I.",
"-Wa,--noexecstack",
"-Og",
"-g",
"-gdescribe-dies",
"-msse3",
"-mno-red-zone",
"-fno-math-errno",
"-fno-trapping-math",
"-fno-fp-int-builtin-inexact",
"-fno-ident",
"-fno-common",
"-fno-gnu-unique",
"-fstrict-aliasing",
"-fstrict-overflow",
"-fno-semantic-interposition",
"-mno-omit-leaf-frame-pointer",
"-fno-jump-tables",
"-nostdinc",
"-iquote."
],
"forcedInclude": [
"libc/integral/normalize.inc"
],
"defines": [
"COSMO",
"MODE="
]
}
],
"version": 4
}
-2
View File
@@ -1,2 +0,0 @@
#define __VSCODE_INTELLISENSE__ 1
#include "libc/integral/normalize.inc"
+69 -45
View File
@@ -2,23 +2,77 @@
We'd love to accept your patches! Please read this guide first.
## Identity Disclosure
This project does not accept anonymous contributions. Justine Tunney
won't merge pull requests from strangers. In order to change the Cosmo
codebase, and have your changes be upstreamed, she has to know who you
are. You're encouraged to disclose your full name and email address to
the public too, by including them in your git commit messages; however
that's not a requirement; as we're happy to respect the wishes of
contributors who prefer to remain anonymous to the public.
## Copyright Assignment
Please send an email to Justine Tunney <jtunney@gmail.com> stating that
you intend to assign her the copyright to the changes you contribute to
Cosmopolitan. Please use the same email address you use for git commits
which should only contain original source code from you or other people
who are also assigning copyright. Please note that, if you're employed,
you may need to get your employer's approval beforehand. If you can not
assign copyright due to local laws, then you may alternatively consider
disclaiming it using the language in [Unlicense](https://unlicense.org)
or [CC-0](http://creativecommons.org/share-your-work/public-domain/cc0)
The first time you send a pull request, you need to send an email to
Justine Tunney <jtunney@gmail.com> stating that you intend to assign her
the copyright to the changes you contribute to Cosmopolitan. It only
needs to happen once. This only applies to the code you *choose* to
contribute. The email should be sent from an email address associated
with your identity. Your email should link to your pull request.
This is important because we can't produce 12kb single-file executables
that comply with license requirements if we have to embed lots of them.
Although that's less of an issue depending on the purpose of the files.
For example, ownership is much less of a concern in the unit test files
so you're encouraged to put your copyright on those, provided it's ISC.
To make things easy, here's an example of a good email you can use:
> **From**: YOUR NAME ([email protected])
> **To**: Justine Tunney ([email protected])
> **Subject**: Cosmopolitan Copyright Assignment for YOUR NAME
>
> Hi Justine,
>
> I made my first contribution to Cosmopolitan in
> https://github.com/jart/cosmopolitan/pull/XXXX could you please take a
> look? I intend to assign you the copyright to the changes I contribute
> to Cosmopolitan.
>
> Thanks!
Please note that in order to give Justine the copyright, it has to be
yours to give in the first place. If you're employed, then you should
get your employer's approval to do this beforehand. Even with big
companies like Google, this process is quick and painless. Usually we
see employers granting authorization in less than one day.
If you live in a country that doesn't recognize one's ability to assign
copyright, then you may alternatively consider disclaiming it using the
language in [Unlicense](https://unlicense.org) or
[CC-0](http://creativecommons.org/share-your-work/public-domain/cc0).
If you're checking-in third party code, then you need to have headers at
the top of each source file (but never header files) documenting its
owners and the code should go in the `third_party/` folder. Every third
party project should have a `README.cosmo` file that documents its
provenance as well as any local changes you've made.
## Copyright Policy Exceptions
### Tests
You're encoraged to claim ownership of your test code. If you add a new
file under the `test/` directory, then you should put your name in the
ISC license header at the top of the file. If you add new test cases to
an existing unit test file, then you're encouraged to append a line with
your name to the existing copyright header of that file.
### Exceptional Features
Let's say you discovered a faster better way to implement `log10()` and
you want to give it to Cosmopolitan. In cases like this, it really isn't
appropriate for Justine to own your code. What you could do instead, is
write your own new and improved `log10.c` from scratch, put your name on
the top with the ISC license, and then add a `__notice()` directive so
that your name will be embedded inside every executable that links the
`log10()` function. This will help you get your name out there. Please
note you need get approval from Justine each time you want to do this.
## Style Guide
@@ -29,34 +83,4 @@ clang-format -i -style=file tool/net/redbean.c
```
If you use Emacs this can be automated on save for Cosmopolitan using
[tool/emacs/cosmo-format.el]([tool/emacs/cosmo-format.el]).
### Source Files
- Must use include paths relative to the root of the repository
- Must have comment at top of file documenting copyright and license
- Must have notice embedding if not owned by Justine (exception: tests)
- May use language extensions that are supported by both GCC and Clang
- Should use Google indentation (otherwise use `/* clang-format off */`)
- Should use asm() instead of compiler APIs (exception: ctz, clz, memcpy)
### Header Files
- Must not have copyright or license comments
- Must have once guards (otherwise change `.h` to `.inc`)
- Must be ANSI C89 compatible to be included in the amalgamation header
- Must include its dependencies (exception: libc/integral/normalize.inc)
- Must not define objects (i.e. `cc -c -xc foo.h` will produce empty `.o`)
- Should not use typedefs
- Should not use forward declarations
- Should not include documentation comments
- Should not include parameter names in prototypes
- Should not pose problems if included by C++ or Assembly sources
- Should not declare non-ANSI code, at all, when the user requests ANSI
### Build Config
- Must not write files outside `o/`
- Must not communicate with Internet
- Must not depend on system libraries
- Must not depend on system commands (exception: sh, make, gzip, zip)
[tool/emacs/cosmo-format.el](tool/emacs/cosmo-format.el).
+86 -85
View File
@@ -21,23 +21,23 @@
# make -j8 -O MODE=tiny
#
# # build individual target
# make -j8 -O o//examples/hello.com
# o//examples/hello.com
# make -j8 -O o//examples/hello
# o//examples/hello
#
# # view source
# less examples/hello.c
#
# # view binary
# o//tool/viz/bing.com o//examples/hello.com |
# o//tool/viz/fold.com
# o//tool/viz/bing o//examples/hello |
# o//tool/viz/fold
#
# # view transitive closure of legalese
# o//tool/viz/bing.com -n o//examples/hello.com |
# o//tool/viz/fold.com
# o//tool/viz/bing -n o//examples/hello |
# o//tool/viz/fold
#
# # basic debugging
# make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
# o/examples/crashreport.com
# make -j8 -O MODE=dbg o/dbg/examples/crashreport
# o/examples/crashreport
# less examples/crashreport.c
#
# # extremely tiny binaries
@@ -51,7 +51,7 @@
#
# TROUBLESHOOTING
#
# make -j8 -O V=1 o//examples/hello.com
# make -j8 -O V=1 o//examples/hello
# make o//examples/life.elf -pn |& less
# etc.
#
@@ -59,7 +59,7 @@
#
# build/config.mk
SHELL = build/bootstrap/cocmd.com
SHELL = build/bootstrap/cocmd
MAKEFLAGS += --no-builtin-rules
.SUFFIXES:
@@ -77,8 +77,8 @@ COMMA := ,
PWD := $(shell pwd)
# 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
# - user ran build/bootstrap/make, in which case make's working directory is in wsl
# - user ran make, in which case cocmd's working directory is in wsl
ifneq ($(findstring //wsl.localhost/,$(CURDIR) $(PWD)),)
$(warning wsl2 interop is enabled)
$(error you need to run sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop')
@@ -89,7 +89,7 @@ UNAME_S := $(shell uname -s)
# apple still distributes a 17 year old version of gnu make
ifeq ($(MAKE_VERSION), 3.81)
$(error please use build/bootstrap/make.com)
$(error please use build/bootstrap/make)
endif
LC_ALL = C
@@ -101,31 +101,42 @@ XARGS ?= xargs -P4 -rs8000
DOT ?= dot
CLANG = clang
TMPDIR = o/tmp
AR = build/bootstrap/ar.com
CP = build/bootstrap/cp.com
RM = build/bootstrap/rm.com -f
GZIP = build/bootstrap/gzip.com
ECHO = build/bootstrap/echo.com
CHMOD = build/bootstrap/chmod.com
TOUCH = build/bootstrap/touch.com
PKG = build/bootstrap/package.com
MKDEPS = build/bootstrap/mkdeps.com
ZIPOBJ = build/bootstrap/zipobj.com
ZIPCOPY = build/bootstrap/zipcopy.com
PECHECK = build/bootstrap/pecheck.com
FIXUPOBJ = build/bootstrap/fixupobj.com
MKDIR = build/bootstrap/mkdir.com -p
COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
AR = build/bootstrap/ar
CP = build/bootstrap/cp
RM = build/bootstrap/rm -f
GZIP = build/bootstrap/gzip
ECHO = build/bootstrap/echo
CHMOD = build/bootstrap/chmod
TOUCH = build/bootstrap/touch
PKG = build/bootstrap/package
MKDEPS = build/bootstrap/mkdeps
ZIPOBJ = build/bootstrap/zipobj
ZIPCOPY = build/bootstrap/zipcopy
PECHECK = build/bootstrap/pecheck
FIXUPOBJ = build/bootstrap/fixupobj
MKDIR = build/bootstrap/mkdir -p
COMPILE = build/bootstrap/compile -V9 -M2048m -P8192 $(QUOTA)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
# the default build modes is empty string
# on x86_64 hosts, MODE= is the same as MODE=x86_64
# on aarch64 hosts, MODE= is changed to MODE=aarch64
ifeq ($(MODE),)
ifeq ($(UNAME_M),arm64)
MODE := aarch64
endif
ifeq ($(UNAME_M),aarch64)
MODE := aarch64
endif
endif
ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
HOSTS ?= pi studio freebsdarm
else
ARCH = x86_64
HOSTS ?= freebsd rhel7 xnu win10 openbsd netbsd
HOSTS ?= freebsd rhel7 xnu openbsd netbsd win10
endif
ZIPOBJ_FLAGS += -a$(ARCH)
@@ -138,9 +149,9 @@ export MODE
export SOURCE_DATE_EPOCH
export TMPDIR
COSMOCC = cosmocc/3.2
COSMOCC = .cosmocc/3.3.5
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.2 28b48682595f0f46b45ab381118cdffdabc8fcfa29aa54e301fe6ffe35269f5e)
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.5 db78fd8d3f8706e9dff4be72bf71d37a3f12062f212f407e1c33bc4af3780dd0)
AS = $(TOOLCHAIN)as
CC = $(TOOLCHAIN)gcc
@@ -158,23 +169,12 @@ else
ADDR2LINE = $(TOOLCHAIN)addr2line
endif
# the default build modes is empty string
# on x86_64 hosts, MODE= is the same as MODE=x86_64
# on aarch64 hosts, MODE= is changed to MODE=aarch64
ifeq ($(MODE),)
ifeq ($(UNAME_M),arm64)
MODE := aarch64
endif
ifeq ($(UNAME_M),aarch64)
MODE := aarch64
endif
endif
# primary build rules
all: o
o: o/$(MODE)
o/$(MODE): \
o/$(MODE)/ape \
o/$(MODE)/ctl \
o/$(MODE)/dsp \
o/$(MODE)/net \
o/$(MODE)/libc \
@@ -188,7 +188,7 @@ o/$(MODE): \
o/$(MODE)/: o/$(MODE)
o/$(MODE)/.: o/$(MODE)
# check if we're using o//third_party/make/make.com
# check if we're using o//third_party/make/make
# we added sandboxing to guarantee cosmo's makefile is hermetic
# it also shaves away 200ms of startup latency with native $(uniq)
ifneq ($(LANDLOCKMAKE_VERSION),)
@@ -207,9 +207,8 @@ endif
.UNVEIL += \
libc/integral \
libc/stdbool.h \
libc/disclaimer.inc \
rwc:/dev/shm \
rx:cosmocc \
rx:.cosmocc \
rx:build/bootstrap \
r:build/portcosmo.h \
/proc/stat \
@@ -249,7 +248,6 @@ include libc/calls/BUILD.mk #─┐
include libc/irq/BUILD.mk # ├──SYSTEMS RUNTIME
include third_party/nsync/BUILD.mk # │ You can issue system calls
include libc/runtime/BUILD.mk # │
include third_party/double-conversion/BUILD.mk # │
include libc/crt/BUILD.mk # │
include third_party/dlmalloc/BUILD.mk #─┘
include libc/mem/BUILD.mk #─┐
@@ -258,10 +256,11 @@ include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
include libc/proc/BUILD.mk # │ You can now use threads
include libc/dlopen/BUILD.mk # │ You can now use processes
include libc/thread/BUILD.mk # │ You can finally call malloc()
include ctl/BUILD.mk # │
include third_party/zlib/BUILD.mk # │
include libc/stdio/BUILD.mk # │
include tool/hello/BUILD.mk # │
include libc/time/BUILD.mk # │
include third_party/tz/BUILD.mk # │
include net/BUILD.mk # │
include third_party/vqsort/BUILD.mk # │
include libc/log/BUILD.mk # │
@@ -284,7 +283,11 @@ include third_party/stb/BUILD.mk # │
include third_party/mbedtls/BUILD.mk # │
include third_party/ncurses/BUILD.mk # │
include third_party/readline/BUILD.mk # │
include third_party/libunwind/BUILD.mk # |
include third_party/libcxxabi/BUILD.mk # |
include third_party/libcxx/BUILD.mk # │
include third_party/openmp/BUILD.mk # │
include third_party/double-conversion/BUILD.mk # │
include third_party/pcre/BUILD.mk # │
include third_party/less/BUILD.mk # │
include net/https/BUILD.mk # │
@@ -296,7 +299,10 @@ include third_party/nsync/testing/BUILD.mk
include libc/testlib/BUILD.mk
include tool/viz/lib/BUILD.mk
include tool/args/BUILD.mk
include test/math/BUILD.mk
include test/posix/BUILD.mk
include test/ctl/BUILD.mk
include test/libcxx/BUILD.mk
include test/tool/args/BUILD.mk
include third_party/linenoise/BUILD.mk
include third_party/maxmind/BUILD.mk
@@ -316,7 +322,6 @@ include third_party/argon2/BUILD.mk
include third_party/smallz4/BUILD.mk
include third_party/sqlite3/BUILD.mk
include third_party/mbedtls/test/BUILD.mk
include third_party/quickjs/BUILD.mk
include third_party/lz4cli/BUILD.mk
include third_party/zip/BUILD.mk
include third_party/xxhash/BUILD.mk
@@ -328,6 +333,7 @@ include third_party/python/BUILD.mk
include tool/build/BUILD.mk
include tool/curl/BUILD.mk
include third_party/qemu/BUILD.mk
include third_party/libcxxabi/test/BUILD.mk
include examples/BUILD.mk
include examples/pyapp/BUILD.mk
include examples/pylife/BUILD.mk
@@ -359,7 +365,6 @@ include test/libc/fmt/BUILD.mk
include test/libc/time/BUILD.mk
include test/libc/proc/BUILD.mk
include test/libc/stdio/BUILD.mk
include test/libc/release/BUILD.mk
include test/libc/BUILD.mk
include test/net/http/BUILD.mk
include test/net/https/BUILD.mk
@@ -412,17 +417,17 @@ o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
TAGS: private .UNSANDBOXED = 1
TAGS: o/$(MODE)/srcs-old.txt $(SRCS) #o/$(MODE)/third_party/ctags/ctags.com
TAGS: o/$(MODE)/srcs-old.txt $(SRCS) #o/$(MODE)/third_party/ctags/ctags
@$(RM) $@
@o/$(MODE)/third_party/ctags/ctags.com $(TAGSFLAGS) -L $< -o $@
@o/$(MODE)/third_party/ctags/ctags $(TAGSFLAGS) -L $< -o $@
HTAGS: private .UNSANDBOXED = 1
HTAGS: o/$(MODE)/hdrs-old.txt $(filter-out third_party/libcxx/%,$(HDRS)) #o/$(MODE)/third_party/ctags/ctags.com
HTAGS: o/$(MODE)/hdrs-old.txt $(filter-out third_party/libcxx/%,$(HDRS)) #o/$(MODE)/third_party/ctags/ctags
@$(RM) $@
@build/htags o/$(MODE)/third_party/ctags/ctags.com -L $< -o $@
@build/htags o/$(MODE)/third_party/ctags/ctags -L $< -o $@
loc: private .UNSANDBOXED = 1
loc: o/$(MODE)/tool/build/summy.com
loc: o/$(MODE)/tool/build/summy
find -name \*.h -or -name \*.c -or -name \*.S | \
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
@@ -437,15 +442,19 @@ COSMOPOLITAN_OBJECTS = \
LIBC_X \
THIRD_PARTY_GETOPT \
LIBC_LOG \
LIBC_TIME \
THIRD_PARTY_TZ \
THIRD_PARTY_OPENMP \
THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB_GZ \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
LIBC_STDIO \
THIRD_PARTY_GDTOA \
THIRD_PARTY_REGEX \
LIBC_THREAD \
LIBC_PROC \
THIRD_PARTY_NSYNC_MEM \
CTL \
LIBC_MEM \
THIRD_PARTY_DLMALLOC \
LIBC_DLOPEN \
@@ -474,6 +483,7 @@ COSMOPOLITAN_OBJECTS = \
LIBC_STR \
LIBC_SYSV \
LIBC_INTRIN \
LIBC_NT_BCRYPTPRIMITIVES \
LIBC_NT_KERNEL32 \
LIBC_NEXGEN32E
@@ -498,7 +508,6 @@ COSMOPOLITAN_H_PKGS = \
LIBC_STR \
LIBC_SYSV \
LIBC_THREAD \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_X \
LIBC_VGA \
@@ -509,12 +518,17 @@ COSMOPOLITAN_H_PKGS = \
THIRD_PARTY_GETOPT \
THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB \
THIRD_PARTY_ZLIB_GZ \
THIRD_PARTY_REGEX
COSMOCC_PKGS = \
$(COSMOPOLITAN_H_PKGS) \
CTL \
THIRD_PARTY_AARCH64 \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
THIRD_PARTY_OPENMP \
THIRD_PARTY_INTEL
o/$(MODE)/cosmopolitan.a: \
@@ -532,26 +546,14 @@ 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$@ build/bootstrap/rollup.com @$< >>$@
o/cosmopolitan.html: private .UNSANDBOXED = 1
o/cosmopolitan.html: \
o/$(MODE)/third_party/chibicc/chibicc.com.dbg \
o/$(MODE)/third_party/chibicc/chibicc.dbg \
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \
$(SRCS) \
$(filter-out %.cpp,$(filter-out %.cc,$(SRCS))) \
$(HDRS)
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))
o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.cpp,$(filter-out %.cc,$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))))
o/$(MODE)/third_party/chibicc/chibicc.dbg -J \
-fno-common -include libc/integral/normalize.inc -o $@ \
-DCOSMO @$(TMPDIR)/$(subst /,_,$@)
@@ -565,7 +567,6 @@ $(SRCS): \
ifeq ($(ARCH), x86_64)
TOOLCHAIN_ARTIFACTS = \
o/cosmopolitan.h \
o/$(MODE)/ape/ape.lds \
o/$(MODE)/libc/crt/crt.o \
o/$(MODE)/ape/ape.elf \
@@ -574,13 +575,13 @@ TOOLCHAIN_ARTIFACTS = \
o/$(MODE)/ape/ape-no-modify-self.o \
o/$(MODE)/cosmopolitan.a \
o/$(MODE)/third_party/libcxx/libcxx.a \
o/$(MODE)/tool/build/march-native.com \
o/$(MODE)/tool/build/ar.com \
o/$(MODE)/tool/build/mktemper.com \
o/$(MODE)/tool/build/fixupobj.com \
o/$(MODE)/tool/build/zipcopy.com \
o/$(MODE)/tool/build/apelink.com \
o/$(MODE)/tool/build/pecheck.com
o/$(MODE)/tool/build/march-native \
o/$(MODE)/tool/build/ar \
o/$(MODE)/tool/build/mktemper \
o/$(MODE)/tool/build/fixupobj \
o/$(MODE)/tool/build/zipcopy \
o/$(MODE)/tool/build/apelink \
o/$(MODE)/tool/build/pecheck
else
TOOLCHAIN_ARTIFACTS = \
o/$(MODE)/ape/ape.elf \
@@ -588,9 +589,9 @@ TOOLCHAIN_ARTIFACTS = \
o/$(MODE)/libc/crt/crt.o \
o/$(MODE)/cosmopolitan.a \
o/$(MODE)/third_party/libcxx/libcxx.a \
o/$(MODE)/tool/build/march-native.com \
o/$(MODE)/tool/build/fixupobj.com \
o/$(MODE)/tool/build/zipcopy.com
o/$(MODE)/tool/build/march-native \
o/$(MODE)/tool/build/fixupobj \
o/$(MODE)/tool/build/zipcopy
endif
.PHONY: toolchain
+20 -20
View File
@@ -92,8 +92,8 @@ guaranteed to be compatible and furthermore includes our extensions for
doing build system sandboxing.
```sh
build/bootstrap/make.com -j8
o//examples/hello.com
build/bootstrap/make -j8
o//examples/hello
```
Since the Cosmopolitan repository is very large, you might only want to
@@ -103,8 +103,8 @@ depends on core LIBC packages.
```sh
rm -rf o//libc o//test
build/bootstrap/make.com o//test/posix/signal_test.com
o//test/posix/signal_test.com
build/bootstrap/make o//test/posix/signal_test
o//test/posix/signal_test
```
Sometimes it's desirable to build a subset of targets, without having to
@@ -112,21 +112,21 @@ list out each individual one. For example if you wanted to build and run
all the unit tests in the `TEST_POSIX` package, you could say:
```sh
build/bootstrap/make.com o//test/posix
build/bootstrap/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
build/bootstrap/make m=tiny
```
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=tinylinux
build/bootstrap/make m=tinylinux
```
For further details, see [//build/config.mk](build/config.mk).
@@ -179,11 +179,11 @@ end
src
```
You normally run the `.com.dbg` file under gdb. If you need to debug the
`.com` file itself, then you can load the debug symbols independently as
You normally run the `.dbg` file under gdb. If you need to debug the
`` file itself, then you can load the debug symbols independently as
```sh
gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
gdb foo -ex 'add-symbol-file foo.dbg 0x401000'
```
## Platform Notes
@@ -242,16 +242,16 @@ server. You're welcome to join us! <https://discord.gg/FwAVVu7eJ4>
## Support Vector
| Platform | Min Version | Circa |
| :--- | ---: | ---: |
| AMD | K8 Venus | 2005 |
| Intel | Core | 2006 |
| Linux | 2.6.18 | 2007 |
| Windows | 8 [1] | 2012 |
| Mac OS X | 15.6 | 2018 |
| OpenBSD | 7 | 2021 |
| FreeBSD | 13 | 2020 |
| NetBSD | 9.2 | 2021 |
| Platform | Min Version | Circa |
| :--- | ---: | ---: |
| AMD | K8 Venus | 2005 |
| Intel | Core | 2006 |
| Linux | 2.6.18 | 2007 |
| Windows | 8 [1] | 2012 |
| Darwin (macOS) | 23.1.0+ | 2023 |
| OpenBSD | 7 | 2021 |
| FreeBSD | 13 | 2020 |
| NetBSD | 9.2 | 2021 |
[1] See our [vista branch](https://github.com/jart/cosmopolitan/tree/vista)
for a community supported version of Cosmopolitan that works on Windows
+21 -14
View File
@@ -157,7 +157,6 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
ape/ape.S \
ape/ape.h \
ape/macros.internal.h \
ape/notice.inc \
ape/relocations.h \
ape/ape.internal.h \
libc/dce.h \
@@ -173,8 +172,6 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
libc/runtime/mman.internal.h \
libc/runtime/pc.internal.h \
libc/sysv/consts/prot.h \
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz \
o/$(MODE)/ape/ape.elf
@$(COMPILE) \
-AOBJECTIFY.S \
@@ -187,7 +184,6 @@ o/$(MODE)/ape/ape-copy-self.o: \
ape/ape.S \
ape/ape.h \
ape/macros.internal.h \
ape/notice.inc \
ape/relocations.h \
ape/ape.internal.h \
libc/dce.h \
@@ -202,9 +198,7 @@ o/$(MODE)/ape/ape-copy-self.o: \
libc/runtime/e820.internal.h \
libc/runtime/mman.internal.h \
libc/runtime/pc.internal.h \
libc/sysv/consts/prot.h \
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz
libc/sysv/consts/prot.h
@$(COMPILE) \
-AOBJECTIFY.S \
$(OBJECTIFY.S) \
@@ -226,10 +220,10 @@ o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy.com -f -o $@ $<
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy -f -o $@ $<
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.elf.dbg
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy.com -fm -o $@ $<
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy -fm -o $@ $<
APE_LOADER_LDFLAGS = \
-static \
@@ -260,12 +254,25 @@ o/$(MODE)/ape: $(APE_CHECKS) \
endif
# these assembly files are safe to build on aarch64
o/$(MODE)/ape/ape.o: ape/ape.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/ape/ape.o: \
ape/blink-linux-aarch64.gz \
ape/blink-xnu-aarch64.gz
ape/ape.S \
ape/ape.h \
libc/dce.h \
libc/elf/def.h \
ape/relocations.h \
libc/thread/tls.h \
ape/ape.internal.h \
ape/macros.internal.h \
libc/macho.internal.h \
libc/macros.internal.h \
libc/sysv/consts/prot.h \
libc/nt/pedef.internal.h \
libc/runtime/pc.internal.h \
libc/runtime/e820.internal.h \
libc/runtime/mman.internal.h \
libc/nexgen32e/uart.internal.h \
libc/calls/metalfile.internal.h
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/ape/ape.lds: \
ape/ape.lds \
+13 -9
View File
@@ -89,10 +89,12 @@ SECTIONS {
*(.ubsan.data)
}
.comment : {
__comment_start = .;
KEEP(*(.comment))
.notice : {
__notices = .;
KEEP(*(.notice))
BYTE(0);
BYTE(10);
BYTE(10);
}
.eh_frame_hdr : {
@@ -157,8 +159,11 @@ SECTIONS {
.init_array : {
__init_array_start = .;
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
KEEP(*(.preinit_array))
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP(*(.init_array))
KEEP(*(.ctors))
__init_array_end = .;
}
@@ -288,7 +293,6 @@ _tdata_size = _tdata_end - _tdata_start;
_tbss_size = _tbss_end - _tbss_start;
_tbss_offset = _tbss_start - _tdata_start;
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
_tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
_tdata_align = ALIGNOF(.tdata);
_tbss_align = ALIGNOF(.tbss);
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
+171 -124
View File
@@ -31,6 +31,8 @@
#include <string.h>
#include <sys/mman.h>
#include <sys/random.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
@@ -39,7 +41,7 @@
/* maximum path size that cosmo can take */
#define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024)
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 8
#define SYSLIB_VERSION 10 /* sync with libc/runtime/syslib.internal.h */
struct Syslib {
int magic;
@@ -96,43 +98,58 @@ struct Syslib {
long (*sem_trywait)(int *);
long (*getrlimit)(int, struct rlimit *);
long (*setrlimit)(int, const struct rlimit *);
// v6 (2023-11-03)
/* v6 (2023-11-03) */
void *(*dlopen)(const char *, int);
void *(*dlsym)(void *, const char *);
int (*dlclose)(void *);
char *(*dlerror)(void);
/* MANDATORY (cosmo runtime won't load if version < 8)
---------------------------------------------------
OPTIONAL (cosmo lib should check __syslib->version) */
/* v9 (2024-01-31) */
int (*pthread_cpu_number_np)(size_t *);
/* v10 (2024-05-02) */
long (*sysctl)(int *, u_int, void *, size_t *, void *, size_t);
long (*sysctlbyname)(const char *, void *, size_t *, void *, size_t);
long (*sysctlnametomib)(const char *, int *, size_t *);
};
#define ELFCLASS32 1
#define ELFDATA2LSB 1
#define EM_AARCH64 183
#define ET_EXEC 2
#define ET_DYN 3
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define EI_CLASS 4
#define EI_DATA 5
#define PF_X 1
#define PF_W 2
#define PF_R 4
#define AT_PHDR 3
#define AT_PHENT 4
#define AT_PHNUM 5
#define AT_PAGESZ 6
#define AT_BASE 7
#define AT_ENTRY 9
#define AT_UID 11
#define AT_EUID 12
#define AT_GID 13
#define AT_EGID 14
#define AT_HWCAP 16
#define AT_HWCAP2 16
#define AT_SECURE 23
#define AT_RANDOM 25
#define AT_EXECFN 31
#define ELFCLASS32 1
#define ELFDATA2LSB 1
#define EM_AARCH64 183
#define ET_EXEC 2
#define ET_DYN 3
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define EI_CLASS 4
#define EI_DATA 5
#define PF_X 1
#define PF_W 2
#define PF_R 4
#define AT_PHDR 3
#define AT_PHENT 4
#define AT_PHNUM 5
#define AT_PAGESZ 6
#define AT_BASE 7
#define AT_FLAGS 8
#define AT_FLAGS_PRESERVE_ARGV0_BIT 0
#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
#define AT_ENTRY 9
#define AT_UID 11
#define AT_EUID 12
#define AT_GID 13
#define AT_EGID 14
#define AT_HWCAP 16
#define AT_HWCAP2 16
#define AT_SECURE 23
#define AT_RANDOM 25
#define AT_EXECFN 31
#define AUXV_WORDS 29
#define EF_APE_MODERN 0x101ca75
#define EF_APE_MODERN_MASK 0x1ffffff
#define AUXV_WORDS 31
/* from the xnu codebase */
#define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul
@@ -140,8 +157,8 @@ struct Syslib {
#define _COMM_PAGE_APRR_WRITE_ENABLE (_COMM_PAGE_START_ADDRESS + 0x110)
#define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118)
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
#define Min(X, Y) ((Y) > (X) ? (X) : (Y))
#define Max(X, Y) ((Y) < (X) ? (X) : (Y))
#define READ32(S) \
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
@@ -213,13 +230,15 @@ struct ApeLoader {
static unsigned long StrLen(const char *s) {
unsigned long n = 0;
while (*s++) ++n;
while (*s++)
++n;
return n;
}
static int StrCmp(const char *l, const char *r) {
unsigned long i = 0;
while (l[i] == r[i] && r[i]) ++i;
while (l[i] == r[i] && r[i])
++i;
return (l[i] & 255) - (r[i] & 255);
}
@@ -268,7 +287,8 @@ static char *Utoa(char p[21], unsigned long x) {
}
static char *Itoa(char p[21], long x) {
if (x < 0) *p++ = '-', x = -(unsigned long)x;
if (x < 0)
*p++ = '-', x = -(unsigned long)x;
return Utoa(p, x);
}
@@ -304,7 +324,8 @@ static int GetIndirectOffset(const char *arg0) {
static void Perror(const char *thing, long rc, const char *reason) {
char ibuf[21];
ibuf[0] = 0;
if (rc) Itoa(ibuf, -rc);
if (rc)
Itoa(ibuf, -rc);
Print(2, "ape error: ", thing, ": ", reason, rc ? " failed w/ errno " : "",
ibuf, "\n", 0l);
}
@@ -319,20 +340,11 @@ 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++] = '/';
if (pathlen && ps->path[pathlen - 1] != '/')
ps->path[pathlen++] = '/';
memmove(ps->path + pathlen, ps->name, ps->namelen);
ps->path[pathlen + ps->namelen] = 0;
if (!access(ps->path, X_OK)) {
if (ps->indirect) {
ps->namelen -= 4;
ps->path[pathlen + ps->namelen] = 0;
if (access(ps->path, X_OK) < 0) {
Pexit(ps->path, -errno, "access(X_OK)");
}
}
return 1;
}
return 0;
return !access(ps->path, X_OK);
}
static char SearchPath(struct PathSearcher *ps) {
@@ -358,12 +370,8 @@ static char FindCommand(struct PathSearcher *ps) {
ps->path[0] = 0;
/* paths are always 100% taken literally when a slash exists
$ ape foo/bar.com arg1 arg2 */
if (memchr(ps->name, '/', ps->namelen)) {
return AccessCommand(ps, 0);
}
/* we don't run files in the current directory
$ ape foo/bar.com arg1 arg2
we don't run files in the current directory
$ ape foo.com arg1 arg2
unless $PATH has an empty string entry, e.g.
$ expert PATH=":/bin"
@@ -371,8 +379,8 @@ static char FindCommand(struct PathSearcher *ps) {
however we will execute this
$ ape - foo.com foo.com arg1 arg2
because cosmo's execve needs it */
if (ps->literally && AccessCommand(ps, 0)) {
return 1;
if (ps->literally || memchr(ps->name, '/', ps->namelen)) {
return AccessCommand(ps, 0);
}
/* otherwise search for name on $PATH */
@@ -382,8 +390,11 @@ static char FindCommand(struct PathSearcher *ps) {
static char *Commandv(struct PathSearcher *ps, const char *name,
const char *syspath) {
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
if (ps->namelen + 1 > sizeof(ps->path)) return 0;
ps->name = name;
if (!(ps->namelen = ps->indirect ? ps->indirect : StrLen(ps->name)))
return 0;
if (ps->namelen + 1 > sizeof(ps->path))
return 0;
if (FindCommand(ps)) {
return ps->path;
} else {
@@ -550,6 +561,20 @@ static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds,
return sysret(pselect(nfds, readfds, writefds, errorfds, timeout, sigmask));
}
static long sys_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen) {
return sysret(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
}
static long sys_sysctlbyname(const char *name, void *oldp, size_t *oldlenp,
void *newp, size_t newlen) {
return sysret(sysctlbyname(name, oldp, oldlenp, newp, newlen));
}
static long sys_sysctlnametomib(const char *name, int *mibp, size_t *sizep) {
return sysret(sysctlnametomib(name, mibp, sizep));
}
__attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
long *sp, struct ElfEhdr *e,
struct ElfPhdr *p,
@@ -590,10 +615,11 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
a = p[i].p_vaddr & -pagesz;
b = (p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz;
for (j = i + 1; j < e->e_phnum; ++j) {
if (p[j].p_type != PT_LOAD) continue;
if (p[j].p_type != PT_LOAD)
continue;
c = p[j].p_vaddr & -pagesz;
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
if (MAX(a, c) < MIN(b, d)) {
if (Max(a, c) < Min(b, d)) {
Pexit(exe, 0, "ELF segments overlap each others virtual memory");
}
}
@@ -619,7 +645,8 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
if (e->e_type == ET_DYN) {
rc = sys_mmap(0, virtmax - virtmin, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (rc < 0) Pexit(exe, rc, "pie mmap");
if (rc < 0)
Pexit(exe, rc, "pie mmap");
dynbase = rc;
if (dynbase & (pagesz - 1)) {
Pexit(exe, 0, "OS mmap incongruent w/ AT_PAGESZ");
@@ -635,14 +662,18 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
for (i = 0; i < e->e_phnum; ++i) {
void *addr;
unsigned long size;
if (p[i].p_type != PT_LOAD) continue;
if (p[i].p_type != PT_LOAD)
continue;
/* configure mapping */
prot = 0;
flags = MAP_FIXED | MAP_PRIVATE;
if (p[i].p_flags & PF_R) prot |= PROT_READ;
if (p[i].p_flags & PF_W) prot |= PROT_WRITE;
if (p[i].p_flags & PF_X) prot |= PROT_EXEC;
if (p[i].p_flags & PF_R)
prot |= PROT_READ;
if (p[i].p_flags & PF_W)
prot |= PROT_WRITE;
if (p[i].p_flags & PF_X)
prot |= PROT_EXEC;
/* load from file */
if (p[i].p_filesz) {
@@ -662,7 +693,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */
b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */
c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */
wipe = MIN(b - a, c - a);
wipe = Min(b - a, c - a);
if (wipe && (~prot1 & PROT_WRITE)) {
prot1 = PROT_READ | PROT_WRITE;
}
@@ -670,9 +701,9 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
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
/* 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) {
@@ -684,32 +715,38 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
}
}
#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
/* 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");
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");
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 (rc < 0)
Pexit(exe, rc, "prog mmap");
}
if (wipe) memset((void *)(dynbase + a), 0, wipe);
if (wipe)
memset((void *)(dynbase + a), 0, wipe);
if (prot2 != prot1) {
rc = sys_mprotect(addr, size, prot2);
if (rc < 0) Pexit(exe, rc, "prog mprotect");
if (rc < 0)
Pexit(exe, rc, "prog mprotect");
}
/* allocate extra bss */
if (c > b) {
flags |= MAP_ANONYMOUS;
rc = sys_mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0);
if (rc < 0) Pexit(exe, rc, "extra bss mmap");
if (rc < 0)
Pexit(exe, rc, "extra bss mmap");
}
} else {
/* allocate pure bss */
@@ -717,7 +754,8 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_memsz;
flags |= MAP_ANONYMOUS;
rc = sys_mmap(addr, size, prot, flags, -1, 0);
if (rc < 0) Pexit(exe, rc, "bss mmap");
if (rc < 0)
Pexit(exe, rc, "bss mmap");
}
}
@@ -764,7 +802,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
}
static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
const char *exe, int fd, long *sp, long *auxv,
char *exe, int fd, long *sp, long *auxv,
char *execfn) {
long i, rc;
unsigned size;
@@ -785,6 +823,10 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
if (e->e_machine != EM_AARCH64) {
return "couldn't find ELF header with ARM64 machine type";
}
if ((e->e_flags & EF_APE_MODERN_MASK) != EF_APE_MODERN && sp[0] > 0) {
/* change argv[0] to resolved path for older binaries */
((char **)(sp + 1))[0] = exe;
}
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
Pexit(exe, 0, "e_phentsize is wrong");
}
@@ -795,8 +837,10 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
/* read program headers */
rc = pread(fd, M->phdr.buf, size, ebuf->ehdr.e_phoff);
if (rc < 0) return "failed to read ELF program headers";
if (rc != size) return "truncated read of ELF program headers";
if (rc < 0)
return "failed to read ELF program headers";
if (rc != size)
return "truncated read of ELF program headers";
/* bail on recoverable program header errors */
p = &M->phdr.phdr;
@@ -822,12 +866,10 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
}
}
/*
* merge adjacent loads that are contiguous with equal protection,
* which prevents our program header overlap check from needlessly
* failing later on; it also shaves away a microsecond of latency,
* since every program header requires invoking at least 1 syscall
*/
/* merge adjacent loads that are contiguous with equal protection,
which prevents our program header overlap check from needlessly
failing later on; it also shaves away a microsecond of latency,
since every program header requires invoking at least 1 syscall */
for (i = 0; i + 1 < e->e_phnum;) {
if (p[i].p_type == PT_LOAD && p[i + 1].p_type == PT_LOAD &&
((p[i].p_flags & (PF_R | PF_W | PF_X)) ==
@@ -861,25 +903,27 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
auxv[7] = ebuf->ehdr.e_entry;
auxv[8] = AT_PAGESZ;
auxv[9] = pagesz;
auxv[10] = AT_UID;
auxv[11] = getuid();
auxv[12] = AT_EUID;
auxv[13] = geteuid();
auxv[14] = AT_GID;
auxv[15] = getgid();
auxv[16] = AT_EGID;
auxv[17] = getegid();
auxv[18] = AT_HWCAP;
auxv[19] = 0xffb3ffffu;
auxv[20] = AT_HWCAP2;
auxv[21] = 0x181;
auxv[22] = AT_SECURE;
auxv[23] = issetugid();
auxv[24] = AT_RANDOM;
auxv[25] = (long)M->rando;
auxv[26] = AT_EXECFN;
auxv[27] = (long)execfn;
auxv[28] = 0;
auxv[10] = AT_FLAGS;
auxv[11] = M->ps.literally ? AT_FLAGS_PRESERVE_ARGV0 : 0;
auxv[12] = AT_UID;
auxv[13] = getuid();
auxv[14] = AT_EUID;
auxv[15] = geteuid();
auxv[16] = AT_GID;
auxv[17] = getgid();
auxv[18] = AT_EGID;
auxv[19] = getegid();
auxv[20] = AT_HWCAP;
auxv[21] = 0xffb3ffffu;
auxv[22] = AT_HWCAP2;
auxv[23] = 0x181;
auxv[24] = AT_SECURE;
auxv[25] = issetugid();
auxv[26] = AT_RANDOM;
auxv[27] = (long)M->rando;
auxv[28] = AT_EXECFN;
auxv[29] = (long)execfn;
auxv[30] = 0;
/* we're now ready to load */
Spawn(exe, fd, sp, e, p, &M->lib, M->ps.path);
@@ -891,7 +935,7 @@ int main(int argc, char **argv, char **envp) {
struct ApeLoader *M;
long *sp, *sp2, *auxv;
union ElfEhdrBuf *ebuf;
char *p, *pe, *exe, *prog, *execfn, *shell;
char *p, *pe, *exe, *prog, *execfn;
/* allocate loader memory in program's arg block */
n = sizeof(struct ApeLoader);
@@ -952,14 +996,22 @@ int main(int argc, char **argv, char **envp) {
M->lib.dlsym = dlsym;
M->lib.dlclose = dlclose;
M->lib.dlerror = dlerror;
M->lib.pthread_cpu_number_np = pthread_cpu_number_np;
M->lib.sysctl = sys_sysctl;
M->lib.sysctlbyname = sys_sysctlbyname;
M->lib.sysctlnametomib = sys_sysctlnametomib;
/* getenv("_") is close enough to at_execfn */
execfn = argc > 0 ? argv[0] : 0;
execfn = 0;
for (i = 0; envp[i]; ++i) {
if (envp[i][0] == '_' && envp[i][1] == '=') {
execfn = envp[i] + 2;
}
}
prog = GetEnv(envp + i + 1, "executable_path");
if (!execfn) {
execfn = prog;
}
/* sneak the system five abi back out of args */
sp = (long *)(argv - 1);
@@ -970,7 +1022,8 @@ int main(int argc, char **argv, char **envp) {
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;
if ((long)sp2 & 15)
++sp2;
for (; n > 0; n -= pagesz) {
((char *)sp2)[n - 1] = 0;
}
@@ -981,8 +1034,8 @@ int main(int argc, char **argv, char **envp) {
sp = sp2;
/* interpret command line arguments */
if ((M->ps.indirect = argc > 0 ? GetIndirectOffset(argv[0]) : 0)) {
/* if argv[0] is $prog.ape, then we strip off the .ape and run
if ((M->ps.indirect = GetIndirectOffset(prog))) {
/* if called as $prog.ape, then strip off the .ape and run the
$prog. This allows you to use symlinks to trick the OS when
a native executable is required. For example, let's say you
want to use the APE binary /opt/cosmos/bin/bash as a system
@@ -991,13 +1044,7 @@ int main(int argc, char **argv, char **envp) {
but it will if you say:
ln -sf /usr/local/bin/ape /opt/cosmos/bin/bash.ape
and then use #!/opt/cosmos/bin/bash.ape instead. */
M->ps.literally = 0;
if (*argv[0] == '-' && (shell = GetEnv(envp, "SHELL")) &&
!StrCmp(argv[0] + 1, BaseName(shell))) {
execfn = prog = shell;
} else {
prog = (char *)sp[1];
}
M->ps.literally = 1;
argc = sp[0];
argv = (char **)(sp + 1);
} else if ((M->ps.literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
@@ -1011,7 +1058,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"
" ($0 = PROG.ape) [ARGV1,ARGV2,...]\n"
" PROG.ape [ARGV1,ARGV2,...]\n"
"actually portable executable loader silicon 1.10\n"
"copyrights 2023 justine alexandra roberts tunney\n"
"https://justine.lol/ape.html\n");
+24 -57
View File
@@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 nofixeol :vi │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │
@@ -33,7 +33,6 @@
│ αcτµαlly pδrταblε εxεcµταblε § program header │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/macros.internal.h"
#include "ape/notice.inc"
#include "ape/relocations.h"
#include "libc/calls/metalfile.internal.h"
#include "libc/dce.h"
@@ -197,7 +196,7 @@ ape_mz:
.quad ape_elf_entry // 18: e_entry
.quad ape_elf_phoff // 20: e_phoff
.quad ape_elf_shoff // 28: e_shoff
.long 0 // 30: e_flags
.long 0x101ca75 // 30: ape e_flags
.short 64 // 34: e_ehsize
.short 56 // 36: e_phentsize
.short ape_elf_phnum // 38: e_phnum
@@ -670,7 +669,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.shstub ape_elf_entry,8 // 18: e_entry
.shstub ape_elf_phoff,8 // 20: e_phoff
.shstub ape_elf_shoff,8 // 28: e_shoff
.ascii "\\0\\0\\0\\0" // 30: e_flags
.ascii "\\165\\312\\1\\1" // 30: ape e_flags
.ascii "\\100\\0" // 34: e_ehsize
.ascii "\\070\\0" // 36: e_phentsize
.shstub ape_elf_phnum,2 // 38: e_phnum
@@ -700,36 +699,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
#endif /* APE_NO_MODIFY_SELF */
.ascii "exit $?\n"
.ascii "fi\n" // x86_64
// ...
// decentralized section (.apesh)
// ...
.ascii "PHDRS='' <<'@'\n"
.endobj apesh
// elf program headers get inserted here
// because they need to be in the first 4096 bytes
.section .emushprologue,"a",@progbits
emush: .ascii "\n@\n#'\"\n"
.ascii "s=$(uname -s 2>/dev/null) || s=Darwin\n"
// our script is running on a non-x86_64 architecture
// 1. `dd` out the appropriate blink vm blob
// 2. gunzip the blink virtual machine executable
// 3. relaunch this program inside the blink vm
.ascii "o=\"$(command -v \"$0\")\"\n"
.ascii "e=\"${TMPDIR:-${HOME:-.}}/.ape-blink-1.0.0\"\n"
.previous
// ...
// decentralized section (.emush)
// - __static_yoink("blink_linux_aarch64"); // for raspberry pi
// - __static_yoink("blink_xnu_aarch64"); // is apple silicon
// ...
.section .emushepilogue,"a",@progbits
.ascii "echo \"$0: this ape binary lacks $m support\" >&2\n"
.rept 16
.ascii "exit 127\n"
.endr
.ascii "echo error: this ape binary only supports x86_64 >&2\n"
.ascii "exit 1\n"
.previous
.endobj apesh
#ifdef APE_LOADER
.section .ape.loader,"a",@progbits
@@ -1064,7 +1036,7 @@ ape_pe: .ascin "PE",4
.quad ape_pe_base // ImageBase
.long ape_pe_sectionalignment // SectionAlignment
.long ape_pe_filealignment // FileAlignment
.short v_ntversion // MajorOperatingSystemVersion
.short 10 // MajorOperatingSystemVersion
.short 0 // MinorOperatingSystemVersion
.short 0 // MajorImageVersion
.short 0 // MinorImageVersion
@@ -1799,49 +1771,31 @@ kernel: movabs $ape_stack_vaddr,%rsp
.type ape_text_nops,@object
.type __test_end,@object
.section .commentprologue,"a",@progbits
.globl __comment_start
.type __comment_start,@object
.hidden __comment_start
__comment_start:/*
...
decentralized content
...
*/.previous
.section .commentepilogue,"a",@progbits
.byte 0
.previous
.section .ape.pad.head,"a",@progbits
.type ape_pad_head,@object
.hidden ape_pad_head
ape_pad_head:
.previous
.section .ape.pad.text,"a",@progbits
.type ape_pad_text,@object
.hidden ape_pad_text
ape_pad_text:
.previous
.section .ape.pad.privileged,"a",@progbits
.type ape_pad_privileged,@object
.hidden ape_pad_privileged
ape_pad_privileged:
.previous
.section .ape.pad.data,"a",@progbits
.type ape_pad_data,@object
.hidden ape_pad_data
ape_pad_data:
.previous
#if SupportsWindows()
.section .idata.ro,"a",@progbits
.type ape_idata_ro,@object
.hidden ape_idata_ro
ape_idata_ro:
.previous
#endif /* SupportsWindows() */
.section .dataprologue,"aw",@progbits
@@ -1849,32 +1803,45 @@ ape_idata_ro:
.globl __data_start
.hidden __data_start
__data_start:
.previous
.section .dataepilogue,"aw",@progbits
.type __data_end,@object
.globl __data_end
.hidden __data_end
__data_end:
.previous
.section .bssprologue,"aw",@nobits
.type __bss_start,@object
.globl __bss_start
.hidden __bss_start
__bss_start:
.previous
.section .bssepilogue,"aw",@nobits
.type __bss_end,@object
.globl __bss_end
.hidden __bss_end
__bss_end:
.previous
.section .fstls,"awT",@nobits
.align TLS_ALIGNMENT
.previous
.section .notice,"aR",@progbits
.asciz "\n\n\
Cosmopolitan\n\
Copyright 2024 Justine Alexandra Roberts Tunney\n\
\n\
Permission to use, copy, modify, and/or distribute this software for\n\
any purpose with or without fee is hereby granted, provided that the\n\
above copyright notice and this permission notice appear in all copies.\n\
\n\
THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL\n\
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED\n\
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE\n\
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\n\
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\n\
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n\
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n\
PERFORMANCE OF THIS SOFTWARE."
.end

+22 -47
View File
@@ -229,7 +229,6 @@ SECTIONS {
/* Real Mode */
KEEP(*(.head))
KEEP(*(.apesh))
KEEP(*(.text.head))
/* Executable & Linkable Format */
@@ -238,10 +237,6 @@ SECTIONS {
KEEP(*(.elf.phdrs))
ape_phdrs_end = .;
KEEP(*(.emushprologue))
KEEP(*(.emush))
KEEP(*(.emushepilogue))
/* OpenBSD */
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
ape_note = .;
@@ -287,12 +282,9 @@ SECTIONS {
KEEP(*(SORT_BY_NAME(.init.*)))
KEEP(*(.init))
KEEP(*(.initepilogue))
KEEP(*(.pltprologue))
*(.plt)
KEEP(*(.pltepilogue))
KEEP(*(.pltgotprologue))
*(.plt.got)
KEEP(*(.pltgotepilogue))
*(.iplt)
*(.text.startup .text.startup.*)
*(.text.exit .text.exit.*)
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
@@ -301,7 +293,6 @@ SECTIONS {
KEEP(*(.textwindowsprologue))
*(.text.windows)
KEEP(*(.textwindowsepilogue))
KEEP(*(.blink))
*(SORT_BY_ALIGNMENT(.text.modernity))
*(SORT_BY_ALIGNMENT(.text.modernity.*))
*(SORT_BY_ALIGNMENT(.text.hot))
@@ -329,7 +320,7 @@ SECTIONS {
/*BEGIN: Read Only Data */
.rodata . : {
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
KEEP(*(.rodata.pytab.0));
KEEP(*(.rodata.pytab.1));
KEEP(*(.rodata.pytab.2));
@@ -339,11 +330,11 @@ SECTIONS {
*(.ubsan.data)
/* Legal Notices */
#if !defined(IM_FEELING_NAUGHTY) || defined(EMBED_NOTICES)
KEEP(*(.commentprologue))
KEEP(*(.comment))
KEEP(*(.commentepilogue))
#endif
__notices = .;
KEEP(*(.notice))
BYTE(0);
BYTE(10);
BYTE(10);
/*BEGIN: read-only data that's only needed for initialization */
@@ -399,26 +390,28 @@ SECTIONS {
/*BEGIN: NT FORK COPYING */
KEEP(*(.dataprologue))
*(.data .data.*)
*(.gnu_extab)
*(.gcc_except_table .gcc_except_table.*)
*(.exception_ranges*)
*(.PyRuntime) /* for python */
*(.subrs) /* for emacs */
KEEP(*(SORT_BY_NAME(.sort.data.*)))
. += . > 0 ? CODE_GRANULE : 0;
KEEP(*(.gotprologue))
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
__got_start = .;
*(.got)
KEEP(*(.gotepilogue))
__got_end = .;
KEEP(*(.gotpltprologue))
*(.got.plt)
KEEP(*(.gotpltepilogue))
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
__init_array_start = .;
KEEP(*(.preinit_array))
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP(*(.ctors))
KEEP(*(.init_array))
KEEP(*(.preinit_array))
KEEP(*(.ctors))
__init_array_end = .;
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
@@ -435,7 +428,9 @@ SECTIONS {
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
KEEP(*(.piro.pad.data))
*(.igot.plt)
KEEP(*(.dataepilogue))
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
/*END: NT FORK COPYING */
_edata = .;
@@ -533,7 +528,9 @@ SECTIONS {
*(.piro.data.sort.iat.*)
#endif
*(__patchable_function_entries)
*(.note.gnu.property)
*(__mcount_loc)
*(.rela.dyn)
*(.discard)
*(.yoink)
}
@@ -556,7 +553,9 @@ _tdata_size = _tdata_end - _tdata_start;
_tbss_size = _tbss_end - _tbss_start;
_tbss_offset = _tbss_start - _tdata_start;
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
_tls_align = 1;
_tdata_align = ALIGNOF(.tdata);
_tbss_align = ALIGNOF(.tbss);
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
ape_cod_offset = 0;
ape_cod_vaddr = ADDR(.head);
@@ -613,29 +612,6 @@ SHSTUB2(ape_loader_dd_count,
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
: 0);
#if defined(APE_IS_SHELL_SCRIPT) && !IsTiny()
#define IDENTITY(X) X
#define APE_DECLARE_FIXED_DECIMAL(F, X) \
X##_quad = DEFINED(X) ? ((F(X) < 1000000000 ? 32 : F(X) / 1000000000 % 10 + 48) << 000 | \
(F(X) < 100000000 ? 32 : F(X) / 100000000 % 10 + 48) << 010 | \
(F(X) < 10000000 ? 32 : F(X) / 10000000 % 10 + 48) << 020 | \
(F(X) < 1000000 ? 32 : F(X) / 1000000 % 10 + 48) << 030 | \
(F(X) < 100000 ? 32 : F(X) / 100000 % 10 + 48) << 040 | \
(F(X) < 10000 ? 32 : F(X) / 10000 % 10 + 48) << 050 | \
(F(X) < 1000 ? 32 : F(X) / 1000 % 10 + 48) << 060 | \
(F(X) < 100 ? 32 : F(X) / 100 % 10 + 48) << 070) : 0; \
X##_short = DEFINED(X) ? ((F(X) < 10 ? 32 : F(X) / 10 % 10 + 48) << 000 | \
(F(X) % 10 + 48) << 010) : 0
APE_DECLARE_FIXED_DECIMAL(RVA, blink_linux_aarch64);
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_linux_aarch64_size);
APE_DECLARE_FIXED_DECIMAL(RVA, blink_xnu_aarch64);
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_xnu_aarch64_size);
#endif /* APE_IS_SHELL_SCRIPT */
#if SupportsMetal()
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
v_ape_realbytes = v_ape_realsectors * 512;
@@ -739,7 +715,6 @@ ape_idataz = LINK_WINDOWS ? RVA(ape_idata_iat) : 0;
ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0;
ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0;
ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0;
v_ntversion = LINK_WINDOWS ? 6 : 1;
v_ntdllchar = LINK_WINDOWS ? 288 : 0;
v_ntsubversion = LINK_WINDOWS ? 6 : 5;
v_ntsubsystem = (LINK_WINDOWS
+8 -3
View File
@@ -10,16 +10,21 @@ if [ ! -f ape/loader.c ]; then
cd "$COSMO" || exit
fi
if [ -x build/bootstrap/make.com ]; then
MAKE=build/bootstrap/make.com
if [ -x build/bootstrap/make ]; then
MAKE=build/bootstrap/make
else
MAKE=make
fi
if [ "$(id -u)" -eq 0 ]; then
SUDO=
else
elif command -v sudo >/dev/null 2>&1; then
SUDO=sudo
elif command -v doas >/dev/null 2>&1; then
SUDO=doas
else
echo "need root or sudo" >&2
exit
fi
if command -v install >/dev/null 2>&1; then
+7 -4
View File
@@ -11,8 +11,13 @@ fi
if [ "$UID" = "0" ]; then
SUDO=
else
elif command -v sudo >/dev/null 2>&1; then
SUDO=sudo
elif command -v doas >/dev/null 2>&1; then
SUDO=doas
else
echo "need root or sudo" >&2
exit
fi
{
@@ -54,9 +59,7 @@ for x in .ape \
.ape-1.7 \
.ape-1.8 \
.ape-1.9 \
.ape-1.10 \
.ape-blink-0.9.2 \
.ape-blink-1.0.0; do
.ape-1.10; do
rm -f \
~/$x \
/tmp/$x \
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -22,7 +22,7 @@
#include "libc/macros.internal.h"
// Apple Mach-O Executable Headers
// Fixups are applied by objbincopy.com
// Fixups are applied by objbincopy
// There must exist a MAC_LC_SEGMENT_64 for every PT_LOAD
.section .macho,"a",@progbits
+115 -53
View File
@@ -152,6 +152,9 @@
#define PR_SET_MM 35
#define PR_SET_MM_EXE_FILE 13
#define EF_APE_MODERN 0x101ca75
#define EF_APE_MODERN_MASK 0x1ffffff
#define READ32(S) \
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
(unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000)
@@ -166,13 +169,6 @@
(unsigned long)(255 & (S)[1]) << 010 | \
(unsigned long)(255 & (S)[0]) << 000)
#define DEBUG(VAR) \
{ \
char ibuf[19] = {0}; \
Utox(ibuf, VAR); \
Print(os, 2, ibuf, " " #VAR, "\n", 0l); \
}
struct ElfEhdr {
unsigned char e_ident[16];
unsigned short e_type;
@@ -235,13 +231,15 @@ extern char _end[];
static unsigned long StrLen(const char *s) {
unsigned long n = 0;
while (*s++) ++n;
while (*s++)
++n;
return n;
}
static int StrCmp(const char *l, const char *r) {
unsigned long i = 0;
while (l[i] == r[i] && r[i]) ++i;
while (l[i] == r[i] && r[i])
++i;
return (l[i] & 255) - (r[i] & 255);
}
@@ -340,23 +338,6 @@ static char *GetEnv(char **p, const char *s) {
return 0;
}
static char *Utox(char p[19], unsigned long x) {
int i;
if (x) {
*p++ = '0';
*p++ = 'x';
i = (__builtin_clzl(x) ^ (sizeof(long) * 8 - 1)) + 1;
i = (i + 3) & -4;
do {
*p++ = "0123456789abcdef"[(x >> (i -= 4)) & 15];
} while (i);
} else {
*p++ = '0';
}
*p = 0;
return p;
}
static char *Utoa(char p[20], unsigned long x) {
char t;
unsigned long i, a, b;
@@ -377,7 +358,8 @@ static char *Utoa(char p[20], unsigned long x) {
}
static char *Itoa(char p[21], long x) {
if (x < 0) *p++ = '-', x = -(unsigned long)x;
if (x < 0)
*p++ = '-', x = -(unsigned long)x;
return Utoa(p, x);
}
@@ -386,7 +368,8 @@ __attribute__((__noinline__)) static long CallSystem(long arg1, long arg2,
long arg5, long arg6,
long arg7, int numba,
char os) {
if (IsXnu()) numba |= 0x2000000;
if (IsXnu())
numba |= 0x2000000;
return SystemCall(arg1, arg2, arg3, arg4, arg5, arg6, arg7, numba);
}
@@ -534,10 +517,62 @@ static long Print(int os, int fd, const char *s, ...) {
return Write(fd, b, n, os);
}
static long Printf(int os, int fd, const char *fmt, ...) {
int i;
char c;
int k = 0;
unsigned u;
char b[512];
const char *s;
unsigned long d;
__builtin_va_list va;
__builtin_va_start(va, fmt);
for (;;) {
switch ((c = *fmt++)) {
case '\0':
__builtin_va_end(va);
return Write(fd, b, k, os);
case '%':
switch ((c = *fmt++)) {
case 's':
for (s = __builtin_va_arg(va, const char *); s && *s; ++s) {
if (k < 512)
b[k++] = *s;
}
break;
case 'd':
d = __builtin_va_arg(va, unsigned long);
for (i = 16; i--;) {
u = (d >> (i * 4)) & 15;
if (u < 10) {
c = '0' + u;
} else {
u -= 10;
c = 'a' + u;
}
if (k < 512)
b[k++] = c;
}
break;
default:
if (k < 512)
b[k++] = c;
break;
}
break;
default:
if (k < 512)
b[k++] = c;
break;
}
}
}
static void Perror(int os, const char *thing, long rc, const char *reason) {
char ibuf[21];
ibuf[0] = 0;
if (rc) Itoa(ibuf, -rc);
if (rc)
Itoa(ibuf, -rc);
Print(os, 2, "ape error: ", thing, ": ", reason,
rc ? " failed w/ errno " : "", ibuf, "\n", 0l);
}
@@ -549,8 +584,10 @@ __attribute__((__noreturn__)) static void Pexit(int os, const char *c, int rc,
}
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++] = '/';
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);
ps->path[pathlen + ps->namelen] = 0;
return !Access(ps->path, X_OK, ps->os);
@@ -577,11 +614,14 @@ static char SearchPath(struct PathSearcher *ps) {
static char *Commandv(struct PathSearcher *ps, int os, char *name,
const char *syspath) {
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
if (ps->literally || MemChr(ps->name, '/', ps->namelen)) return name;
if (!(ps->namelen = StrLen((ps->name = name))))
return 0;
if (ps->literally || MemChr(ps->name, '/', ps->namelen))
return name;
ps->os = os;
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
if (ps->namelen + 1 > sizeof(ps->path)) return 0;
if (ps->namelen + 1 > sizeof(ps->path))
return 0;
ps->path[0] = 0;
if (SearchPath(ps)) {
return ps->path;
@@ -638,7 +678,8 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
Pexit(os, exe, 0, "ELF segments overlap your APE loader");
}
for (j = i + 1; j < e->e_phnum; ++j) {
if (p[j].p_type != PT_LOAD) continue;
if (p[j].p_type != PT_LOAD)
continue;
c = p[j].p_vaddr & -pagesz;
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
if (MAX(a, c) < MIN(b, d)) {
@@ -671,7 +712,8 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
if (e->e_type == ET_DYN) {
rc = Mmap(0, virtmax - virtmin, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0, os);
if (rc < 0) Pexit(os, exe, rc, "pie mmap");
if (rc < 0)
Pexit(os, exe, rc, "pie mmap");
dynbase = rc;
if (dynbase & (pagesz - 1)) {
Pexit(os, exe, 0, "OS mmap incongruent w/ AT_PAGESZ");
@@ -687,14 +729,18 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
for (i = 0; i < e->e_phnum; ++i) {
void *addr;
unsigned long size;
if (p[i].p_type != PT_LOAD) continue;
if (p[i].p_type != PT_LOAD)
continue;
/* configure mapping */
prot = 0;
flags = MAP_FIXED | MAP_PRIVATE;
if (p[i].p_flags & PF_R) prot |= PROT_READ;
if (p[i].p_flags & PF_W) prot |= PROT_WRITE;
if (p[i].p_flags & PF_X) prot |= PROT_EXEC;
if (p[i].p_flags & PF_R)
prot |= PROT_READ;
if (p[i].p_flags & PF_W)
prot |= PROT_WRITE;
if (p[i].p_flags & PF_X)
prot |= PROT_EXEC;
if (p[i].p_filesz) {
/* load from file */
@@ -721,17 +767,21 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz));
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
rc = Mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz, os);
if (rc < 0) Pexit(os, exe, rc, "prog mmap");
if (wipe) Bzero((void *)(dynbase + a), wipe);
if (rc < 0)
Pexit(os, exe, rc, "prog mmap");
if (wipe)
Bzero((void *)(dynbase + a), wipe);
if (prot2 != prot1) {
rc = Mprotect(addr, size, prot2, os);
if (rc < 0) Pexit(os, exe, rc, "prog mprotect");
if (rc < 0)
Pexit(os, exe, rc, "prog mprotect");
}
/* allocate extra bss */
if (c > b) {
flags |= MAP_ANONYMOUS;
rc = Mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0, os);
if (rc < 0) Pexit(os, exe, rc, "extra bss mmap");
if (rc < 0)
Pexit(os, exe, rc, "extra bss mmap");
}
} else {
/* allocate pure bss */
@@ -739,7 +789,8 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_memsz;
flags |= MAP_ANONYMOUS;
rc = Mmap(addr, size, prot, flags, -1, 0, os);
if (rc < 0) Pexit(os, exe, rc, "bss mmap");
if (rc < 0)
Pexit(os, exe, rc, "bss mmap");
}
}
@@ -760,7 +811,8 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
struct ElfPhdr *p;
/* validate page size */
if (!pagesz) pagesz = 4096;
if (!pagesz)
pagesz = 4096;
if (pagesz & (pagesz - 1)) {
Pexit(os, exe, 0, "AT_PAGESZ isn't two power");
}
@@ -785,6 +837,10 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
return "couldn't find ELF header with x86-64 machine type";
}
#endif
if ((e->e_flags & EF_APE_MODERN_MASK) != EF_APE_MODERN && sp[0] > 0) {
/* change argv[0] to resolved path for older binaries */
((char **)(sp + 1))[0] = exe;
}
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
Pexit(os, exe, 0, "e_phentsize is wrong");
}
@@ -795,8 +851,10 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
/* read program headers */
rc = Pread(fd, M->phdr.buf, size, e->e_phoff, os);
if (rc < 0) return "failed to read ELF program headers";
if (rc != size) return "truncated read of ELF program headers";
if (rc < 0)
return "failed to read ELF program headers";
if (rc != size)
return "truncated read of ELF program headers";
/* bail on recoverable program header errors */
p = &M->phdr.phdr;
@@ -876,7 +934,7 @@ __attribute__((__noreturn__)) static void ShowUsage(int os, int fd, int rc) {
"NAME\n"
"\n"
" actually portable executable loader version " APE_VERSION_STR "\n"
" copyright 2023 justine alexandra roberts tunney\n"
" copyrights 2024 justine alexandra roberts tunney\n"
" https://justine.lol/ape.html\n"
"\n"
"USAGE\n"
@@ -901,7 +959,7 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
long *auxv, *ap, *endp, *sp2;
char *p, *pe, *exe, *prog, **argv, **envp;
(void)Utox;
(void)Printf;
/* detect freebsd */
if (SupportsXnu() && dl == XNU) {
@@ -926,7 +984,8 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
/* determine ape loader program name */
ape = argv[0];
if (!ape) ape = "ape";
if (!ape)
ape = "ape";
/* detect openbsd */
if (SupportsOpenbsd() && !os && !auxv[0]) {
@@ -947,6 +1006,7 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
} else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) {
os = NETBSD;
} else if (SupportsLinux() && ap[0] == AT_FLAGS) {
// TODO(mrdomino): maybe set/insert this when we are called as "ape -".
arg0 = !!(ap[1] & AT_FLAGS_PRESERVE_ARGV0);
}
}
@@ -978,7 +1038,8 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
ShowUsage(os, 2, 1);
} else {
if (argv[1][0] == '-') {
rc = !(argv[1][1] == 'h' && !argv[1][2]) || !StrCmp(argv[1] + 1, "-help");
rc = !((argv[1][1] == 'h' && !argv[1][2]) ||
!StrCmp(argv[1] + 1, "-help"));
ShowUsage(os, 1 + rc, rc);
}
prog = (char *)sp[2];
@@ -996,7 +1057,8 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
grows down the alloc by poking the guard pages */
n = (endp - sp + 1) * sizeof(long);
sp2 = (long *)__builtin_alloca(n);
if ((long)sp2 & 15) ++sp2;
if ((long)sp2 & 15)
++sp2;
for (; n > 0; n -= pagesz) {
((char *)sp2)[n - 1] = 0;
}
+15 -26
View File
@@ -132,7 +132,7 @@
#define SHSTUB2(SYM, X) \
HIDDEN(SYM##_bcs0 = BCD_LEFT(X)); \
HIDDEN(SYM##_bcs1 = BCD_RIGHT(X))
#define BCD_SMEAR(X) ((X) + (X) * 10000)
#define BCD_SMEAR(X) ((X) + (X)*10000)
#define BCD_LEFT(X) \
(((X)) < 10000 ? BCD_RIGHT(BCD_SMEAR(X)) | 0x10 \
: (X) < 100000 ? BCD_RIGHT(BCD_SMEAR((X) / 10)) \
@@ -140,23 +140,16 @@
: (X) < 10000000 ? BCD_RIGHT(BCD_SMEAR((X) / 1000)) \
: (X) < 100000000 ? BCD_RIGHT(BCD_SMEAR((X) / 10000)) \
: 0xffffffffffffffff)
#define BCD_RIGHT(X) \
(((X)) < 10000 ? 0x20202020 \
: (X) < 100000 ? 0x20202030 + \
(X) % 10 \
: (X) < 1000000 ? 0x20203030 + \
((X) / 10) % 10 + \
(X) % 10 * 0x100 \
: (X) < 10000000 ? 0x20303030 + \
((X) / 100) % 10 + \
((X) / 10) % 10 * 0x100 + \
(X) % 10 * 0x10000 \
: (X) < 100000000 ? 0x30303030 + \
((X) / 1000) % 10 + \
((X) / 100) % 10 * 0x100 + \
((X) / 10) % 10 * 0x10000 + \
(X) % 10 * 0x1000000 \
: 0xffffffffffffffff)
#define BCD_RIGHT(X) \
(((X)) < 10000 ? 0x20202020 \
: (X) < 100000 ? 0x20202030 + (X) % 10 \
: (X) < 1000000 ? 0x20203030 + ((X) / 10) % 10 + (X) % 10 * 0x100 \
: (X) < 10000000 ? 0x20303030 + ((X) / 100) % 10 + \
((X) / 10) % 10 * 0x100 + (X) % 10 * 0x10000 \
: (X) < 100000000 \
? 0x30303030 + ((X) / 1000) % 10 + ((X) / 100) % 10 * 0x100 + \
((X) / 10) % 10 * 0x10000 + (X) % 10 * 0x1000000 \
: 0xffffffffffffffff)
/**
* Laying out the GDT entries for a TSS for bare metal operation.
@@ -165,15 +158,11 @@
HIDDEN(SYM##_desc_ent0 = TSSDESC_ENT0(BASE, LIM)); \
HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \
ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat")
#define TSSDESC_ENT0(BASE, LIM) \
(((LIM) << 0 & 0x000000000000ffff) | \
((BASE) << 16 & 0x000000ffffff0000) | \
0x89 << 40 | \
((LIM) >> 16 << 48 & 0x000f000000000000) | \
0x2 << 52 | \
#define TSSDESC_ENT0(BASE, LIM) \
(((LIM) << 0 & 0x000000000000ffff) | ((BASE) << 16 & 0x000000ffffff0000) | \
0x89 << 40 | ((LIM) >> 16 << 48 & 0x000f000000000000) | 0x2 << 52 | \
((BASE) >> 24 << 56 & 0xff00000000000000))
#define TSSDESC_ENT1(BASE) \
((BASE) >> 32 << 0 & 0x00000000ffffffff)
#define TSSDESC_ENT1(BASE) ((BASE) >> 32 << 0 & 0x00000000ffffffff)
#endif /* __ASSEMBLER__ */
#endif /* APE_MACROS_H_ */
+9 -5
View File
@@ -2,7 +2,7 @@
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
COSMOPOLITAN_C_START_
extern const char __comment_start[] __attribute__((__weak__));
extern const char __notices[] __attribute__((__weak__));
extern unsigned char __executable_start[] __attribute__((__weak__));
extern unsigned char __privileged_start[] __attribute__((__weak__));
extern unsigned char _ehead[] __attribute__((__weak__));
@@ -16,12 +16,16 @@ extern unsigned char _tdata_end[] __attribute__((__weak__));
extern unsigned char _tbss_start[] __attribute__((__weak__));
extern unsigned char _tbss_end[] __attribute__((__weak__));
extern unsigned char _tls_align[] __attribute__((__weak__));
extern unsigned char _tdata_align[] __attribute__((__weak__));
extern unsigned char _tbss_align[] __attribute__((__weak__));
extern unsigned char __test_start[] __attribute__((__weak__));
extern unsigned char __ro[] __attribute__((__weak__));
extern uint8_t __data_start[] __attribute__((__weak__));
extern uint8_t __data_end[] __attribute__((__weak__));
extern uint8_t __bss_start[] __attribute__((__weak__));
extern uint8_t __bss_end[] __attribute__((__weak__));
extern unsigned char __data_start[] __attribute__((__weak__));
extern unsigned char __data_end[] __attribute__((__weak__));
extern unsigned char __bss_start[] __attribute__((__weak__));
extern unsigned char __bss_end[] __attribute__((__weak__));
extern unsigned long __got_start[] __attribute__((__weak__));
extern unsigned long __got_end[] __attribute__((__weak__));
extern unsigned char ape_phdrs[] __attribute__((__weak__));
COSMOPOLITAN_C_END_
Binary file not shown.
Binary file not shown.
Binary file not shown.
File renamed without changes.
Binary file not shown.
File renamed without changes.
BIN
View File
Binary file not shown.
Binary file not shown.
File renamed without changes.
File renamed without changes.
BIN
View File
Binary file not shown.
+58
View File
@@ -0,0 +1,58 @@
--nocompress-debug-sections
--noexecstack
-Wa,--nocompress-debug-sections
-Wa,--noexecstack
-Wa,-msse2avx
-Werror=maybe-uninitialized
-Wno-literal-suffix
-Wno-unused-but-set-variable
-Wunsafe-loop-optimizations
-fbranch-target-load-optimize
-fcx-limited-range
-fdelete-dead-exceptions
-femit-struct-debug-baseonly
-ffp-int-builtin-inexact
-finline-functions-called-once
-fipa-pta
-fivopts
-flimit-function-alignment
-fmerge-constants
-fmodulo-sched
-fmodulo-sched-allow-regmoves
-fno-align-jumps
-fno-align-labels
-fno-align-loops
-fno-code-hoisting
-fno-cx-limited-range
-fno-fp-int-builtin-inexact
-fno-gnu-unique
-fno-inline-functions-called-once
-fno-instrument-functions
-fno-schedule-insns2
-fno-whole-program
-fopt-info-vec
-fopt-info-vec-missed
-freg-struct-return
-freschedule-modulo-scheduled-loops
-frounding-math
-fsched2-use-superblocks
-fschedule-insns
-fschedule-insns2
-fshrink-wrap
-fshrink-wrap-separate
-fsignaling-nans
-fstack-clash-protection
-ftracer
-ftrapv
-ftree-loop-im
-ftree-loop-vectorize
-funsafe-loop-optimizations
-fversion-loops-for-strides
-fwhole-program
-gdescribe-dies
-gstabs
-mcall-ms2sysv-xlogues
-mdispatch-scheduler
-mfpmath=sse+387
-mmitigate-rop
-mno-fentry
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+11 -11
View File
@@ -11,20 +11,20 @@
#
ifeq ($(MODE),)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
CONFIG_CPPFLAGS += -DSYSDEBUG
TARGET_ARCH ?= -msse3
endif
ifeq ($(MODE), x86_64)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
CONFIG_CPPFLAGS += -DSYSDEBUG
endif
ifeq ($(MODE), aarch64)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
CONFIG_CPPFLAGS += -DSYSDEBUG
endif
@@ -38,13 +38,13 @@ endif
#
ifeq ($(MODE), zero)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
OVERRIDE_CFLAGS += -O0
OVERRIDE_CXXFLAGS += -O0
CONFIG_CPPFLAGS += -DSYSDEBUG
endif
ifeq ($(MODE), aarch64-zero)
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
OVERRIDE_CFLAGS += -O0 -fdce
OVERRIDE_CXXFLAGS += -O0 -fdce
CONFIG_CPPFLAGS += -DSYSDEBUG
@@ -81,7 +81,7 @@ endif
#
ifeq ($(MODE), opt)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
CONFIG_CCFLAGS += $(BACKTRACES) -O3 -fmerge-all-constants
TARGET_ARCH ?= -march=native
@@ -98,7 +98,7 @@ endif
# - Turns off support for other operating systems
#
ifeq ($(MODE), optlinux)
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
CONFIG_COPTS += -mred-zone
@@ -140,7 +140,7 @@ endif
#
ifeq ($(MODE), asan)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -D__SANITIZE_ADDRESS__
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
CONFIG_COPTS += -fsanitize=address
@@ -160,7 +160,7 @@ endif
#
ifeq ($(MODE), dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ -D__SANITIZE_UNDEFINED__
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
@@ -170,7 +170,7 @@ QUOTA ?= -C64 -L300
endif
ifeq ($(MODE), aarch64-dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline -fdce
CONFIG_COPTS += -fsanitize=undefined
@@ -189,7 +189,7 @@ endif
#
ifeq ($(MODE), sysv)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CCFLAGS += $(BACKTRACES) -O2
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
TARGET_ARCH ?= -msse3
+11 -9
View File
@@ -54,19 +54,16 @@
#
ifeq ($(LANDLOCKMAKE_VERSION),)
TMPSAFE = $(join $(TMPDIR),$(subst /,_,$@)).tmp
TMPSAFE = $(join $(TMPDIR)/,$(subst /,_,$@)).tmp
else
TMPSAFE = $(TMPDIR)/
endif
BACKTRACES = \
-fno-schedule-insns2 \
-fno-optimize-sibling-calls \
-mno-omit-leaf-frame-pointer
ifneq ($(ARCH), aarch64)
BACKTRACES += -fno-schedule-insns2
endif
SANITIZER = \
-fsanitize=address
@@ -93,7 +90,6 @@ DEFAULT_CCFLAGS += \
-frecord-gcc-switches
DEFAULT_COPTS ?= \
-fno-math-errno \
-fno-ident \
-fno-common \
-fno-gnu-unique \
@@ -128,6 +124,7 @@ ifeq ($(ARCH), aarch64)
DEFAULT_COPTS += \
-ffixed-x18 \
-ffixed-x28 \
-fsigned-char \
-mno-outline-atomics
endif
@@ -138,6 +135,8 @@ MATHEMATICAL = \
DEFAULT_CPPFLAGS += \
-D_COSMO_SOURCE \
-DMODE='"$(MODE)"' \
-Wno-prio-ctor-dtor \
-Wno-unknown-pragmas \
-nostdinc \
-iquote. \
-isystem libc/isystem
@@ -146,12 +145,14 @@ DEFAULT_CFLAGS = \
-std=gnu2x
DEFAULT_CXXFLAGS = \
-std=gnu++20 \
-fno-rtti \
-fno-exceptions \
-fuse-cxa-atexit \
-Wno-int-in-bool-context \
-Wno-narrowing \
-Wno-literal-suffix
-Wno-literal-suffix \
-isystem third_party/libcxx
DEFAULT_ASFLAGS = \
-W \
@@ -163,6 +164,7 @@ DEFAULT_LDFLAGS = \
-nostdlib \
-znorelro \
--gc-sections \
-z noexecstack \
--build-id=none \
--no-dynamic-linker
@@ -257,12 +259,12 @@ LD.libs = \
$(LIBS)
COMPILE.c.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(c.flags)
COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(cxx.flags)
COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cxx.flags) $(cpp.flags)
COMPILE.i.flags = $(cc.flags) $(copt.flags) $(c.flags)
COMPILE.ii.flags = $(cc.flags) $(copt.flags) $(cxx.flags)
LINK.flags = $(DEFAULT_LDFLAGS) $(CONFIG_LDFLAGS) $(LDFLAGS)
OBJECTIFY.c.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(c.flags)
OBJECTIFY.cxx.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(cxx.flags)
OBJECTIFY.cxx.flags = $(cc.flags) $(o.flags) $(S.flags) $(cxx.flags) $(cpp.flags) $(copt.flags)
OBJECTIFY.s.flags = $(ASONLYFLAGS) $(s.flags)
OBJECTIFY.S.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags)
PREPROCESS.flags = -E $(copt.flags) $(cc.flags) $(cpp.flags)
+12 -2
View File
@@ -29,7 +29,14 @@ if ! UNZIP=$(command -v unzip 2>/dev/null); then
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/unzip and put it on the system path" >&2
abort
fi
if ! SHA256SUM=$(command -v sha256sum 2>/dev/null); then
if command -v sha256sum >/dev/null 2>&1; then
# can use system sha256sum
true
elif command -v shasum >/dev/null 2>&1; then
sha256sum() {
shasum -a 256 "$@"
}
else
if [ ! -f build/sha256sum.c ]; then
printf '%s\n' "$0: fatal error: you need to install sha256sum" >&2
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/sha256sum and put it on the system path" >&2
@@ -51,6 +58,9 @@ if ! SHA256SUM=$(command -v sha256sum 2>/dev/null); then
"${CC}" -w -O2 -o "${SHA256SUM}.$$" build/sha256sum.c || abort
mv -f "${SHA256SUM}.$$" "${SHA256SUM}" || abort
fi
sha256sum() {
"${SHA256SUM}" "$@"
}
fi
if WGET=$(command -v wget 2>/dev/null); then
DOWNLOAD=$WGET
@@ -82,7 +92,7 @@ if ! "${DOWNLOAD}" ${DOWNLOAD_ARGS} cosmocc.zip "${URL1}"; then
"${DOWNLOAD}" ${DOWNLOAD_ARGS} cosmocc.zip "${URL2}" || die
fi
printf '%s\n' "${COSMOCC_SHA256SUM} *cosmocc.zip" >cosmocc.zip.sha256sum
"${SHA256SUM}" -c cosmocc.zip.sha256sum || die
sha256sum -c cosmocc.zip.sha256sum || die
"${UNZIP}" cosmocc.zip || die
rm -f cosmocc.zip cosmocc.zip.sha256sum
+2 -2
View File
@@ -55,7 +55,7 @@ set -- --regex-c='/_Atomic(\([^)]*\))/\1/b' "$@"
set -- --regex-c='/^\(\(hidden\|extern\|const\) \)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)/\4/b' "$@"
# ctags doesn't understand function prototypes, e.g.
# bool isheap(void *p) dontthrow nocallback;
# bool isheap(void *p) dontthrow dontcallback;
set -- --regex-c='/^[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)(.*/\2/b' "$@"
# ctags doesn't understand function pointers, e.g.
@@ -66,7 +66,7 @@ set -- --regex-c='/^extern [^(]*(\*const \([^)]*\))(/\1/b' "$@"
# struct WorstSoftwareEver;
set -- --regex-c='/^struct.*;$/uehocruehcroue/b' "$@"
exec $TAGS \
build/run $TAGS \
-e \
--langmap=c:.c.h \
--exclude=libc/nt/struct/imagefileheader.internal.h \
+8 -8
View File
@@ -6,14 +6,14 @@ if [ -n "$OBJDUMP" ]; then
fi
find_objdump() {
if [ -x cosmocc/3.2/bin/$1-linux-cosmo-objdump ]; then
OBJDUMP=cosmocc/3.2/bin/$1-linux-cosmo-objdump
elif [ -x cosmocc/3.2/bin/$1-linux-musl-objdump ]; then
OBJDUMP=cosmocc/3.2/bin/$1-linux-musl-objdump
elif [ -x "$COSMO/cosmocc/3.2/bin/$1-linux-cosmo-objdump" ]; then
OBJDUMP="$COSMO/cosmocc/3.2/bin/$1-linux-cosmo-objdump"
elif [ -x "$COSMO/cosmocc/3.2/bin/$1-linux-musl-objdump" ]; then
OBJDUMP="$COSMO/cosmocc/3.2/bin/$1-linux-musl-objdump"
if [ -x .cosmocc/3.3.5/bin/$1-linux-cosmo-objdump ]; then
OBJDUMP=.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump
elif [ -x .cosmocc/3.3.5/bin/$1-linux-musl-objdump ]; then
OBJDUMP=.cosmocc/3.3.5/bin/$1-linux-musl-objdump
elif [ -x "$COSMO/.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump"
elif [ -x "$COSMO/.cosmocc/3.3.5/bin/$1-linux-musl-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.3.5/bin/$1-linux-musl-objdump"
else
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
exit 1
+8 -7
View File
@@ -22,13 +22,14 @@
# - tool/build/runit.c
# - tool/build/runitd.c
.PRECIOUS: o/$(MODE)/%.com.ok
o/$(MODE)/%.com.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet
o/$(MODE)/%.com.ok: \
o/$(MODE)/tool/build/runit.com \
o/$(MODE)/tool/build/runitd.com \
o/$(MODE)/%.com
.PRECIOUS: o/$(MODE)/%.ok
o/$(MODE)/%.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet dns
o/$(MODE)/%.ok: private .UNVEIL += r:/etc/resolv.conf
o/$(MODE)/%.ok: \
o/$(MODE)/tool/build/runit \
o/$(MODE)/tool/build/runitd \
o/$(MODE)/%
@$(COMPILE) -wATEST -tT$@ $^ $(HOSTS)
.PHONY:
o/tiny/tool/build/runit.com:
o/tiny/tool/build/runit:
+18 -31
View File
@@ -39,6 +39,10 @@ o/$(MODE)/%.h: %.c
o/$(MODE)/%.o: %.cc
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
o/$(MODE)/%.o: %.cpp
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.lds: %.lds
@$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
@@ -75,17 +79,17 @@ o/$(MODE)/%.pkg:
$(file >$(TMPSAFE).args,$(filter %.o,$^))
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com
@$(COMPILE) -wAPYOBJ o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj
@$(COMPILE) -wAPYOBJ o/$(MODE)/third_party/python/pyobj $(PYFLAGS) -o $@ $<
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com
@$(COMPILE) -wAPYCOMP o/$(MODE)/third_party/python/pycomp.com $(PYCFLAGS) -o $@ $<
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp
@$(COMPILE) -wAPYCOMP o/$(MODE)/third_party/python/pycomp $(PYCFLAGS) -o $@ $<
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
@$(COMPILE) -wALUAC o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac
@$(COMPILE) -wALUAC o/$(MODE)/third_party/lua/luac -s -o $@ $<
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean.com
@$(COMPILE) -wALUA -tT$@ o/$(MODE)/tool/net/redbean.com $(LUAFLAGS) -i $<
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean
@$(COMPILE) -wALUA -tT$@ o/$(MODE)/tool/net/redbean $(LUAFLAGS) -i $<
################################################################################
# LOCAL UNIT TESTS
@@ -104,22 +108,22 @@ o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean.com
#
# You could then run a command like:
#
# make -j8 o//test/libc/calls/openbsd_test.com.runs
# make -j8 o//test/libc/calls/openbsd_test.runs
#
# You need PROT_EXEC permission since ftrace morphs the binary. It's
# also worth mentioning that the pledge.com command can simulate what
# also worth mentioning that the pledge command can simulate what
# Landlock Make does:
#
# o//tool/build/pledge.com \
# o//tool/build/pledge \
# -v. -p 'stdio rpath wpath cpath tty prot_exec' \
# o//test/libc/calls/openbsd_test.com \
# o//test/libc/calls/openbsd_test \
# ----ftrace
#
# This is useful in the event a test binary should run by itself, but
# fails to run beneath Landlock Make. It's also useful sometimes to
# override the verbosity when running tests:
#
# make V=5 TESTARGS=-b o//test/libc/calls/openbsd_test.com.runs
# make V=5 TESTARGS=-b o//test/libc/calls/openbsd_test.runs
#
# This way, if for some reason a test should fail but calls exit(0),
# then the stdout/stderr output, which would normally be suppressed,
@@ -131,7 +135,7 @@ o/$(MODE)/%.runs: o/$(MODE)/%
################################################################################
# ELF ZIP FILES
#
# zipobj.com lets us do fast incremental linking of compressed data.
# zipobj lets us do fast incremental linking of compressed data.
# it's nice because if we link a hundred binaries that use the time zone
# database, then that database only needs to be DEFLATE'd once.
@@ -179,23 +183,6 @@ o/$(MODE)/%.okk: private .UNSANDBOXED = 1
o/$(MODE)/%.okk: %
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
################################################################################
# EXECUTABLE HELPERS
MAKE_SYMTAB_CREATE = \
$(COMPILE) -wASYMTAB \
o/$(MODE)/tool/build/symtab.com \
-o $(TMPSAFE)/.symtab \
$<
MAKE_SYMTAB_ZIP = \
$(COMPILE) -AZIP -T$@ \
o/$(MODE)/third_party/zip/zip.com \
-b$(TMPDIR) \
-9qj \
$@ \
$(TMPSAFE)/.symtab
################################################################################
# EMACS ASSEMBLY GENERATION
+4 -5
View File
@@ -1,9 +1,8 @@
#!/bin/sh
if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then
if [ ! -f o/third_party/qemu/qemu-aarch64 ]; then
make -j8 o/third_party/qemu/qemu-aarch64
fi
exec o/third_party/qemu/qemu-aarch64 "$@"
UNAMEM=$(uname -m)
UNAMES=$(uname -s)
if [ x"$UNAMES" = x"Darwin" ] && [ x"$UNAMEM" = x"arm64" ]; then
exec ape "$@"
else
exec "$@"
fi
+455
View File
@@ -0,0 +1,455 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2022 Justine Alexandra Roberts Tunney │
│ │
│ Permission to use, copy, modify, and/or distribute this software for │
│ any purpose with or without fee is hereby granted, provided that the │
│ above copyright notice and this permission notice appear in all copies. │
│ │
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// this file should not have dependencies, because everything will be
// re-downloaded if the o/tool/sha256sum artifact becomes invalidated
#define PROG "sha256sum"
#define USAGE \
"\
Usage: " PROG " [-?hbctw] [PATH...]\n\
-h help\n\
-c check mode\n\
-b binary mode\n\
-t textual mode\n\
-w warning mode\n"
#define ROTR(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define EP1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SIG0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3))
#define SIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10))
struct Sha256Ctx {
uint8_t data[64];
uint32_t datalen;
uint64_t bitlen;
uint32_t state[8];
};
static const uint32_t kSha256Tab[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, //
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, //
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, //
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, //
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, //
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, //
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, //
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, //
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, //
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, //
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, //
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, //
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, //
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, //
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, //
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, //
};
static bool g_warn;
static char g_mode;
static bool g_check;
static int g_mismatches;
static void Sha256Transform(uint32_t state[8], const uint8_t data[64]) {
unsigned i;
uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64];
for (i = 0; i < 16; ++i, data += 4) {
m[i] = (uint32_t)data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
}
for (; i < 64; ++i) {
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
}
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e, f, g) + kSha256Tab[i] + m[i];
t2 = EP0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
}
static void Sha256Init(struct Sha256Ctx *ctx) {
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
static void Sha256Update(struct Sha256Ctx *ctx, const uint8_t *data,
long size) {
long i;
for (i = 0; i < size; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
Sha256Transform(ctx->state, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
static void Sha256Final(struct Sha256Ctx *ctx, uint8_t *hash) {
long i;
i = ctx->datalen;
ctx->data[i++] = 0x80;
if (ctx->datalen < 56) {
memset(ctx->data + i, 0, 56 - i);
} else {
memset(ctx->data + i, 0, 64 - i);
Sha256Transform(ctx->state, ctx->data);
memset(ctx->data, 0, 56);
}
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
Sha256Transform(ctx->state, ctx->data);
for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0xff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0xff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0xff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0xff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0xff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0xff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0xff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0xff;
}
}
static char *FormatUint32(char *p, uint32_t x) {
char t;
size_t i, a, b;
i = 0;
do {
p[i++] = x % 10 + '0';
x = x / 10;
} while (x > 0);
p[i] = '\0';
if (i) {
for (a = 0, b = i - 1; a < b; ++a, --b) {
t = p[a];
p[a] = p[b];
p[b] = t;
}
}
return p + i;
}
static char *FormatInt32(char *p, int32_t x) {
if (x < 0)
*p++ = '-', x = -(uint32_t)x;
return FormatUint32(p, x);
}
static size_t StrCat(char *dst, const char *src, size_t dsize) {
size_t m, n = dsize;
const char *p = dst;
const char *q = src;
while (n-- != 0 && *dst != '\0')
dst++;
m = dst - p;
n = dsize - m;
if (n-- == 0) {
return m + strlen(src);
}
while (*src != '\0') {
if (n != 0) {
*dst++ = *src;
n--;
}
src++;
}
*dst = '\0';
return m + (src - q);
}
static void GetOpts(int argc, char *argv[]) {
int opt;
g_mode = ' ';
while ((opt = getopt(argc, argv, "?hbctw")) != -1) {
switch (opt) {
case 'w':
g_warn = true;
break;
case 'c':
g_check = true;
break;
case 't':
g_mode = ' ';
break;
case 'b':
g_mode = '*';
break;
case 'h':
case '?':
(void)write(1, USAGE, sizeof(USAGE) - 1);
exit(0);
default:
(void)write(2, USAGE, sizeof(USAGE) - 1);
exit(64);
}
}
}
static void Write(int fd, const char *s, ...) {
va_list va;
char buf[512];
buf[0] = 0;
va_start(va, s);
do {
StrCat(buf, s, sizeof(buf));
} while ((s = va_arg(va, const char *)));
va_end(va);
(void)write(fd, buf, strlen(buf));
}
static bool IsModeCharacter(char c) {
switch (c) {
case ' ':
case '*':
return true;
default:
return false;
}
}
static bool IsSupportedPath(const char *path) {
size_t i;
for (i = 0;; ++i) {
switch (path[i]) {
case 0:
if (i)
return true;
// fallthrough
case '\r':
case '\n':
case '\\':
Write(2, PROG, ": ", path, ": unsupported path\n", NULL);
return false;
default:
break;
}
}
}
static bool GetDigest(const char *path, FILE *f, uint8_t digest[32]) {
size_t got;
uint8_t buf[512];
struct Sha256Ctx ctx;
Sha256Init(&ctx);
while ((got = fread(buf, 1, sizeof(buf), f))) {
Sha256Update(&ctx, buf, got);
}
if (ferror(f)) {
Write(2, PROG, ": ", path, ": ", strerror(errno), "\n", NULL);
return false;
}
Sha256Final(&ctx, digest);
return true;
}
static char *CopyHex(char *s, const void *p, size_t n) {
const char *d, *e;
for (d = (const char *)p, e = d + n; d < e; ++d) {
*s++ = "0123456789abcdef"[(*d >> 4) & 15];
*s++ = "0123456789abcdef"[(*d >> 0) & 15];
}
*s = 0;
return s;
}
static bool ProduceDigest(const char *path, FILE *f) {
char hexdigest[65];
char mode[2] = {g_mode};
unsigned char digest[32];
if (!IsSupportedPath(path))
return false;
if (!GetDigest(path, f, digest))
return false;
CopyHex(hexdigest, digest, 32);
Write(1, hexdigest, " ", mode, path, "\n", NULL);
return true;
}
static char *Chomp(char *line) {
size_t i;
if (line) {
for (i = strlen(line); i--;) {
if (line[i] == '\r' || line[i] == '\n') {
line[i] = '\0';
} else {
break;
}
}
}
return line;
}
static int HexToInt(int c) {
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('a' <= c && c <= 'f') {
return c - 'a' + 10;
} else if ('A' <= c && c <= 'F') {
return c - 'A' + 10;
} else {
return -1;
}
}
static bool CheckDigests(const char *path, FILE *f) {
FILE *f2;
bool k = true;
int a, b, i, line;
const char *path2, *status;
uint8_t wantdigest[32], gotdigest[32];
char buf[64 + 2 + PATH_MAX + 1 + 1], *p;
for (line = 0; fgets(buf, sizeof(buf), f); ++line) {
if (!*Chomp(buf))
continue;
for (p = buf, i = 0; i < 32; ++i) {
if ((a = HexToInt(*p++ & 255)) == -1)
goto InvalidLine;
if ((b = HexToInt(*p++ & 255)) == -1)
goto InvalidLine;
wantdigest[i] = a << 4 | b;
}
if (*p++ != ' ')
goto InvalidLine;
if (!IsModeCharacter(*p++))
goto InvalidLine;
path2 = p;
if (!*path2)
goto InvalidLine;
if (!IsSupportedPath(path2))
continue;
if ((f2 = fopen(path2, "rb"))) {
if (GetDigest(path2, f2, gotdigest)) {
if (!memcmp(wantdigest, gotdigest, 32)) {
status = "OK";
} else {
status = "FAILED";
++g_mismatches;
k = false;
}
Write(1, path2, ": ", status, "\n", NULL);
} else {
k = false;
}
fclose(f2);
} else {
Write(2, PROG, ": ", path2, ": ", strerror(errno), "\n", NULL);
k = false;
}
continue;
InvalidLine:
if (g_warn) {
char linestr[12];
FormatInt32(linestr, line + 1);
Write(2, PROG, ": ", path, ":", linestr, ": ",
"improperly formatted checksum line", "\n", NULL);
}
}
if (ferror(f)) {
Write(2, PROG, ": ", path, ": ", strerror(errno), "\n", NULL);
k = false;
}
return k;
}
static bool Process(const char *path, FILE *f) {
if (g_check) {
return CheckDigests(path, f);
} else {
return ProduceDigest(path, f);
}
}
int main(int argc, char *argv[]) {
int i;
FILE *f;
bool k = true;
GetOpts(argc, argv);
if (optind == argc) {
f = stdin;
k &= Process("-", f);
} else {
for (i = optind; i < argc; ++i) {
if ((f = fopen(argv[i], "rb"))) {
k &= Process(argv[i], f);
fclose(f);
} else {
Write(2, PROG, ": ", argv[i], ": ", strerror(errno), "\n", NULL);
k = false;
}
}
}
if (g_mismatches) {
char ibuf[12];
FormatInt32(ibuf, g_mismatches);
Write(2, PROG, ": WARNING: ", ibuf, " computed checksum did NOT match\n",
NULL);
}
return !k;
}
+13
View File
@@ -0,0 +1,13 @@
---
BasedOnStyle: Mozilla
IndentWidth: 4
ColumnLimit: 80
---
Language: Cpp
AllowShortFunctionsOnASingleLine: false
AlignTrailingComments: false
AlignEscapedNewlines: DontAlign
AlwaysBreakTemplateDeclarations: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
FixNamespaceComments: true
---
+48
View File
@@ -0,0 +1,48 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
PKGS += CTL
CTL_ARTIFACTS += CTL_A
CTL = $(CTL_A_DEPS) $(CTL_A)
CTL_A = o/$(MODE)/ctl/ctl.a
CTL_A_FILES := $(wildcard ctl/*)
CTL_A_HDRS = $(filter %.h,$(CTL_A_FILES))
CTL_A_SRCS = $(filter %.cc,$(CTL_A_FILES))
CTL_A_OBJS = $(CTL_A_SRCS:%.cc=o/$(MODE)/%.o)
CTL_A_CHECKS = \
$(CTL_A).pkg \
$(CTL_A_HDRS:%=o/$(MODE)/%.okk) \
CTL_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_MEM \
LIBC_STR \
CTL_A_DEPS := $(call uniq,$(foreach x,$(CTL_A_DIRECTDEPS),$($(x))))
$(CTL_A): ctl/ \
$(CTL_A).pkg \
$(CTL_A_OBJS)
$(CTL_A).pkg: \
$(CTL_A_OBJS) \
$(foreach x,$(CTL_A_DIRECTDEPS),$($(x)_A).pkg)
$(CTL_A_OBJS): private \
OVERRIDE_CXXFLAGS += \
-Wframe-larger-than=4096 \
-Walloca-larger-than=4096 \
-ffunction-sections \
-fdata-sections \
CTL_LIBS = $(foreach x,$(CTL_ARTIFACTS),$($(x)))
CTL_SRCS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_SRCS))
CTL_HDRS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_HDRS))
CTL_CHECKS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_CHECKS))
CTL_OBJS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_OBJS))
$(CTL_OBJS): $(BUILD_FILES) ctl/BUILD.mk
.PHONY: o/$(MODE)/ctl
o/$(MODE)/ctl: $(CTL_CHECKS)
+5015
View File
File diff suppressed because it is too large. Load diff
+129
View File
@@ -0,0 +1,129 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
#define COSMOPOLITAN_CTL_OPTIONAL_H_
#include <__utility/forward.h>
#include <__utility/move.h>
#include <__utility/swap.h>
namespace ctl {
template<typename T>
class optional
{
public:
using value_type = T;
~optional() = default;
optional() noexcept : present_(false)
{
}
optional(const T& value) : present_(true), value_(value)
{
}
optional(T&& value) : present_(true), value_(std::move(value))
{
}
optional(const optional& other) : present_(other.present_)
{
if (present_)
new (&value_) T(other.value_);
}
optional(optional&& other) noexcept : present_(other.present_)
{
if (present_)
value_ = std::move(other.value_);
}
optional& operator=(const optional& other)
{
if (this != &other) {
present_ = other.present_;
if (present_)
value_ = other.value_;
}
return *this;
}
optional& operator=(optional&& other) noexcept
{
if (this != &other) {
present_ = other.present_;
if (present_)
value_ = std::move(other.value_);
}
return *this;
}
T& value() &
{
if (!present_)
__builtin_trap();
return value_;
}
const T& value() const&
{
if (!present_)
__builtin_trap();
return value_;
}
T&& value() &&
{
if (!present_)
__builtin_trap();
return std::move(value_);
}
explicit operator bool() const noexcept
{
return present_;
}
bool has_value() const noexcept
{
return present_;
}
void reset() noexcept
{
if (present_) {
value_.~T();
present_ = false;
}
}
template<typename... Args>
void emplace(Args&&... args)
{
present_ = true;
value_ = T(std::forward<Args>(args)...);
}
void swap(optional& other) noexcept
{
if (present_ && other.present_) {
std::swap(value_, other.value_);
} else if (present_) {
other.emplace(std::move(value_));
reset();
} else if (other.present_) {
emplace(std::move(other.value_));
other.reset();
}
}
private:
bool present_;
T value_;
};
} // namespace ctl
#endif // COSMOPOLITAN_CTL_OPTIONAL_H_
+44
View File
@@ -0,0 +1,44 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
//
// Copyright 2024 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 "string.h"
#include <stdckdint.h>
#include <string.h>
namespace ctl {
string
strcat(const string_view lhs, const string_view rhs) noexcept
{
string res;
size_t need;
if (ckd_add(&need, lhs.n, rhs.n))
__builtin_trap();
if (ckd_add(&need, need, 1))
__builtin_trap();
res.reserve(need);
if (lhs.n)
memcpy(res.p, lhs.p, lhs.n);
if (rhs.n)
memcpy(res.p + lhs.n, rhs.p, rhs.n);
res.p[res.n = lhs.n + rhs.n] = 0;
return res;
}
} // namespace ctl
+43
View File
@@ -0,0 +1,43 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
//
// Copyright 2024 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 "string_view.h"
#include <string.h>
namespace ctl {
int
strcmp(const string_view lhs, const string_view rhs) noexcept
{
int r;
size_t m = lhs.n;
if ((m = rhs.n < m ? rhs.n : m)) {
if (!m)
return 0;
if ((r = memcmp(lhs.p, rhs.p, m)))
return r;
}
if (lhs.n == rhs.n)
return 0;
if (m < lhs.n)
return +1;
return -1;
}
} // namespace ctl
+323
View File
@@ -0,0 +1,323 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
//
// Copyright 2024 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 "string.h"
#include <__atomic/fence.h>
#include <stdckdint.h>
namespace ctl {
string::~string() noexcept
{
if (n) {
if (n >= c)
__builtin_trap();
if (p[n])
__builtin_trap();
}
if (c && !p)
__builtin_trap();
free(p);
}
string::string(const char* s) noexcept
{
append(s, strlen(s));
}
string::string(const string& s) noexcept
{
append(s.p, s.n);
}
string::string(const string_view s) noexcept
{
append(s.p, s.n);
}
string::string(size_t size, char ch) noexcept
{
resize(size, ch);
}
string::string(const char* s, size_t size) noexcept
{
append(s, size);
}
const char*
string::c_str() const noexcept
{
if (!n)
return "";
if (n >= c)
__builtin_trap();
if (p[n])
__builtin_trap();
return p;
}
void
string::reserve(size_t c2) noexcept
{
char* p2;
if (c2 < n)
c2 = n;
if (ckd_add(&c2, c2, 15))
__builtin_trap();
c2 &= -16;
if (!(p2 = (char*)realloc(p, c2)))
__builtin_trap();
std::atomic_signal_fence(std::memory_order_seq_cst);
c = c2;
p = p2;
}
void
string::resize(size_t n2, char ch) noexcept
{
size_t c2;
if (ckd_add(&c2, n2, 1))
__builtin_trap();
reserve(c2);
if (n2 > n)
memset(p + n, ch, n2 - n);
p[n = n2] = 0;
}
void
string::append(char ch) noexcept
{
if (n + 2 > c) {
size_t c2 = c + 2;
c2 += c2 >> 1;
reserve(c2);
}
p[n++] = ch;
p[n] = 0;
}
void
string::grow(size_t size) noexcept
{
size_t need;
if (ckd_add(&need, n, size))
__builtin_trap();
if (ckd_add(&need, need, 1))
__builtin_trap();
if (need <= c)
return;
size_t c2 = c;
if (!c2) {
c2 = need;
} else {
while (c2 < need)
if (ckd_add(&c2, c2, c2 >> 1))
__builtin_trap();
}
reserve(c2);
}
void
string::append(char ch, size_t size) noexcept
{
grow(size);
if (size)
memset(p + n, ch, size);
p[n += size] = 0;
}
void
string::append(const void* data, size_t size) noexcept
{
grow(size);
if (size)
memcpy(p + n, data, size);
p[n += size] = 0;
}
void
string::pop_back() noexcept
{
if (!n)
__builtin_trap();
p[--n] = 0;
}
string&
string::operator=(string&& s) noexcept
{
if (p != s.p) {
if (p) {
clear();
append(s.p, s.n);
} else {
p = s.p;
n = s.n;
c = s.c;
s.p = nullptr;
s.n = 0;
s.c = 0;
}
}
return *this;
}
bool
string::operator==(const string_view s) const noexcept
{
if (n != s.n)
return false;
if (!n)
return true;
return !memcmp(p, s.p, n);
}
bool
string::operator!=(const string_view s) const noexcept
{
if (n != s.n)
return true;
if (!n)
return false;
return !!memcmp(p, s.p, n);
}
bool
string::contains(const string_view s) const noexcept
{
if (!s.n)
return true;
return !!memmem(p, n, s.p, s.n);
}
bool
string::ends_with(const string_view s) const noexcept
{
if (n < s.n)
return false;
if (!s.n)
return true;
return !memcmp(p + n - s.n, s.p, s.n);
}
bool
string::starts_with(const string_view s) const noexcept
{
if (n < s.n)
return false;
if (!s.n)
return true;
return !memcmp(p, s.p, s.n);
}
size_t
string::find(char ch, size_t pos) const noexcept
{
char* q;
if ((q = (char*)memchr(p, ch, n)))
return q - p;
return npos;
}
size_t
string::find(const string_view s, size_t pos) const noexcept
{
char* q;
if (pos > n)
__builtin_trap();
if ((q = (char*)memmem(p + pos, n - pos, s.p, s.n)))
return q - p;
return npos;
}
string
string::substr(size_t pos, size_t count) const noexcept
{
size_t last;
if (pos > n)
__builtin_trap();
if (count > n - pos)
count = n - pos;
if (ckd_add(&last, pos, count))
last = n;
if (last > n)
__builtin_trap();
return string(p + pos, count);
}
string&
string::replace(size_t pos, size_t count, const string_view& s) noexcept
{
size_t last;
if (ckd_add(&last, pos, count))
__builtin_trap();
if (last > n)
__builtin_trap();
size_t need;
if (ckd_add(&need, pos, s.n))
__builtin_trap();
size_t extra = n - last;
if (ckd_add(&need, need, extra))
__builtin_trap();
size_t c2;
if (ckd_add(&c2, need, 1))
__builtin_trap();
reserve(c2);
if (extra)
memmove(p + pos + s.n, p + last, extra);
memcpy(p + pos, s.p, s.n);
p[n = need] = 0;
return *this;
}
string&
string::insert(size_t i, const string_view s) noexcept
{
if (i > n)
__builtin_trap();
size_t extra = n - i;
size_t need;
if (ckd_add(&need, n, s.n))
__builtin_trap();
if (ckd_add(&need, need, 1))
__builtin_trap();
reserve(need);
if (extra)
memmove(p + i + s.n, p + i, extra);
memcpy(p + i, s.p, s.n);
p[n += s.n] = 0;
return *this;
}
string&
string::erase(size_t pos, size_t count) noexcept
{
if (pos > n)
__builtin_trap();
if (count > n - pos)
count = n - pos;
size_t extra = n - (pos + count);
if (extra)
memmove(p + pos, p + pos + count, extra);
p[n = pos + extra] = 0;
return *this;
}
} // namespace ctl
+236
View File
@@ -0,0 +1,236 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef COSMOPOLITAN_CTL_STRING_H_
#define COSMOPOLITAN_CTL_STRING_H_
#include "string_view.h"
namespace ctl {
struct string;
string
strcat(const string_view, const string_view) noexcept __wur;
struct string
{
char* p = nullptr;
size_t n = 0;
size_t c = 0;
using iterator = char*;
using const_iterator = const char*;
static constexpr size_t npos = -1;
~string() noexcept;
string() = default;
string(const string_view) noexcept;
string(const char*) noexcept;
string(const string&) noexcept;
string(const char*, size_t) noexcept;
explicit string(size_t, char = 0) noexcept;
string& operator=(string&&) noexcept;
const char* c_str() const noexcept;
void pop_back() noexcept;
void grow(size_t) noexcept;
void reserve(size_t) noexcept;
void resize(size_t, char = 0) noexcept;
void append(char) noexcept;
void append(char, size_t) noexcept;
void append(unsigned long) noexcept;
void append(const void*, size_t) noexcept;
string& insert(size_t, const string_view) noexcept;
string& erase(size_t = 0, size_t = npos) noexcept;
string substr(size_t = 0, size_t = npos) const noexcept;
string& replace(size_t, size_t, const string_view&) noexcept;
bool operator==(const string_view) const noexcept;
bool operator!=(const string_view) const noexcept;
bool contains(const string_view) const noexcept;
bool ends_with(const string_view) const noexcept;
bool starts_with(const string_view) const noexcept;
size_t find(char, size_t = 0) const noexcept;
size_t find(const string_view, size_t = 0) const noexcept;
string(string&& s) noexcept : p(s.p), n(s.n), c(s.c)
{
s.p = nullptr;
s.n = 0;
s.c = 0;
}
void clear() noexcept
{
n = 0;
}
bool empty() const noexcept
{
return !n;
}
char* data() const noexcept
{
return p;
}
size_t size() const noexcept
{
return n;
}
size_t length() const noexcept
{
return n;
}
size_t capacity() const noexcept
{
return c;
}
iterator begin() noexcept
{
return p;
}
iterator end() noexcept
{
return p + n;
}
const_iterator cbegin() const noexcept
{
return p;
}
const_iterator cend() const noexcept
{
return p + n;
}
char& front()
{
if (!n)
__builtin_trap();
return p[0];
}
const char& front() const
{
if (!n)
__builtin_trap();
return p[0];
}
char& back()
{
if (!n)
__builtin_trap();
return p[n - 1];
}
const char& back() const
{
if (!n)
__builtin_trap();
return p[n - 1];
}
char& operator[](size_t i) noexcept
{
if (i >= n)
__builtin_trap();
return p[i];
}
const char& operator[](size_t i) const noexcept
{
if (i >= n)
__builtin_trap();
return p[i];
}
void push_back(char ch) noexcept
{
append(ch);
}
void append(const string_view s) noexcept
{
append(s.p, s.n);
}
inline constexpr operator string_view() const noexcept
{
return string_view(p, n);
}
string& operator=(const char* s) noexcept
{
clear();
append(s);
return *this;
}
string& operator=(const string_view s) noexcept
{
clear();
append(s);
return *this;
}
string& operator+=(char x) noexcept
{
append(x);
return *this;
}
string& operator+=(const string_view s) noexcept
{
append(s);
return *this;
}
string operator+(const string_view s) const noexcept
{
return strcat(*this, s);
}
int compare(const string_view s) const noexcept
{
return strcmp(*this, s);
}
bool operator<(const string_view s) const noexcept
{
return compare(s) < 0;
}
bool operator<=(const string_view s) const noexcept
{
return compare(s) <= 0;
}
bool operator>(const string_view s) const noexcept
{
return compare(s) > 0;
}
bool operator>=(const string_view s) const noexcept
{
return compare(s) >= 0;
}
};
} // namespace ctl
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wliteral-suffix"
inline ctl::string
operator"" s(const char* s, size_t n)
{
return ctl::string(s, n);
}
#pragma GCC diagnostic pop
#endif // COSMOPOLITAN_CTL_STRING_H_
+111
View File
@@ -0,0 +1,111 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
//
// Copyright 2024 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 "string_view.h"
#include <stdckdint.h>
#include <string.h>
#include "string.h"
namespace ctl {
size_t
string_view::find(char ch, size_t pos) const noexcept
{
char* q;
if (n && (q = (char*)memchr(p, ch, n)))
return q - p;
return npos;
}
size_t
string_view::find(const string_view s, size_t pos) const noexcept
{
char* q;
if (pos > n)
__builtin_trap();
if ((q = (char*)memmem(p + pos, n - pos, s.p, s.n)))
return q - p;
return npos;
}
string_view
string_view::substr(size_t pos, size_t count) const noexcept
{
size_t last;
if (pos > n)
__builtin_trap();
if (count > n - pos)
count = n - pos;
if (ckd_add(&last, pos, count))
last = n;
if (last > n)
__builtin_trap();
return string_view(p + pos, count);
}
bool
string_view::operator==(const string_view s) const noexcept
{
if (n != s.n)
return false;
if (!n)
return true;
return !memcmp(p, s.p, n);
}
bool
string_view::operator!=(const string_view s) const noexcept
{
if (n != s.n)
return true;
if (!n)
return false;
return !!memcmp(p, s.p, n);
}
bool
string_view::contains(const string_view s) const noexcept
{
if (!s.n)
return true;
return !!memmem(p, n, s.p, s.n);
}
bool
string_view::ends_with(const string_view s) const noexcept
{
if (n < s.n)
return false;
if (!s.n)
return true;
return !memcmp(p + n - s.n, s.p, s.n);
}
bool
string_view::starts_with(const string_view s) const noexcept
{
if (n < s.n)
return false;
if (!s.n)
return true;
return !memcmp(p, s.p, s.n);
}
} // namespace ctl
+159
View File
@@ -0,0 +1,159 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef COSMOPOLITAN_CTL_STRINGVIEW_H_
#define COSMOPOLITAN_CTL_STRINGVIEW_H_
namespace ctl {
struct string_view;
int
strcmp(const string_view, const string_view) noexcept;
struct string_view
{
const char* p;
size_t n;
using iterator = const char*;
using const_iterator = const char*;
static constexpr size_t npos = -1;
constexpr string_view() noexcept : p(nullptr), n(0)
{
}
constexpr string_view(const char* s) noexcept
: p(s), n(s ? __builtin_strlen(s) : 0)
{
}
constexpr string_view(const char* s, size_t n) noexcept : p(s), n(n)
{
}
inline constexpr ~string_view() noexcept
{
}
bool operator==(const string_view) const noexcept;
bool operator!=(const string_view) const noexcept;
bool contains(const string_view) const noexcept;
bool ends_with(const string_view) const noexcept;
bool starts_with(const string_view) const noexcept;
string_view substr(size_t = 0, size_t = npos) const noexcept;
size_t find(char, size_t = 0) const noexcept;
size_t find(const string_view, size_t = 0) const noexcept;
constexpr string_view& operator=(const string_view& s) noexcept
{
p = s.p;
n = s.n;
return *this;
}
constexpr bool empty() const noexcept
{
return !n;
}
constexpr const char* data() const noexcept
{
return p;
}
constexpr size_t size() const noexcept
{
return n;
}
constexpr size_t length() const noexcept
{
return n;
}
constexpr const char& operator[](size_t i) const noexcept
{
if (i >= n)
__builtin_trap();
return p[i];
}
constexpr void remove_prefix(size_t count)
{
if (count > n)
__builtin_trap();
p += count;
n -= count;
}
constexpr void remove_suffix(size_t count)
{
if (count > n)
__builtin_trap();
n -= count;
}
constexpr const char& front() const
{
if (!n)
__builtin_trap();
return p[0];
}
constexpr const char& back() const
{
if (!n)
__builtin_trap();
return p[n - 1];
}
constexpr const_iterator begin() noexcept
{
return p;
}
constexpr const_iterator end() noexcept
{
return p + n;
}
constexpr const_iterator cbegin() const noexcept
{
return p;
}
constexpr const_iterator cend() const noexcept
{
return p + n;
}
int compare(const string_view s) const noexcept
{
return strcmp(*this, s);
}
bool operator<(const string_view& s) const noexcept
{
return compare(s) < 0;
}
bool operator<=(const string_view& s) const noexcept
{
return compare(s) <= 0;
}
bool operator>(const string_view& s) const noexcept
{
return compare(s) > 0;
}
bool operator>=(const string_view& s) const noexcept
{
return compare(s) >= 0;
}
};
} // namespace ctl
#endif // COSMOPOLITAN_CTL_STRINGVIEW_H_
+246
View File
@@ -0,0 +1,246 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
#define COSMOPOLITAN_CTL_OPTIONAL_H_
#include <__utility/forward.h>
#include <__utility/move.h>
#include <__utility/swap.h>
namespace ctl {
template<typename T>
struct vector
{
size_t n = 0;
size_t c = 0;
T* p = nullptr;
using iterator = T*;
using const_iterator = const T*;
vector() = default;
~vector()
{
delete[] p;
}
vector(const vector& other)
{
n = other.n;
c = other.c;
p = new T[c];
for (size_t i = 0; i < n; ++i)
new (&p[i]) T(other.p[i]);
}
vector(vector&& other) noexcept
{
n = other.n;
c = other.c;
p = other.p;
other.n = 0;
other.c = 0;
other.p = nullptr;
}
explicit vector(size_t count, const T& value = T())
{
n = count;
c = count;
p = new T[c];
for (size_t i = 0; i < n; ++i)
new (&p[i]) T(value);
}
vector& operator=(const vector& other)
{
if (this != &other) {
T* newData = new T[other.c];
for (size_t i = 0; i < other.n; ++i) {
newData[i] = other.p[i];
}
delete[] p;
p = newData;
n = other.n;
c = other.c;
}
return *this;
}
vector& operator=(vector&& other) noexcept
{
if (this != &other) {
delete[] p;
p = other.p;
n = other.n;
c = other.c;
other.p = nullptr;
other.n = 0;
other.c = 0;
}
return *this;
}
bool empty() const
{
return !n;
}
size_t size() const
{
return n;
}
size_t capacity() const
{
return c;
}
T& operator[](size_t i)
{
if (i >= n)
__builtin_trap();
return p[i];
}
const T& operator[](size_t i) const
{
if (i >= n)
__builtin_trap();
return p[i];
}
iterator begin()
{
return p;
}
iterator end()
{
return p + n;
}
const_iterator cbegin() const
{
return p;
}
const_iterator cend() const
{
return p + n;
}
T& front()
{
if (!n)
__builtin_trap();
return p[0];
}
const T& front() const
{
if (!n)
__builtin_trap();
return p[0];
}
T& back()
{
if (!n)
__builtin_trap();
return p[n - 1];
}
const T& back() const
{
if (!n)
__builtin_trap();
return p[n - 1];
}
void clear()
{
for (size_t i = 0; i < n; ++i)
p[i].~T();
n = 0;
}
void reserve(size_t c2)
{
if (c2 <= c)
return;
T* newP = new T[c2];
for (size_t i = 0; i < n; ++i)
newP[i] = std::move(p[i]);
delete[] p;
p = newP;
c = c2;
}
void push_back(const T& e)
{
if (n == c) {
size_t c2 = c + 1;
c2 += c2 >> 1;
reserve(c2);
}
new (&p[n]) T(e);
++n;
}
void push_back(T&& e)
{
if (n == c) {
size_t c2 = c + 1;
c2 += c2 >> 1;
reserve(c2);
}
new (&p[n]) T(std::forward<T>(e));
++n;
}
template<typename... Args>
void emplace_back(Args&&... args)
{
if (n == c) {
size_t c2 = c + 1;
c2 += c2 >> 1;
reserve(c2);
}
new (&p[n]) T(std::forward<Args>(args)...);
++n;
}
void pop_back()
{
if (n > 0) {
--n;
p[n].~T();
}
}
void resize(size_t n2)
{
if (n2 > n) {
reserve(n2);
for (size_t i = n; i < n2; ++i)
new (&p[i]) T();
} else if (n2 < n) {
for (size_t i = n2; i < n; ++i)
p[i].~T();
}
n = n2;
}
void swap(vector& other) noexcept
{
std::swap(n, other.n);
std::swap(c, other.c);
std::swap(p, other.p);
}
};
} // namespace ctl
#endif // COSMOPOLITAN_CTL_OPTIONAL_H_
+4 -2
View File
@@ -27,7 +27,8 @@
*/
int alaw(int x) {
int a, b, i;
if ((a = x) < 0) a = ~a;
if ((a = x) < 0)
a = ~a;
a >>= 4;
if (a > 15) {
if ((i = a >> 5)) {
@@ -40,6 +41,7 @@ int alaw(int x) {
a += 16;
}
}
if (x >= 0) a |= 128;
if (x >= 0)
a |= 128;
return a ^ 85;
}
+2 -2
View File
@@ -9,8 +9,8 @@ int mulaw(int);
int unmulaw(int);
void *double2byte(long, const void *, double, double) vallocesque;
void *byte2double(long, const void *, double, double) vallocesque;
void *dct(float[restrict hasatleast 8][8], unsigned,
float, float, float, float, float);
void *dct(float[restrict hasatleast 8][8], unsigned, float, float, float, float,
float);
void *dctjpeg(float[restrict hasatleast 8][8], unsigned);
double det3(const double[3][3]) nosideeffect;
void *inv3(double[restrict 3][3], const double[restrict 3][3], double);
+2 -2
View File
@@ -65,8 +65,8 @@
*
* @cost ~100ns
*/
void *dct(float M[restrict hasatleast 8][8], unsigned stride,
float c0, float c1, float c2, float c3, float c4) {
void *dct(float M[restrict hasatleast 8][8], unsigned stride, float c0,
float c1, float c2, float c3, float c4) {
unsigned y, x;
for (y = 0; y < stride * 8; y += stride) {
DCT(M[y][0], M[y][1], M[y][2], M[y][3], M[y][4], M[y][5], M[y][6], M[y][7],
+1 -1
View File
@@ -16,8 +16,8 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/core/core.h"
#include "dsp/core/gamma.h"
#include "dsp/core/core.h"
#include "libc/math.h"
double rgb2stdpc(double x, double g) {
+4 -2
View File
@@ -28,13 +28,15 @@
int mulaw(int x) {
int b, i, a, s, l, h;
a = x < 0 ? (~x >> 2) + 33 : (x >> 2) + 33;
if (a > 8191) a = 8191;
if (a > 8191)
a = 8191;
i = a >> 6;
s = i ? (__builtin_clz(i) ^ 31) + 2 : 1;
h = 8 - s;
l = (a >> s) & 15;
l = 15 - l;
b = (h << 4) | l;
if (x >= 0) b |= 128;
if (x >= 0)
b |= 128;
return b;
}
+4 -2
View File
@@ -29,7 +29,8 @@ void scalevolume(size_t n, int16_t pcm[n][8], int p) {
/* TODO(jart): This isn't acceptable. */
size_t i, j;
if (p > 0) {
if (p > 15) p = 15;
if (p > 15)
p = 15;
for (i = 0; i < n; ++i) {
for (j = 0; j < 8; ++j) {
pcm[i][j] =
@@ -38,7 +39,8 @@ void scalevolume(size_t n, int16_t pcm[n][8], int p) {
}
} else if (p < 0) {
p = -p;
if (p > 15) p = 15;
if (p > 15)
p = 15;
for (i = 0; i < n; ++i) {
for (j = 0; j < 8; ++j) {
pcm[i][j] = pcm[i][j] >> p;
+4 -2
View File
@@ -31,8 +31,10 @@ int unalaw(int x) {
i = (x ^ 85) & 127;
e = i >> 4;
m = i & 15;
if (e > 0) m += 16;
if (e > 0)
m += 16;
m = (m << 4) + 8;
if (e > 1) m = m << (e - 1);
if (e > 1)
m = m << (e - 1);
return x & 128 ? m : -m;
}
-1
View File
@@ -35,7 +35,6 @@ DSP_MPEG_A_DIRECTDEPS = \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_TIME \
LIBC_TINYMATH \
THIRD_PARTY_COMPILER_RT
+1 -6
View File
@@ -35,12 +35,7 @@
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/madv.h"
asm(".ident\t\"\\n\\n\
PL_MPEG (MIT License)\\n\
Copyright(c) 2019 Dominic Szablewski\\n\
https://phoboslab.org\"");
asm(".include \"libc/disclaimer.inc\"");
__static_yoink("pl_mpeg_notice");
/* clang-format off */
// -----------------------------------------------------------------------------
+2 -1
View File
@@ -64,7 +64,8 @@ forceinline bool plm_buffer_has(plm_buffer_t *b, size_t bits) {
}
forceinline int plm_buffer_read(plm_buffer_t *self, int count) {
if (!plm_buffer_has(self, count)) return 0;
if (!plm_buffer_has(self, count))
return 0;
int value = 0;
while (count) {
int current_byte = self->bytes[self->bit_index >> 3];
+2 -7
View File
@@ -27,17 +27,12 @@
│ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE │
│ SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/mpeg/buffer.h"
#include "dsp/mpeg/demux.h"
#include "dsp/mpeg/buffer.h"
#include "dsp/mpeg/mpeg.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
asm(".ident\t\"\\n\\n\
PL_MPEG (MIT License)\\n\
Copyright(c) 2019 Dominic Szablewski\\n\
https://phoboslab.org\"");
asm(".include \"libc/disclaimer.inc\"");
__static_yoink("pl_mpeg_notice");
/* clang-format off */
// ----------------------------------------------------------------------------
+2 -2
View File
@@ -3,8 +3,8 @@
#include "dsp/mpeg/mpeg.h"
COSMOPOLITAN_C_START_
#define START_PACK 0xBA
#define START_END 0xB9
#define START_PACK 0xBA
#define START_END 0xB9
#define START_SYSTEM 0xBB
typedef struct plm_demux_t {
+1 -6
View File
@@ -28,12 +28,7 @@
│ SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/core/half.h"
asm(".ident\t\"\\n\\n\
PL_MPEG (MIT License)\\n\
Copyright(c) 2019 Dominic Szablewski\\n\
https://phoboslab.org\"");
asm(".include \"libc/disclaimer.inc\"");
__static_yoink("pl_mpeg_notice");
/**
* Computes Fixed-Point 8x8 Inverse Discrete Cosine Transform.
+2 -1
View File
@@ -46,7 +46,8 @@ forceinline void plm_video_process_macroblock(plm_video_t *self,
si = ((self->mb_row * BW) + vp) * dw + (self->mb_col * BW) + hp;
di = (self->mb_row * dw + self->mb_col) * BW;
max_address = (dw * (self->mb_height * BW - BW + 1) - BW);
if (si > max_address || di > max_address) return;
if (si > max_address || di > max_address)
return;
d += di;
s += si;
switch (((interpolate << 2) | (odd_h << 1) | (odd_v)) & 7) {
-6
View File
@@ -33,12 +33,6 @@
#include "libc/mem/mem.h"
#include "libc/str/str.h"
asm(".ident\t\"\\n\\n\
PL_MPEG (MIT License)\\n\
Copyright(c) 2019 Dominic Szablewski\\n\
https://phoboslab.org\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
// -----------------------------------------------------------------------------
// plm_audio implementation
+3 -10
View File
@@ -39,14 +39,9 @@
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/time/time.h"
#include "libc/time.h"
#include "libc/x/x.h"
asm(".ident\t\"\\n\\n\
PL_MPEG (MIT License)\\n\
Copyright(c) 2019 Dominic Szablewski\\n\
https://phoboslab.org\"");
asm(".include \"libc/disclaimer.inc\"");
__static_yoink("pl_mpeg_notice");
// -----------------------------------------------------------------------------
// plm_video implementation
@@ -1104,7 +1099,7 @@ plm_video_t *plm_video_create_with_buffer(plm_buffer_t *buffer,
return self;
}
static textstartup void plm_video_init(void) {
__attribute__((__constructor__)) static textstartup void plm_video_init(void) {
PLM_VIDEO_MACROBLOCK_TYPE[0] = NULL;
PLM_VIDEO_MACROBLOCK_TYPE[1] = (void *)PLM_VIDEO_MACROBLOCK_TYPE_INTRA;
PLM_VIDEO_MACROBLOCK_TYPE[2] = (void *)PLM_VIDEO_MACROBLOCK_TYPE_PREDICTIVE;
@@ -1113,5 +1108,3 @@ static textstartup void plm_video_init(void) {
PLM_VIDEO_DCT_SIZE[1] = (void *)PLM_VIDEO_DCT_SIZE_CHROMINANCE;
PLM_VIDEO_DCT_SIZE[2] = (void *)PLM_VIDEO_DCT_SIZE_CHROMINANCE;
}
const void *const plm_video_init_ctor[] initarray = {plm_video_init};
+4
View File
@@ -0,0 +1,4 @@
__notice(pl_mpeg_notice, "\
PL_MPEG (MIT License)\n\
Copyright(c) 2019 Dominic Szablewski\n\
https://phoboslab.org");
+1 -6
View File
@@ -32,12 +32,7 @@
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
asm(".ident\t\"\\n\\n\
PL_MPEG (MIT License)\\n\
Copyright(c) 2019 Dominic Szablewski\\n\
https://phoboslab.org\"");
asm(".include \"libc/disclaimer.inc\"");
__static_yoink("pl_mpeg_notice");
/* clang-format off */
// -----------------------------------------------------------------------------
+1 -6
View File
@@ -29,12 +29,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/mpeg/mpeg.h"
#include "libc/macros.internal.h"
asm(".ident\t\"\\n\\n\
PL_MPEG (MIT License)\\n\
Copyright(c) 2019 Dominic Szablewski\\n\
https://phoboslab.org\"");
asm(".include \"libc/disclaimer.inc\"");
__static_yoink("pl_mpeg_notice");
/**
* @see YCbCr2RGB() in tool/viz/lib/ycbcr2rgb.c
-1
View File
@@ -31,7 +31,6 @@ DSP_SCALE_A_DIRECTDEPS = \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
LIBC_STR \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_X
+13 -8
View File
@@ -27,7 +27,7 @@
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
@@ -77,7 +77,8 @@ static struct SamplingSolution *NewSamplingSolution(long n, long s) {
static bool IsNormalized(int n, double A[n]) {
int i;
double x;
for (x = i = 0; i < n; ++i) x += A[i];
for (x = i = 0; i < n; ++i)
x += A[i];
return fabs(x - 1) < 1e-4;
}
@@ -96,8 +97,10 @@ struct SamplingSolution *ComputeSamplingSolution(long dn, long sn, double dar,
short *weights, *indices;
struct SamplingSolution *res;
long j, i, k, n, min, max, s, N[6];
if (!dar) dar = sn, dar /= dn;
if (!off) off = (dar - 1) / 2;
if (!dar)
dar = sn, dar /= dn;
if (!off)
off = (dar - 1) / 2;
f = dar < 1 ? 1 / dar : dar;
s = 3 * f + 4;
fweights = gc(xcalloc(s + /*xxx*/ 2, sizeof(double)));
@@ -114,8 +117,10 @@ struct SamplingSolution *ComputeSamplingSolution(long dn, long sn, double dar,
for (k = 0, j = min; j <= max; ++j) {
fweights[k++] = ComputeWeight((j - x) / (f / par));
}
for (sum = k = 0; k < n; ++k) sum += fweights[k];
for (j = 0; j < n; ++j) fweights[j] *= 1 / sum;
for (sum = k = 0; k < n; ++k)
sum += fweights[k];
for (j = 0; j < n; ++j)
fweights[j] *= 1 / sum;
DCHECK(IsNormalized(n, fweights));
for (j = 0; j < n; ++j) {
indices[i * s + j] = MIN(sn - 1, MAX(0, min + j));
@@ -202,8 +207,8 @@ void *Gyarados(long dyw, long dxw, int dst[dyw][dxw], long syw, long sxw,
CHECK_LE(sxn, sxw);
CHECK_LE(dyn, dyw);
CHECK_LE(dxn, dxw);
CHECK_LT(_bsrl(syn) + _bsrl(sxn), 32);
CHECK_LT(_bsrl(dyn) + _bsrl(dxn), 32);
CHECK_LT(bsrl(syn) + bsrl(sxn), 32);
CHECK_LT(bsrl(dyn) + bsrl(dxn), 32);
CHECK_LE(dyw, 0x7fff);
CHECK_LE(dxw, 0x7fff);
CHECK_LE(syw, 0x7fff);
+1 -2
View File
@@ -121,8 +121,7 @@ void *MagikarpY(long dys, long dxs, unsigned char d[restrict dys][dxs],
return d;
}
static textstartup void g_magikarp_init() {
__attribute__((__constructor__)) static textstartup void g_magikarp_init() {
memcpy(g_magkern, kMagkern[0], sizeof(g_magkern));
memcpy(g_magikarp, kMagikarp[0], sizeof(g_magikarp));
}
const void *const g_magikarp_ctor[] initarray = {g_magikarp_init};
-1
View File
@@ -38,7 +38,6 @@ DSP_TTY_A_DIRECTDEPS = \
LIBC_SOCK \
LIBC_SYSV \
LIBC_TINYMATH \
LIBC_TIME \
LIBC_X
DSP_TTY_A_DEPS := \
+6 -2
View File
@@ -24,9 +24,13 @@
* The alternate buffer trick lets one restore the console exactly as it
* was, once the program is done running.
*/
int ttyenablealtbuf(int ttyfd) { return ttysend(ttyfd, "\e[?1049h"); }
int ttyenablealtbuf(int ttyfd) {
return ttysend(ttyfd, "\e[?1049h");
}
/**
* Asks teletypewriter to restore blinking box thing.
*/
int ttydisablealtbuf(int ttyfd) { return ttysend(ttyfd, "\e[?1049l"); }
int ttydisablealtbuf(int ttyfd) {
return ttysend(ttyfd, "\e[?1049l");
}
+4 -2
View File
@@ -30,8 +30,10 @@
static int ttysetcursor(int fd, bool visible) {
struct NtConsoleCursorInfo ntcursor;
char code[8] = "\e[?25l";
if (__nocolor) return 0;
if (visible) code[5] = 'h';
if (__nocolor)
return 0;
if (visible)
code[5] = 'h';
if (IsWindows()) {
GetConsoleCursorInfo(GetStdHandle(kNtStdOutputHandle), &ntcursor);
ntcursor.bVisible = visible;
+1 -3
View File
@@ -21,7 +21,7 @@
struct Itoa8 kItoa8;
static textstartup void itoa8_init(void) {
__attribute__((__constructor__)) static textstartup void itoa8_init(void) {
int i;
uint8_t z;
uint32_t w;
@@ -41,5 +41,3 @@ static textstartup void itoa8_init(void) {
kItoa8.data[i] = w;
}
}
const void *const itoa8_init_ctor[] initarray = {itoa8_init};
+1 -3
View File
@@ -97,7 +97,7 @@ static int uncube(int x) {
return x < 48 ? 0 : x < 115 ? 1 : (x - 35) / 40;
}
static textstartup void rgb2ansi_init(void) {
__attribute__((__constructor__)) static textstartup void rgb2ansi_init(void) {
uint8_t c;
uint32_t i;
memcpy(g_ansi2rgb_, &kCgaPalette, sizeof(kCgaPalette));
@@ -114,5 +114,3 @@ static textstartup void rgb2ansi_init(void) {
g_ansi2rgb_[i].xt = i;
}
}
const void *const rgb2ansi_init_ctor[] initarray = {rgb2ansi_init};
+6 -2
View File
@@ -21,9 +21,13 @@
/**
* Asks teletypewriter to push current position.
*/
int ttysavecursor(int ttyfd) { return ttysend(ttyfd, "\e[s"); }
int ttysavecursor(int ttyfd) {
return ttysend(ttyfd, "\e[s");
}
/**
* Asks teletypewriter to pop previous position.
*/
int ttyrestorecursor(int ttyfd) { return ttysend(ttyfd, "\e[u"); }
int ttyrestorecursor(int ttyfd) {
return ttysend(ttyfd, "\e[u");
}
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/tty/tty.h"
#include "libc/mem/arraylist2.internal.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/x/x.h"
+14 -6
View File
@@ -21,22 +21,30 @@
#include "libc/limits.h"
static char *ansitoa(char *p, unsigned xt, unsigned base) {
if (xt >= 8) xt -= 8, base += 60;
if (xt >= 8)
xt -= 8, base += 60;
return itoa8(p, xt + base);
}
static char *setansibgfg(char *p, unsigned bg, unsigned fg) {
*p++ = '\e';
*p++ = '[';
if (bg != -1u) p = ansitoa(p, bg, 40);
if (bg != -1u && fg != -1u) *p++ = ';';
if (fg != -1u) p = ansitoa(p, fg, 30);
if (bg != -1u)
p = ansitoa(p, bg, 40);
if (bg != -1u && fg != -1u)
*p++ = ';';
if (fg != -1u)
p = ansitoa(p, fg, 30);
*p++ = 'm';
return p;
}
char *setbg16_(char *p, struct TtyRgb bg) { return setansibgfg(p, bg.xt, -1u); }
char *setfg16_(char *p, struct TtyRgb fg) { return setansibgfg(p, -1u, fg.xt); }
char *setbg16_(char *p, struct TtyRgb bg) {
return setansibgfg(p, bg.xt, -1u);
}
char *setfg16_(char *p, struct TtyRgb fg) {
return setansibgfg(p, -1u, fg.xt);
}
char *setbgfg16_(char *p, struct TtyRgb bg, struct TtyRgb fg) {
return setansibgfg(p, bg.xt, fg.xt);
}
+1 -3
View File
@@ -73,8 +73,6 @@ textstartup void ttyquantsetup(enum TtyQuantizationAlgorithm alg,
TTYQUANT()->blocks = blocks;
}
textstartup void ttyquant_init(void) {
__attribute__((__constructor__)) textstartup void ttyquant_init(void) {
ttyquantsetup(kTtyQuantXterm256, kTtyQuantRgb, kTtyBlocksUnicode);
}
const void *const ttyquant_init_ctor[] initarray = {ttyquant_init};
+4 -2
View File
@@ -666,7 +666,8 @@ static char *CopyBlock(char *v, const struct TtyRgb chunk[hasatleast 4],
struct Glyph *glyph) {
unsigned i;
CHECK_LT(pick.bg, 4);
if (pick.fg != 0xff) CHECK_LT(pick.fg, 4);
if (pick.fg != 0xff)
CHECK_LT(pick.fg, 4);
i = 0;
if (pick.fg == 0xff) {
if (!ttyeq(*bg, chunk[pick.bg])) {
@@ -744,7 +745,8 @@ static dontinline char *CopyRun(char *v, size_t n,
v = CopyGlyph(v, *glyph);
*x += 2;
*c += 2;
if (*x >= n) break;
if (*x >= n)
break;
CopyChunk(chunk, *c, n);
} while (ChunkEq(chunk, lastchunk));
*x -= 2;
+10 -6
View File
@@ -25,7 +25,7 @@
#include "libc/calls/ucontext.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
@@ -69,13 +69,16 @@ static textstartup int ttyraw_enable(void) {
}
static textstartup void ttyraw_hidecursor(void) {
if (!g_ttyraw.setup) return;
if (g_ttyraw.flags & kTtyCursor) return;
if (!g_ttyraw.setup)
return;
if (g_ttyraw.flags & kTtyCursor)
return;
ttyhidecursor(FD);
}
static textexit int ttyraw_disable(void) {
if (!g_ttyraw.setup) return 0;
if (!g_ttyraw.setup)
return 0;
ttyshowcursor(FD);
return ttyrestore(FD, &g_ttyraw.old);
}
@@ -84,10 +87,11 @@ static textexit void ttyraw_onexit(void) {
ttyraw_disable();
}
static relegated void ttyraw_onsig(int sig, struct siginfo *info,
static relegated void ttyraw_onsig(int sig, siginfo_t *info,
struct ucontext *ctx) {
size_t i;
if (g_ttyraw.noreentry) _Exit(128 + sig);
if (g_ttyraw.noreentry)
_Exit(128 + sig);
g_ttyraw.noreentry = true;
if (g_ttyraw.flags != -1) {
if (sig == SIGCONT) {
+106 -104
View File
@@ -14,130 +14,131 @@ EXAMPLES_MAINS_S = $(filter %.S,$(EXAMPLES_FILES))
EXAMPLES_MAINS_C = $(filter %.c,$(EXAMPLES_FILES))
EXAMPLES_MAINS_CC = $(filter %.cc,$(EXAMPLES_FILES))
EXAMPLES_SRCS = \
$(EXAMPLES_MAINS_S) \
$(EXAMPLES_MAINS_C) \
EXAMPLES_SRCS = \
$(EXAMPLES_MAINS_S) \
$(EXAMPLES_MAINS_C) \
$(EXAMPLES_MAINS_CC)
EXAMPLES_MAINS = \
$(EXAMPLES_MAINS_S) \
$(EXAMPLES_MAINS_C) \
EXAMPLES_MAINS = \
$(EXAMPLES_MAINS_S) \
$(EXAMPLES_MAINS_C) \
$(EXAMPLES_MAINS_CC)
EXAMPLES_OBJS = \
$(EXAMPLES_MAINS_S:%.S=o/$(MODE)/%.o) \
$(EXAMPLES_MAINS_C:%.c=o/$(MODE)/%.o) \
EXAMPLES_OBJS = \
$(EXAMPLES_MAINS_S:%.S=o/$(MODE)/%.o) \
$(EXAMPLES_MAINS_C:%.c=o/$(MODE)/%.o) \
$(EXAMPLES_MAINS_CC:%.cc=o/$(MODE)/%.o)
EXAMPLES_COMS = \
$(EXAMPLES_MAINS_S:%.S=o/$(MODE)/%.com) \
$(EXAMPLES_MAINS_C:%.c=o/$(MODE)/%.com) \
$(EXAMPLES_MAINS_CC:%.cc=o/$(MODE)/%.com)
EXAMPLES_COMS = \
$(EXAMPLES_MAINS_S:%.S=o/$(MODE)/%) \
$(EXAMPLES_MAINS_C:%.c=o/$(MODE)/%) \
$(EXAMPLES_MAINS_CC:%.cc=o/$(MODE)/%)
EXAMPLES_BINS = \
$(EXAMPLES_COMS) \
EXAMPLES_BINS = \
$(EXAMPLES_COMS) \
$(EXAMPLES_COMS:%=%.dbg)
EXAMPLES_DIRECTDEPS = \
DSP_CORE \
DSP_SCALE \
DSP_TTY \
LIBC_CALLS \
LIBC_DLOPEN \
LIBC_FMT \
LIBC_INTRIN \
LIBC_IRQ \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_PROC \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_TESTLIB \
LIBC_THREAD \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_VGA \
LIBC_X \
NET_HTTP \
NET_HTTPS \
THIRD_PARTY_AWK \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_HIREDIS \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_LINENOISE \
THIRD_PARTY_LUA \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_MUSL \
THIRD_PARTY_NSYNC \
THIRD_PARTY_NSYNC_MEM \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_SED \
THIRD_PARTY_STB \
THIRD_PARTY_TR \
THIRD_PARTY_VQSORT \
THIRD_PARTY_XED \
THIRD_PARTY_ZLIB \
TOOL_ARGS \
TOOL_BUILD_LIB \
EXAMPLES_DIRECTDEPS = \
DSP_CORE \
DSP_SCALE \
DSP_TTY \
LIBC_CALLS \
LIBC_DLOPEN \
LIBC_FMT \
LIBC_INTRIN \
LIBC_IRQ \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_PROC \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_TESTLIB \
LIBC_THREAD \
LIBC_TINYMATH \
LIBC_VGA \
LIBC_X \
NET_HTTP \
NET_HTTPS \
THIRD_PARTY_AWK \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_HIREDIS \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_LINENOISE \
THIRD_PARTY_LUA \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_MUSL \
THIRD_PARTY_NSYNC \
THIRD_PARTY_NSYNC_MEM \
THIRD_PARTY_OPENMP \
THIRD_PARTY_SED \
THIRD_PARTY_STB \
THIRD_PARTY_TR \
THIRD_PARTY_TZ \
THIRD_PARTY_VQSORT \
THIRD_PARTY_XED \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_ZLIB \
TOOL_ARGS \
TOOL_BUILD_LIB \
TOOL_VIZ_LIB
EXAMPLES_DEPS := \
EXAMPLES_DEPS := \
$(call uniq,$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x))))
o/$(MODE)/examples/examples.pkg: \
$(EXAMPLES_OBJS) \
o/$(MODE)/examples/examples.pkg: \
$(EXAMPLES_OBJS) \
$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/examples/unbourne.o: private \
CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED \
o/$(MODE)/examples/unbourne.o: private \
CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED \
-fpie
o/$(MODE)/examples/%.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/%.o \
o/$(MODE)/examples/examples.pkg \
o/$(MODE)/examples/%.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/%.o \
o/$(MODE)/examples/examples.pkg \
$(EXAMPLES_BOOTLOADER)
@$(APELINK)
o/$(MODE)/examples/hellolua.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/hellolua.o \
o/$(MODE)/examples/hellolua.lua.zip.o \
o/$(MODE)/examples/examples.pkg \
o/$(MODE)/examples/hellolua.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/hellolua.o \
o/$(MODE)/examples/hellolua.lua.zip.o \
o/$(MODE)/examples/examples.pkg \
$(EXAMPLES_BOOTLOADER)
@$(APELINK)
o/$(MODE)/examples/ispell.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/ispell.o \
o/$(MODE)/usr/share/dict/words.zip.o \
o/$(MODE)/examples/examples.pkg \
o/$(MODE)/examples/ispell.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/ispell.o \
o/$(MODE)/usr/share/dict/words.zip.o \
o/$(MODE)/examples/examples.pkg \
$(EXAMPLES_BOOTLOADER)
@$(APELINK)
o/$(MODE)/examples/nesemu1.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/nesemu1.o \
o/$(MODE)/usr/share/rom/mario.nes.zip.o \
o/$(MODE)/usr/share/rom/zelda.nes.zip.o \
o/$(MODE)/usr/share/rom/tetris.nes.zip.o \
o/$(MODE)/examples/examples.pkg \
o/$(MODE)/examples/nesemu1.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/nesemu1.o \
o/$(MODE)/usr/share/rom/mario.nes.zip.o \
o/$(MODE)/usr/share/rom/zelda.nes.zip.o \
o/$(MODE)/usr/share/rom/tetris.nes.zip.o \
o/$(MODE)/examples/examples.pkg \
$(EXAMPLES_BOOTLOADER)
@$(APELINK)
@@ -145,7 +146,7 @@ o/$(MODE)/examples/picol.o: private \
CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED
o/$(MODE)/examples/picol.com.dbg: \
o/$(MODE)/examples/picol.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/picol.o \
o/$(MODE)/examples/examples.pkg \
@@ -153,9 +154,10 @@ o/$(MODE)/examples/picol.com.dbg: \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/examples/nesemu1.o: private QUOTA += -M512m
o/$(MODE)/usr/share/dict/words.zip.o: private ZIPOBJ_FLAGS += -C2
o/$(MODE)/examples/blas.o: private COPTS += -O3 -fopenmp
$(EXAMPLES_OBJS): examples/BUILD.mk
o/$(MODE)/usr/share/dict/words: \
@@ -166,8 +168,8 @@ o/$(MODE)/usr/share/dict/words: \
################################################################################
.PHONY: o/$(MODE)/examples
o/$(MODE)/examples: \
o/$(MODE)/examples/package \
o/$(MODE)/examples/pylife \
o/$(MODE)/examples/pyapp \
o/$(MODE)/examples: \
o/$(MODE)/examples/package \
o/$(MODE)/examples/pylife \
o/$(MODE)/examples/pyapp \
$(EXAMPLES_BINS)
Loaded 100 of 6015 files, more files were not shown because too many files have changed in this diff. Show more