Compare commits

...
81 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
3172 changed files with 227336 additions and 75973 deletions

No files matched your search

+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
-108
View File
@@ -1,108 +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=",
"dontcallback=",
"relegated=",
"hidden=",
"textstartup=",
"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"
+10 -17
View File
@@ -133,7 +133,7 @@ endif
ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
HOSTS ?= pi pi5 studio freebsdarm
HOSTS ?= pi studio freebsdarm
else
ARCH = x86_64
HOSTS ?= freebsd rhel7 xnu openbsd netbsd win10
@@ -149,9 +149,9 @@ export MODE
export SOURCE_DATE_EPOCH
export TMPDIR
COSMOCC = .cosmocc/3.3.3
COSMOCC = .cosmocc/3.3.5
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.3 e4d0fa63cd79cc3bfff6c2d015f1776db081409907625aea8ad40cefc1996d08)
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.5 db78fd8d3f8706e9dff4be72bf71d37a3f12062f212f407e1c33bc4af3780dd0)
AS = $(TOOLCHAIN)as
CC = $(TOOLCHAIN)gcc
@@ -174,6 +174,7 @@ all: o
o: o/$(MODE)
o/$(MODE): \
o/$(MODE)/ape \
o/$(MODE)/ctl \
o/$(MODE)/dsp \
o/$(MODE)/net \
o/$(MODE)/libc \
@@ -255,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 # │
@@ -299,6 +301,7 @@ 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
@@ -362,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
@@ -440,7 +442,7 @@ COSMOPOLITAN_OBJECTS = \
LIBC_X \
THIRD_PARTY_GETOPT \
LIBC_LOG \
LIBC_TIME \
THIRD_PARTY_TZ \
THIRD_PARTY_OPENMP \
THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB_GZ \
@@ -452,6 +454,7 @@ COSMOPOLITAN_OBJECTS = \
LIBC_THREAD \
LIBC_PROC \
THIRD_PARTY_NSYNC_MEM \
CTL \
LIBC_MEM \
THIRD_PARTY_DLMALLOC \
LIBC_DLOPEN \
@@ -505,7 +508,6 @@ COSMOPOLITAN_H_PKGS = \
LIBC_STR \
LIBC_SYSV \
LIBC_THREAD \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_X \
LIBC_VGA \
@@ -521,6 +523,7 @@ COSMOPOLITAN_H_PKGS = \
COSMOCC_PKGS = \
$(COSMOPOLITAN_H_PKGS) \
CTL \
THIRD_PARTY_AARCH64 \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_LIBCXXABI \
@@ -543,15 +546,6 @@ 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))
@$(COMPILE) -AROLLUP -T$@ build/bootstrap/rollup @$< >>$@
o/cosmopolitan.html: private .UNSANDBOXED = 1
o/cosmopolitan.html: \
o/$(MODE)/third_party/chibicc/chibicc.dbg \
@@ -573,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 \
+18 -1
View File
@@ -254,7 +254,24 @@ o/$(MODE)/ape: $(APE_CHECKS) \
endif
# these assembly files are safe to build on aarch64
o/$(MODE)/ape/ape.o: ape/ape.S
o/$(MODE)/ape/ape.o: \
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: \
+3 -4
View File
@@ -293,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)));
+8 -1
View File
@@ -146,6 +146,9 @@ struct Syslib {
#define AT_RANDOM 25
#define AT_EXECFN 31
#define EF_APE_MODERN 0x101ca75
#define EF_APE_MODERN_MASK 0x1ffffff
#define AUXV_WORDS 31
/* from the xnu codebase */
@@ -799,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;
@@ -820,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");
}
+4 -4
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 │
│ │
@@ -196,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
@@ -669,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
@@ -1036,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
+3 -2
View File
@@ -553,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);
@@ -713,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
+11 -4
View File
@@ -137,13 +137,20 @@ if [ x"$(uname -s)" = xLinux ]; then
echo done >&2
fi
uname_r="$(uname -r)"
if printf '%s\n%s\n' 5.12 "$uname_r" | sort -CV; then
FLAGS=FP
else
FLAGS=F
fi
echo >&2
echo registering APE with binfmt_misc >&2
echo you may need to edit configs to persist across reboot >&2
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
echo done >&2
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
+7
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)
@@ -834,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");
}
+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_ */
+2
View File
@@ -16,6 +16,8 @@ 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 unsigned char __data_start[] __attribute__((__weak__));
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+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
+6 -7
View File
@@ -60,13 +60,10 @@ 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
@@ -148,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 \
@@ -260,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)
+8 -8
View File
@@ -6,14 +6,14 @@ if [ -n "$OBJDUMP" ]; then
fi
find_objdump() {
if [ -x .cosmocc/3.3.2/bin/$1-linux-cosmo-objdump ]; then
OBJDUMP=.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump
elif [ -x .cosmocc/3.3.2/bin/$1-linux-musl-objdump ]; then
OBJDUMP=.cosmocc/3.3.2/bin/$1-linux-musl-objdump
elif [ -x "$COSMO/.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump"
elif [ -x "$COSMO/.cosmocc/3.3.2/bin/$1-linux-musl-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.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
+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_
+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) {
-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
+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 -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 -1
View File
@@ -39,7 +39,7 @@
#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"
__static_yoink("pl_mpeg_notice");
-1
View File
@@ -31,7 +31,6 @@ DSP_SCALE_A_DIRECTDEPS = \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
LIBC_STR \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_X
-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");
}
+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");
}
+6 -2
View File
@@ -39,8 +39,12 @@ static char *setansibgfg(char *p, unsigned bg, unsigned fg) {
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 -1
View File
@@ -87,7 +87,7 @@ 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)
+4 -2
View File
@@ -65,7 +65,6 @@ EXAMPLES_DIRECTDEPS = \
LIBC_SYSV_CALLS \
LIBC_TESTLIB \
LIBC_THREAD \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_VGA \
LIBC_X \
@@ -89,8 +88,10 @@ EXAMPLES_DIRECTDEPS = \
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 \
@@ -154,7 +155,8 @@ o/$(MODE)/examples/picol.dbg: \
@$(APELINK)
o/$(MODE)/usr/share/dict/words.zip.o: private ZIPOBJ_FLAGS += -C2
o/$(MODE)/examples/wut.o: private COPTS += -fopenmp
o/$(MODE)/examples/blas.o: private COPTS += -O3 -fopenmp
$(EXAMPLES_OBJS): examples/BUILD.mk
+16
View File
@@ -0,0 +1,16 @@
#include <stdlib.h>
__static_yoink("__die");
__static_yoink("GetSymbolByAddr");
__static_yoink("malloc_inspect_all");
char *lol(int n) {
return malloc(n);
}
char *(*pLol)(int) = lol;
int main(int argc, char *argv[]) {
char *s = pLol(4);
s[4] = 1;
}
+221
View File
@@ -0,0 +1,221 @@
// 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 <unistd.h>
#include <cinttypes>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include "libc/assert.h"
// high performance high accuracy matrix multiplication in ansi c
#define MATH __target_clones("avx512f,fma")
namespace {
namespace ansiBLAS {
static constexpr int KN = 8;
struct Vector {
double v[KN];
};
Vector load(const float *p) {
Vector x;
for (int i = 0; i < KN; ++i)
x.v[i] = p[i];
return x;
}
Vector madd(Vector x, Vector y, Vector s) {
for (int i = 0; i < KN; ++i)
s.v[i] = fma(x.v[i], y.v[i], s.v[i]);
return s;
}
float hsum(Vector x) {
double s = 0;
for (int i = 0; i < KN; ++i)
s += x.v[i];
return s;
}
struct ansiBLAS {
public:
ansiBLAS(int k, const float *A, int lda, const float *B, int ldb, float *C,
int ldc, int ith, int nth)
: k(k),
A(A),
lda(lda),
B(B),
ldb(ldb),
C(C),
ldc(ldc),
ith(ith),
nth(nth) {
}
void matmul(int m, int n) {
mnpack(0, m, 0, n);
}
private:
void mnpack(int m0, int m, int n0, int n) {
int mc, nc, mp, np;
if (m - m0 <= 0 || n - n0 <= 0)
return;
if (m - m0 >= 4 && n - n0 >= 3) {
mc = 4;
nc = 3;
gemm<4, 3>(m0, m, n0, n);
} else {
mc = 1;
nc = 1;
gemm<1, 1>(m0, m, n0, n);
}
mp = m0 + (m - m0) / mc * mc;
np = n0 + (n - n0) / nc * nc;
mnpack(mp, m, n0, np);
mnpack(m0, m, np, n);
}
template <int RM, int RN>
MATH void gemm(int m0, int m, int n0, int n) {
int ytiles = (m - m0) / RM;
int xtiles = (n - n0) / RN;
int tiles = xtiles * ytiles;
int duty = (tiles + nth - 1) / nth;
int start = duty * ith;
int end = start + duty;
if (end > tiles)
end = tiles;
for (int job = start; job < end; ++job) {
int ii = m0 + job / xtiles * RM;
int jj = n0 + job % xtiles * RN;
Vector Cv[RN][RM] = {};
for (int l = 0; l < k; l += KN)
for (int j = 0; j < RN; ++j)
for (int i = 0; i < RM; ++i)
Cv[j][i] = madd(load(A + lda * (ii + i) + l), //
load(B + ldb * (jj + j) + l), //
Cv[j][i]);
for (int j = 0; j < RN; ++j)
for (int i = 0; i < RM; ++i)
C[ldc * (jj + j) + (ii + i)] = hsum(Cv[j][i]);
}
}
const int k;
const float *const A;
const int lda;
const float *const B;
const int ldb;
float *const C;
const int ldc;
const int ith;
const int nth;
};
void sgemm(int m, int n, int k, //
const float *A, int lda, //
const float *B, int ldb, //
float *C, int ldc) {
int nth = sysconf(_SC_NPROCESSORS_ONLN);
#pragma omp parallel for
for (int ith = 0; ith < nth; ++ith) {
ansiBLAS tb{k, A, lda, B, ldb, C, ldc, ith, nth};
tb.matmul(m, n);
}
}
} // namespace ansiBLAS
long micros(void) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return ts.tv_sec * 1000000 + (ts.tv_nsec + 999) / 1000;
}
unsigned rand32(void) {
/* Knuth, D.E., "The Art of Computer Programming," Vol 2,
Seminumerical Algorithms, Third Edition, Addison-Wesley, 1998,
p. 106 (line 26) & p. 108 */
static unsigned long long lcg = 1;
lcg *= 6364136223846793005;
lcg += 1442695040888963407;
return lcg >> 32;
}
float float01(unsigned x) { // (0,1)
return 1.f / 8388608 * ((x >> 9) + .5f);
}
float numba(void) { // (-1,1)
return float01(rand32()) * 2 - 1;
}
void fill(int m, int n, float *A, int lda) {
for (int j = 0; j < n; ++j)
for (int i = 0; i < m; ++i)
A[lda * j + i] = numba();
}
float *new_matrix(int m, int n, int *lda) {
void *ptr = 0;
int b = 64 / sizeof(float);
*lda = (n + b - 1) & -b;
posix_memalign(&ptr, 4096, sizeof(float) * m * *lda);
return (float *)ptr;
}
} // namespace
void barrier(void) {
}
void (*pBarrier)(void) = barrier;
#define BENCH(x) \
do { \
x; \
int N = 10; \
long t1 = micros(); \
for (long i = 0; i < N; ++i) { \
pBarrier(); \
x; \
} \
long t2 = micros(); \
printf("%8" PRId64 " µs %s %g gigaflops\n", (t2 - t1 + N - 1) / N, #x, \
1e6 / ((t2 - t1 + N - 1) / N) * m * n * k * 2 * 1e-9); \
} while (0)
int main() {
int m = 1024;
int n = 1024;
int k = 1024;
int lda, ldb, ldc;
float *A = new_matrix(m, k, &lda);
float *B = new_matrix(n, k, &ldb);
float *C = new_matrix(n, m, &ldc);
fill(k, n, A, lda);
fill(k, m, B, ldb);
BENCH(ansiBLAS::sgemm(m, n, k, A, lda, B, ldb, C, ldc));
assert(C[0] == -0x1.20902ap+4);
assert(C[1] == -0x1.bf7726p+4);
free(C);
free(B);
free(A);
}
+11 -8
View File
@@ -7,6 +7,7 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/intrin/kprintf.h"
#include "libc/math.h"
#include "libc/runtime/runtime.h"
@@ -26,6 +27,13 @@
* o//examples/crashreport.com
*/
int Divide(int x, int y) {
volatile int z = 0; // force creation of stack frame
return x / y + z;
}
int (*pDivide)(int, int) = Divide;
dontubsan int main(int argc, char *argv[]) {
kprintf("----------------\n");
kprintf(" THIS IS A TEST \n");
@@ -34,12 +42,7 @@ dontubsan int main(int argc, char *argv[]) {
ShowCrashReports();
volatile double a = 0;
volatile double b = 23;
volatile double c = exp(b) / a;
(void)c;
volatile int x = 0;
volatile int y = 1 / x;
return y;
pDivide(1, 0);
pDivide(2, 0);
pDivide(3, 0);
}
+12
View File
@@ -7,6 +7,7 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/math.h"
#include "libc/runtime/runtime.h"
@@ -18,6 +19,17 @@ void crash(long x0, long x1, long x2, //
void (*pCrash)(long, long, long, double, double, double) = crash;
int main(int argc, char *argv[]) {
// // by default we launch an addr2line subprocess to print backtraces
// // with line numbers. you can force it to use the embedded solution
// setenv("ADDR2LINE", "", true);
// // using a seccomp sandbox is another way to force embedded backtraces
// pledge("stdio", NULL);
// enable the crash reporting feature
ShowCrashReports();
// time to die
pCrash(1, 2, 3, NAN, NAN, NAN);
}
+25 -4
View File
@@ -9,19 +9,30 @@
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/timespec.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/timezoneid.h"
#include "libc/nt/struct/timezoneinformation.h"
#include "libc/nt/time.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/time/struct/tm.h"
#include "libc/thread/threads.h"
#include "libc/time.h"
/**
* @fileoverview High performance ISO-8601 timestamp formatter.
*
* The strftime() function is very slow. This goes much faster.
* Consider using something like this instead for your loggers.
*/
char *GetTimestamp(void) {
int x;
struct timespec ts;
_Thread_local static long last;
_Thread_local static char s[27];
_Thread_local static struct tm tm;
thread_local static long last;
thread_local static char s[32];
thread_local static struct tm tm;
clock_gettime(0, &ts);
if (ts.tv_sec != last) {
localtime_r(&ts.tv_sec, &tm);
@@ -61,11 +72,21 @@ char *GetTimestamp(void) {
s[23] = '0' + x / 100000 % 10;
s[24] = '0' + x / 10000 % 10;
s[25] = '0' + x / 1000 % 10;
s[26] = tm.tm_gmtoff < 0 ? '-' : '+';
x = ABS(tm.tm_gmtoff) / 60 / 60;
s[27] = '0' + x / 10 % 10;
s[28] = '0' + x % 10;
x = ABS(tm.tm_gmtoff) / 60 % 60;
s[29] = '0' + x / 10 % 10;
s[30] = '0' + x % 10;
return s;
}
int main(int argc, char *argv[]) {
char buf[128], *p = buf;
// setenv("TZ", "UTC", true);
// setenv("TZ", "US/Eastern", true);
// setenv("TZ", "Asia/Kolkata", true);
p = stpcpy(p, GetTimestamp());
p = stpcpy(p, "\n");
write(1, buf, p - buf);
+2 -2
View File
@@ -1,9 +1,9 @@
#include "libc/stdio/stdio.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
int main(int argc, char* argv[]) {
fprintf(stderr, "%s (%s)\n", argv[0], GetProgramExecutableName());
for (char **p = environ; *p; ++p) {
for (char** p = environ; *p; ++p) {
printf("%s\n", *p);
}
return 0;
+1 -1
View File
@@ -151,7 +151,7 @@ void *Worker(void *id) {
// check that client message wasn't fragmented into more reads
InitHttpMessage(&msg, kHttpRequest);
if ((inmsglen = ParseHttpMessage(&msg, buf, got)) <= 0) {
if ((inmsglen = ParseHttpMessage(&msg, buf, got, sizeof(buf))) <= 0) {
if (!inmsglen) {
LOG("%6H client sent fragmented message");
} else {
+1 -1
View File
@@ -42,7 +42,7 @@
#include "libc/stdio/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/time/time.h"
#include "libc/time.h"
#include "third_party/zlib/zlib.h"
// clang-format off
+2 -2
View File
@@ -7,11 +7,11 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/runtime/runtime.h"
#include "third_party/hiredis/hiredis.h"
#include "libc/fmt/conv.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "third_party/hiredis/hiredis.h"
/**
* @fileoverview Demo of using hiredis to connect to a Redis server
+1 -1
View File
@@ -71,7 +71,7 @@ Contact: [email protected]");
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/termios.h"
#include "libc/time/time.h"
#include "libc/time.h"
/* Syntax highlight types */
#define HL_NORMAL 0
+15
View File
@@ -0,0 +1,15 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/time.h"
int main(int argc, char *argv[]) {
int64_t t = 0;
localtime(&t);
}
+1 -1
View File
@@ -44,7 +44,7 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/w.h"
#include "libc/thread/thread.h"
#include "libc/time/time.h"
#include "libc/time.h"
#include "libc/x/xasprintf.h"
#include "libc/x/xsigaction.h"
#include "libc/zip.internal.h"
+1
View File
@@ -42,6 +42,7 @@ EXAMPLES_PACKAGE_OBJS = \
EXAMPLES_PACKAGE_DIRECTDEPS = \
EXAMPLES_PACKAGE_LIB \
LIBC_INTRIN \
LIBC_MEM \
LIBC_STDIO \
LIBC_TINYMATH
+1
View File
@@ -71,6 +71,7 @@ EXAMPLES_PACKAGE_LIB_A_CHECKS = \
EXAMPLES_PACKAGE_LIB_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_NEXGEN32E \
LIBC_MEM \
LIBC_STDIO
# Evaluates variable as set of transitive package dependencies.
+26 -26
View File
@@ -1,31 +1,31 @@
#include <stdio.h>
#define PARSE_AND_PRINT(type, scan_fmt, print_fmt, str) \
do { \
type val; int ret; \
ret = sscanf(str, scan_fmt, &val); \
printf("\"%s\" => " print_fmt " = %d\n", str, val, ret); \
#define PARSE_AND_PRINT(type, scan_fmt, print_fmt, str) \
do { \
type val; \
int ret; \
ret = sscanf(str, scan_fmt, &val); \
printf("\"%s\" => " print_fmt " = %d\n", str, val, ret); \
} while (0)
int main()
{
PARSE_AND_PRINT(float, "%f", "%f", "0.3715");
PARSE_AND_PRINT(float, "%f", "%f", ".3715");
PARSE_AND_PRINT(float, "%f", "%f", "3715");
PARSE_AND_PRINT(float, "%f", "%f", "111.11");
PARSE_AND_PRINT(float, "%f", "%f", "-2.22");
PARSE_AND_PRINT(float, "%f", "%f", "Nan");
PARSE_AND_PRINT(float, "%f", "%f", "nAn(2)");
PARSE_AND_PRINT(float, "%f", "%f", "-NAN(_asdfZXCV1234_)");
PARSE_AND_PRINT(float, "%f", "%f", "-nan");
PARSE_AND_PRINT(float, "%f", "%f", "+nan");
PARSE_AND_PRINT(float, "%f", "%f", "inF");
PARSE_AND_PRINT(float, "%f", "%f", "iNfINiTy");
PARSE_AND_PRINT(float, "%f", "%f", "+inf");
PARSE_AND_PRINT(float, "%f", "%f", "-inf");
PARSE_AND_PRINT(float, "%f", "%f", "0X1.BC70A3D70A3D7P+6");
PARSE_AND_PRINT(float, "%f", "%f", "1.18973e+4932zzz");
PARSE_AND_PRINT(float, "%f", "%.10f", " -0.0000000123junk");
PARSE_AND_PRINT(float, "%f", "%f", "junk");
return 0;
int main() {
PARSE_AND_PRINT(float, "%f", "%f", "0.3715");
PARSE_AND_PRINT(float, "%f", "%f", ".3715");
PARSE_AND_PRINT(float, "%f", "%f", "3715");
PARSE_AND_PRINT(float, "%f", "%f", "111.11");
PARSE_AND_PRINT(float, "%f", "%f", "-2.22");
PARSE_AND_PRINT(float, "%f", "%f", "Nan");
PARSE_AND_PRINT(float, "%f", "%f", "nAn(2)");
PARSE_AND_PRINT(float, "%f", "%f", "-NAN(_asdfZXCV1234_)");
PARSE_AND_PRINT(float, "%f", "%f", "-nan");
PARSE_AND_PRINT(float, "%f", "%f", "+nan");
PARSE_AND_PRINT(float, "%f", "%f", "inF");
PARSE_AND_PRINT(float, "%f", "%f", "iNfINiTy");
PARSE_AND_PRINT(float, "%f", "%f", "+inf");
PARSE_AND_PRINT(float, "%f", "%f", "-inf");
PARSE_AND_PRINT(float, "%f", "%f", "0X1.BC70A3D70A3D7P+6");
PARSE_AND_PRINT(float, "%f", "%f", "1.18973e+4932zzz");
PARSE_AND_PRINT(float, "%f", "%.10f", " -0.0000000123junk");
PARSE_AND_PRINT(float, "%f", "%f", "junk");
return 0;
}
+1 -1
View File
@@ -50,7 +50,7 @@
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/consts/termios.h"
#include "libc/time/time.h"
#include "libc/time.h"
#include "third_party/getopt/getopt.internal.h"
// clang-format off
+1 -1
View File
@@ -17,7 +17,7 @@
#include "libc/sysv/consts/itimer.h"
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
#include "libc/time/time.h"
#include "libc/time.h"
volatile bool gotalrm;
+30 -11
View File
@@ -8,16 +8,18 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/struct/stat.h"
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/s.h"
#include "libc/x/xiso8601.h"
#include "libc/time.h"
/**
* @fileoverview File metadata viewer.
@@ -27,6 +29,23 @@
bool numeric;
char *xiso8601(struct timespec ts) {
struct tm tm;
if (!localtime_r(&ts.tv_sec, &tm))
return 0;
int len = 128;
char *res = malloc(len);
char *ptr = res;
char *end = res + len;
if (!res)
return 0;
ptr += strftime(ptr, end - ptr, "%Y-%m-%d %H:%M:%S", &tm);
ptr += snprintf(ptr, end - ptr, ".%09ld", ts.tv_nsec);
ptr += strftime(ptr, end - ptr, "%z %Z", &tm);
unassert(ptr + 1 <= end);
return res;
}
const char *DescribeFileType(unsigned mode) {
switch (mode & S_IFMT) {
case S_IFIFO:
@@ -74,16 +93,16 @@ void PrintFileMetadata(const char *pathname, struct stat *st) {
"%-32s%s\n"
"%-32s%s\n"
"%-32s%s\n",
"bytes in file", st->st_size, "physical bytes", st->st_blocks * 512,
"device id w/ file", st->st_dev, "inode", st->st_ino,
"hard link count", st->st_nlink, "mode / permissions", st->st_mode,
DescribeFileType(st->st_mode), "owner id", st->st_uid, "group id",
st->st_gid, "flags", st->st_flags, "gen", st->st_gen,
"device id (if special)", st->st_rdev, "block size", st->st_blksize,
"access time", gc(xiso8601(&st->st_atim)), "modified time",
gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
gc(xiso8601(&st->st_ctim)), "birthtime",
gc(xiso8601(&st->st_birthtim)));
"bytes in file:", st->st_size, "physical bytes:", st->st_blocks * 512,
"device id w/ file:", st->st_dev, "inode:", st->st_ino,
"hard link count:", st->st_nlink, "mode / permissions:", st->st_mode,
DescribeFileType(st->st_mode), "owner id:", st->st_uid,
"group id:", st->st_gid, "flags:", st->st_flags, "gen:", st->st_gen,
"device id (if special):", st->st_rdev, "block size:", st->st_blksize,
"access time:", gc(xiso8601(st->st_atim)),
"modified time:", gc(xiso8601(st->st_mtim)),
"c[omplicated]time:", gc(xiso8601(st->st_ctim)),
"[birthtime]:", gc(xiso8601(st->st_birthtim)));
}
int main(int argc, char *argv[]) {
+16 -11
View File
@@ -2601,7 +2601,8 @@ static int shlex() {
case 'y':
case 'z':
p = buf;
while (buf++, is_in_name(*buf));
while (buf++, is_in_name(*buf))
;
yylval.name = stalloc(buf - p + 1);
*(char *)mempcpy(yylval.name, p, buf - p) = 0;
value = ARITH_VAR;
@@ -7757,7 +7758,8 @@ static int ulimitcmd(int argc, char **argv) {
what = optc;
}
}
for (l = limits; l->option != what; l++);
for (l = limits; l->option != what; l++)
;
set = *argptr ? 1 : 0;
if (set) {
char *p = *argptr;
@@ -7986,7 +7988,8 @@ static void setparam(char **argv) {
char **newparam;
char **ap;
int nparam;
for (nparam = 0; argv[nparam]; nparam++);
for (nparam = 0; argv[nparam]; nparam++)
;
ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
while (*argv) {
*ap++ = savestr(*argv++);
@@ -8664,7 +8667,8 @@ static void parsefname(void) {
if (heredoclist == NULL)
heredoclist = here;
else {
for (p = heredoclist; p->next; p = p->next);
for (p = heredoclist; p->next; p = p->next)
;
p->next = here;
}
} else if (n->type == NTOFD || n->type == NFROMFD) {
@@ -8788,7 +8792,8 @@ static int xxreadtoken(void) {
case '\t':
continue;
case '#':
while ((c = pgetc()) != '\n' && c != PEOF);
while ((c = pgetc()) != '\n' && c != PEOF)
;
pungetc();
continue;
case '\n':
@@ -8912,7 +8917,7 @@ static int readtoken1(int firstc, char const *syntax, char *eofmark,
quotef = 0;
bqlist = NULL;
STARTSTACKSTR(out);
loop: { /* for each line, until end of word */
loop : { /* for each line, until end of word */
CHECKEND(); /* set c to PEOF if at end of here document */
for (;;) { /* until end of line or end of word */
CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
@@ -9064,7 +9069,7 @@ endword:
* is called, c is set to the first character of the next input line. If
* we are at the end of the here document, this routine sets the c to PEOF.
*/
checkend: {
checkend : {
if (realeofmark(eofmark)) {
int markloc;
char *p;
@@ -9107,7 +9112,7 @@ checkend: {
* specifying the fd to be redirected. The variable "c" contains the
* first character of the redirection operator.
*/
parseredir: {
parseredir : {
char fd = *out;
union node *np;
np = (union node *)stalloc(sizeof(struct nfile));
@@ -9164,7 +9169,7 @@ parseredir: {
* Parse a substitution. At this point, we have read the dollar sign
* and nothing else.
*/
parsesub: {
parsesub : {
int subtype;
int typeloc;
char *p;
@@ -9282,7 +9287,7 @@ parsesub: {
* list of commands (passed by reference), and savelen is the number of
* characters on the top of the stack which must be preserved.
*/
parsebackq: {
parsebackq : {
struct nodelist **nlpp;
union node *n;
char *str;
@@ -9377,7 +9382,7 @@ parsebackq: {
/*
* Parse an arithmetic expansion (indicate start of one and set state)
*/
parsearith: {
parsearith : {
synstack_push(&synstack, synstack->prev ?: alloca(sizeof(*synstack)),
ARISYNTAX);
synstack->dblquote = 1;
+1 -1
View File
@@ -9,11 +9,11 @@
#endif
#include "libc/errno.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/ftw.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/s.h"
#include "libc/stdio/ftw.h"
/**
* @fileoverview Directory walker example.
+1 -1
View File
@@ -16,7 +16,7 @@
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
#include "libc/time/struct/tm.h"
#include "libc/time.h"
#include "third_party/getopt/getopt.internal.h"
#include "third_party/musl/passwd.h"
+1 -91
View File
@@ -4,10 +4,8 @@
PKGS += LIBC
LIBC_ISYSTEM = \
libc/isystem/algorithm \
libc/isystem/alloca.h \
libc/isystem/ammintrin.h \
libc/isystem/any \
libc/isystem/ar.h \
libc/isystem/arm_acle.h \
libc/isystem/arm_bf16.h \
@@ -15,51 +13,16 @@ libc/isystem/arm_fp16.h \
libc/isystem/arm_neon.h \
libc/isystem/arpa/inet.h \
libc/isystem/arpa/nameser.h \
libc/isystem/array \
libc/isystem/assert.h \
libc/isystem/atomic \
libc/isystem/bit \
libc/isystem/bitset \
libc/isystem/byteswap.h \
libc/isystem/cassert \
libc/isystem/ccomplex \
libc/isystem/cctype \
libc/isystem/cerrno \
libc/isystem/cfenv \
libc/isystem/cfloat \
libc/isystem/charconv \
libc/isystem/chrono \
libc/isystem/cinttypes \
libc/isystem/ciso646 \
libc/isystem/climits \
libc/isystem/clocale \
libc/isystem/clzerointrin.h \
libc/isystem/cmath \
libc/isystem/codecvt \
libc/isystem/compare \
libc/isystem/complex \
libc/isystem/complex.h \
libc/isystem/condition_variable \
libc/isystem/cosmo.h \
libc/isystem/cpio.h \
libc/isystem/cpuid.h \
libc/isystem/crypt.h \
libc/isystem/csetjmp \
libc/isystem/csignal \
libc/isystem/cstdarg \
libc/isystem/cstdbool \
libc/isystem/cstddef \
libc/isystem/cstdint \
libc/isystem/cstdio \
libc/isystem/cstdlib \
libc/isystem/cstring \
libc/isystem/ctgmath \
libc/isystem/ctime \
libc/isystem/ctype.h \
libc/isystem/cwchar \
libc/isystem/cwctype \
libc/isystem/cxxabi.h \
libc/isystem/deque \
libc/isystem/dirent.h \
libc/isystem/dlfcn.h \
libc/isystem/elf.h \
@@ -67,57 +30,37 @@ libc/isystem/emmintrin.h \
libc/isystem/endian.h \
libc/isystem/err.h \
libc/isystem/errno.h \
libc/isystem/exception \
libc/isystem/execution \
libc/isystem/fcntl.h \
libc/isystem/features.h \
libc/isystem/fenv.h \
libc/isystem/filesystem \
libc/isystem/float.h \
libc/isystem/fnmatch.h \
libc/isystem/forward_list \
libc/isystem/fstream \
libc/isystem/ftw.h \
libc/isystem/functional \
libc/isystem/future \
libc/isystem/getopt.h \
libc/isystem/glob.h \
libc/isystem/grp.h \
libc/isystem/iconv.h \
libc/isystem/ifaddrs.h \
libc/isystem/immintrin.h \
libc/isystem/initializer_list \
libc/isystem/inttypes.h \
libc/isystem/iomanip \
libc/isystem/ios \
libc/isystem/iosfwd \
libc/isystem/iostream \
libc/isystem/iso646.h \
libc/isystem/istream \
libc/isystem/iterator \
libc/isystem/langinfo.h \
libc/isystem/libgen.h \
libc/isystem/limits \
libc/isystem/limits.h \
libc/isystem/link.h \
libc/isystem/linux/futex.h \
libc/isystem/linux/limits.h \
libc/isystem/linux/param.h \
libc/isystem/linux/types.h \
libc/isystem/list \
libc/isystem/locale \
libc/isystem/locale.h \
libc/isystem/malloc.h \
libc/isystem/map \
libc/isystem/math.h \
libc/isystem/memory \
libc/isystem/memory.h \
libc/isystem/mm3dnow.h \
libc/isystem/mm_malloc.h \
libc/isystem/mmintrin.h \
libc/isystem/mntent.h \
libc/isystem/monetary.h \
libc/isystem/mutex \
libc/isystem/mwaitxintrin.h \
libc/isystem/net/ethernet.h \
libc/isystem/net/if.h \
@@ -127,7 +70,6 @@ libc/isystem/netinet/in.h \
libc/isystem/netinet/ip.h \
libc/isystem/netinet/tcp.h \
libc/isystem/netinet/udp.h \
libc/isystem/new \
libc/isystem/nl_types.h \
libc/isystem/nmmintrin.h \
libc/isystem/nsync.h \
@@ -141,12 +83,9 @@ libc/isystem/nsync_note.h \
libc/isystem/nsync_once.h \
libc/isystem/nsync_time.h \
libc/isystem/nsync_waiter.h \
libc/isystem/numeric \
libc/isystem/omp-tools.h \
libc/isystem/omp.h \
libc/isystem/ompx.h \
libc/isystem/optional \
libc/isystem/ostream \
libc/isystem/paths.h \
libc/isystem/pmmintrin.h \
libc/isystem/poll.h \
@@ -154,27 +93,17 @@ libc/isystem/popcntintrin.h \
libc/isystem/pthread.h \
libc/isystem/pty.h \
libc/isystem/pwd.h \
libc/isystem/queue \
libc/isystem/random \
libc/isystem/ratio \
libc/isystem/regex \
libc/isystem/regex.h \
libc/isystem/resolv.h \
libc/isystem/sched.h \
libc/isystem/scoped_allocator \
libc/isystem/search.h \
libc/isystem/semaphore.h \
libc/isystem/set \
libc/isystem/setjmp.h \
libc/isystem/sgxintrin.h \
libc/isystem/shadow.h \
libc/isystem/shared_mutex \
libc/isystem/signal.h \
libc/isystem/smmintrin.h \
libc/isystem/span \
libc/isystem/spawn.h \
libc/isystem/sstream \
libc/isystem/stack \
libc/isystem/stdalign.h \
libc/isystem/stdarg.h \
libc/isystem/stdatomic.h \
@@ -182,18 +111,13 @@ libc/isystem/stdbool.h \
libc/isystem/stdc-predef.h \
libc/isystem/stdckdint.h \
libc/isystem/stddef.h \
libc/isystem/stdexcept \
libc/isystem/stdint.h \
libc/isystem/stdio.h \
libc/isystem/stdio_ext.h \
libc/isystem/stdlib.h \
libc/isystem/stdnoreturn.h \
libc/isystem/streambuf \
libc/isystem/string \
libc/isystem/string.h \
libc/isystem/string_view \
libc/isystem/strings.h \
libc/isystem/strstream \
libc/isystem/sys/auxv.h \
libc/isystem/sys/cdefs.h \
libc/isystem/sys/dir.h \
@@ -238,39 +162,26 @@ libc/isystem/sys/vfs.h \
libc/isystem/sys/wait.h \
libc/isystem/sysexits.h \
libc/isystem/syslog.h \
libc/isystem/system_error \
libc/isystem/termios.h \
libc/isystem/tgmath.h \
libc/isystem/thread \
libc/isystem/threads.h \
libc/isystem/time.h \
libc/isystem/tmmintrin.h \
libc/isystem/tuple \
libc/isystem/type_traits \
libc/isystem/typeindex \
libc/isystem/typeinfo \
libc/isystem/uchar.h \
libc/isystem/ucontext.h \
libc/isystem/uio.h \
libc/isystem/unistd.h \
libc/isystem/unordered_map \
libc/isystem/unordered_set \
libc/isystem/unwind.h \
libc/isystem/utility \
libc/isystem/utime.h \
libc/isystem/utmp.h \
libc/isystem/utmpx.h \
libc/isystem/valarray \
libc/isystem/variant \
libc/isystem/vector \
libc/isystem/version \
libc/isystem/wait.h \
libc/isystem/wchar.h \
libc/isystem/wctype.h \
libc/isystem/winternl.h \
libc/isystem/wmmintrin.h \
libc/isystem/x86intrin.h \
libc/isystem/xmmintrin.h
libc/isystem/xmmintrin.h \
LIBC_HDRS = $(filter %.h,$(LIBC_FILES)) $(LIBC_ISYSTEM)
LIBC_HDRS_H = $(filter %.h,$(LIBC_HDRS))
@@ -300,7 +211,6 @@ o/$(MODE)/libc: o/$(MODE)/libc/calls \
o/$(MODE)/libc/sysv \
o/$(MODE)/libc/testlib \
o/$(MODE)/libc/thread \
o/$(MODE)/libc/time \
o/$(MODE)/libc/tinymath \
o/$(MODE)/libc/vga \
o/$(MODE)/libc/x \
+7
View File
@@ -147,6 +147,13 @@ o/$(MODE)/libc/calls/pledge-linux.o: private \
-fPIC \
-ffreestanding
# we want -Os because:
# it makes a big difference
# it gets called very rarely
o/$(MODE)/libc/calls/sigcrashsig.o: private \
CFLAGS += \
-Os
# these assembly files are safe to build on aarch64
o/$(MODE)/libc/calls/getcontext.o: libc/calls/getcontext.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
+1 -1
View File
@@ -23,7 +23,7 @@
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
#include "libc/time.h"
static int sys_clock_getres_poly(int clock, struct timespec *ts, int64_t real,
int64_t real_coarse, int64_t boot) {
+3 -3
View File
@@ -10,12 +10,12 @@ void end_cancelation_point(int);
#define END_CANCELATION_POINT (void)0
#else
#define BEGIN_CANCELATION_POINT \
do { \
int _Cp; \
do { \
int _Cp; \
_Cp = begin_cancelation_point()
#define END_CANCELATION_POINT \
end_cancelation_point(_Cp); \
} \
} \
while (0)
#endif
+1 -1
View File
@@ -23,8 +23,8 @@
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Duplicates file descriptor.
+1 -1
View File
@@ -76,7 +76,7 @@ int dup2(int oldfd, int newfd) {
rc = oldfd;
} else
#endif
if (!IsWindows()) {
if (!IsWindows()) {
if (__isfdkind(oldfd, kFdZip) || __isfdkind(newfd, kFdZip)) {
if (__vforked) {
return enotsup();
File renamed without changes.
+5 -14
View File
@@ -48,20 +48,11 @@ int getcpu(unsigned *out_opt_cpu, unsigned *out_opt_node) {
} else {
return __winerr();
}
} else if (IsXnuSilicon()) {
if (__syslib->__version >= 9) {
size_t cpu64;
errno_t err = __syslib->__pthread_cpu_number_np(&cpu64);
if (!err) {
cpu = cpu64;
node = 0;
} else {
errno = err;
return -1;
}
} else {
return enosys();
}
} else if (IsAarch64()) {
long tpidr_el0;
asm("mrs\t%0,tpidr_el0" : "=r"(tpidr_el0));
cpu = tpidr_el0 & 255;
node = 0;
} else {
int rc = sys_getcpu(&cpu, &node, 0);
if (rc == -1)
+1 -1
View File
@@ -19,7 +19,7 @@
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/sysv/consts/clock.h"
#include "libc/time/struct/timezone.h"
#include "libc/time.h"
/**
* Returns system wall time in microseconds, e.g.
+1 -1
View File
@@ -66,7 +66,7 @@ static struct HostAdapterInfoNode {
struct sockaddr netmask;
struct sockaddr broadcast;
short flags;
} * __hostInfo;
} *__hostInfo;
static int ioctl_default(int fd, unsigned long request, void *arg) {
int rc;
+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 "libc/serialize.h"
#include "libc/proc/execve.internal.h"
#include "libc/serialize.h"
/**
* Returns true if executable image is supported by APE Loader.
+1 -1
View File
@@ -24,8 +24,8 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Creates hard filesystem link.
+1 -1
View File
@@ -24,9 +24,9 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
/**
* Creates directory a.k.a. folder.
+18 -21
View File
@@ -23,6 +23,7 @@
#include "libc/mem/mem.h"
#include "libc/nt/files.h"
#include "libc/proc/ntspawn.h"
#include "libc/stdio/sysparam.h"
#include "libc/str/str.h"
#include "libc/str/thompike.h"
#include "libc/str/utf16.h"
@@ -31,16 +32,14 @@
#define APPEND(c) \
do { \
if (k == 32766) { \
return e2big(); \
} \
cmdline[k++] = c; \
if (k < size) \
cmdline[k] = c; \
++k; \
} while (0)
static bool NeedsQuotes(const char *s) {
if (!*s) {
static textwindows bool NeedsQuotes(const char *s) {
if (!*s)
return true;
}
do {
switch (*s) {
case '"':
@@ -60,7 +59,7 @@ static inline int IsAlpha(int c) {
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}
static bool LooksLikeCosmoDrivePath(const char *s) {
static textwindows bool LooksLikeCosmoDrivePath(const char *s) {
return s[0] == '/' && //
IsAlpha(s[1]) && //
s[2] == '/';
@@ -74,12 +73,13 @@ static bool LooksLikeCosmoDrivePath(const char *s) {
//
// @param cmdline is output buffer
// @param argv is an a NULL-terminated array of UTF-8 strings
// @return 0 on success, or -1 w/ errno
// @raise E2BIG if everything is too huge
// @param size is number of characters in cmdline buffer
// @return length on success, which is >=size on truncation
// @see "Everyone quotes command line arguments the wrong way" MSDN
// @see libc/runtime/getdosargv.c
// @asyncsignalsafe
textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
textwindows size_t mkntcmdline(char16_t *cmdline, char *const argv[],
size_t size) {
char *arg;
int slashes, n;
bool needsquote;
@@ -95,9 +95,8 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
} else {
arg = argv[i];
}
if ((needsquote = NeedsQuotes(arg))) {
if ((needsquote = NeedsQuotes(arg)))
APPEND(u'"');
}
for (slashes = j = 0;;) {
wint_t x = arg[j++] & 255;
if (x >= 0300) {
@@ -122,9 +121,8 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
APPEND(u'"');
APPEND(u'"');
} else {
for (s = 0; s < slashes; ++s) {
for (s = 0; s < slashes; ++s)
APPEND(u'\\');
}
slashes = 0;
uint32_t w = EncodeUtf16(x);
do
@@ -132,13 +130,12 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
while ((w >>= 16));
}
}
for (s = 0; s < (slashes << needsquote); ++s) {
for (s = 0; s < (slashes << needsquote); ++s)
APPEND(u'\\');
}
if (needsquote) {
if (needsquote)
APPEND(u'"');
}
}
cmdline[k] = 0;
return 0;
if (size)
cmdline[MIN(k, size - 1)] = 0;
return k;
}
+168 -86
View File
@@ -20,9 +20,15 @@
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filesharemode.h"
#include "libc/nt/enum/processaccess.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/errors.h"
#include "libc/nt/events.h"
#include "libc/nt/files.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
@@ -33,6 +39,7 @@
#include "libc/nt/struct/startupinfo.h"
#include "libc/nt/struct/startupinfoex.h"
#include "libc/proc/ntspawn.h"
#include "libc/stdalign.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
#ifdef __x86_64__
@@ -44,14 +51,167 @@ struct SpawnBlock {
char envbuf[32767];
};
static void *ntspawn_malloc(size_t size) {
static textwindows void *ntspawn_malloc(size_t size) {
return HeapAlloc(GetProcessHeap(), 0, size);
}
static void ntspawn_free(void *ptr) {
static textwindows void ntspawn_free(void *ptr) {
HeapFree(GetProcessHeap(), 0, ptr);
}
static textwindows ssize_t ntspawn_read(intptr_t fh, char *buf, size_t len) {
bool ok;
uint32_t got;
struct NtOverlapped overlap = {.hEvent = CreateEvent(0, 0, 0, 0)};
ok = (ReadFile(fh, buf, len, 0, &overlap) ||
GetLastError() == kNtErrorIoPending) &&
GetOverlappedResult(fh, &overlap, &got, true);
CloseHandle(overlap.hEvent);
return ok ? got : -1;
}
static textwindows int ntspawn2(struct NtSpawnArgs *a, struct SpawnBlock *sb) {
// make executable path
if (__mkntpathath(a->dirhand, a->prog, 0, sb->path) == -1)
return -1;
// open executable
char *p = sb->envbuf;
char *pe = p + sizeof(sb->envbuf);
intptr_t fh = CreateFile(
sb->path, kNtFileGenericRead,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
kNtOpenExisting, kNtFileAttributeNormal | kNtFileFlagBackupSemantics, 0);
if (fh == -1)
return -1;
ssize_t got = ntspawn_read(fh, p, pe - p);
CloseHandle(fh);
if (got < 3)
return enoexec();
pe = p + got;
// handle shebang
size_t i = 0; // represents space of sb->cmdline consumed
if (p[0] == 'M' && p[1] == 'Z') {
// it's a windows executable
} else if (p[0] == '#' && p[1] == '!') {
p += 2;
// make sure we got a complete first line
pe = memchr(p, '\n', pe - p);
if (!pe)
return enoexec();
*pe = 0;
int argc = 0;
char *argv[4];
// it's legal to say "#! /bin/sh"
while (p < pe && (*p == ' ' || *p == '\t'))
++p;
if (p == pe)
return enoexec();
argv[argc++] = p;
// find the optional argument
while (p < pe && !(*p == ' ' || *p == '\t'))
++p;
if (p < pe) {
*p++ = 0;
while (p < pe && (*p == ' ' || *p == '\t'))
++p;
if (p < pe) {
argv[argc++] = p;
}
}
// now add the prog
argv[argc++] = (char *)a->prog;
argv[argc] = 0;
// ignore argv[0]
if (*a->argv)
++a->argv;
// prepend arguments
if ((i += mkntcmdline(sb->cmdline + i, argv, 32767 - i)) >= 32767 - 1)
return e2big();
sb->cmdline[i++] = ' ';
sb->cmdline[i] = 0;
// setup the true executable path
if (__mkntpathath(a->dirhand, argv[0], 0, sb->path) == -1)
return -1;
} else {
// it's something else
return enoexec();
}
// setup arguments and environment
if ((i += mkntcmdline(sb->cmdline + i, a->argv, 32767 - i)) >= 32767)
return e2big();
if (mkntenvblock(sb->envblock, a->envp, a->extravars, sb->envbuf) == -1)
return -1;
// create attribute list
// this code won't call malloc in practice
bool32 ok;
void *freeme = 0;
alignas(16) char memory[128];
size_t size = sizeof(memory);
struct NtProcThreadAttributeList *alist = (void *)memory;
uint32_t items = !!a->opt_hParentProcess + !!a->opt_lpExplicitHandleList;
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
if (!ok && GetLastError() == kNtErrorInsufficientBuffer) {
ok = !!(alist = freeme = ntspawn_malloc(size));
if (ok) {
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
}
}
if (ok && a->opt_hParentProcess) {
ok = UpdateProcThreadAttribute(
alist, 0, kNtProcThreadAttributeParentProcess, &a->opt_hParentProcess,
sizeof(a->opt_hParentProcess), 0, 0);
}
if (ok && a->opt_lpExplicitHandleList) {
ok = UpdateProcThreadAttribute(
alist, 0, kNtProcThreadAttributeHandleList, a->opt_lpExplicitHandleList,
a->dwExplicitHandleCount * sizeof(*a->opt_lpExplicitHandleList), 0, 0);
}
// create the process
int rc;
if (ok) {
struct NtStartupInfoEx info = {
.StartupInfo = *a->lpStartupInfo,
.lpAttributeList = alist,
};
info.StartupInfo.cb = sizeof(info);
if (ok) {
if (CreateProcess(sb->path, sb->cmdline, 0, 0, true,
a->dwCreationFlags | kNtCreateUnicodeEnvironment |
kNtExtendedStartupinfoPresent |
kNtInheritParentAffinity |
GetPriorityClass(GetCurrentProcess()),
sb->envblock, a->opt_lpCurrentDirectory,
&info.StartupInfo, a->opt_out_lpProcessInformation)) {
rc = 0;
} else {
rc = -1;
STRACE("CreateProcess() failed w/ %d", GetLastError());
if (GetLastError() == kNtErrorSharingViolation) {
etxtbsy();
} else if (GetLastError() == kNtErrorInvalidName) {
enoent();
}
}
rc = __fix_enotdir(rc, sb->path);
}
} else {
rc = __winerr();
}
// clean up resources
if (alist)
DeleteProcThreadAttributeList(alist);
if (freeme)
ntspawn_free(freeme);
return rc;
}
/**
* Spawns process on Windows NT.
*
@@ -72,93 +232,15 @@ static void ntspawn_free(void *ptr) {
* @see spawnve() which abstracts this function
* @asyncsignalsafe
*/
textwindows int ntspawn(
int64_t dirhand, const char *prog, char *const argv[], char *const envp[],
char *const extravars[], uint32_t dwCreationFlags,
const char16_t *opt_lpCurrentDirectory, int64_t opt_hParentProcess,
int64_t *opt_lpExplicitHandleList, uint32_t dwExplicitHandleCount,
const struct NtStartupInfo *lpStartupInfo,
struct NtProcessInformation *opt_out_lpProcessInformation) {
int rc = -1;
textwindows int ntspawn(struct NtSpawnArgs *args) {
int rc;
struct SpawnBlock *sb;
BLOCK_SIGNALS;
if ((sb = ntspawn_malloc(sizeof(*sb))) &&
__mkntpathath(dirhand, prog, 0, sb->path) != -1) {
if (!mkntcmdline(sb->cmdline, argv) &&
!mkntenvblock(sb->envblock, envp, extravars, sb->envbuf)) {
bool32 ok;
int64_t dp = GetCurrentProcess();
// create attribute list
// this code won't call malloc in practice
void *freeme = 0;
_Alignas(16) char memory[128];
size_t size = sizeof(memory);
struct NtProcThreadAttributeList *alist = (void *)memory;
uint32_t items = !!opt_hParentProcess + !!opt_lpExplicitHandleList;
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
if (!ok && GetLastError() == kNtErrorInsufficientBuffer) {
ok = !!(alist = freeme = ntspawn_malloc(size));
if (ok) {
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
}
}
if (ok && opt_hParentProcess) {
ok = UpdateProcThreadAttribute(
alist, 0, kNtProcThreadAttributeParentProcess, &opt_hParentProcess,
sizeof(opt_hParentProcess), 0, 0);
}
if (ok && opt_lpExplicitHandleList) {
ok = UpdateProcThreadAttribute(
alist, 0, kNtProcThreadAttributeHandleList,
opt_lpExplicitHandleList,
dwExplicitHandleCount * sizeof(*opt_lpExplicitHandleList), 0, 0);
}
// create the process
if (ok) {
struct NtStartupInfoEx info;
bzero(&info, sizeof(info));
info.StartupInfo = *lpStartupInfo;
info.StartupInfo.cb = sizeof(info);
info.lpAttributeList = alist;
if (ok) {
if (CreateProcess(sb->path, sb->cmdline, 0, 0, true,
dwCreationFlags | kNtCreateUnicodeEnvironment |
kNtExtendedStartupinfoPresent |
kNtInheritParentAffinity |
GetPriorityClass(GetCurrentProcess()),
sb->envblock, opt_lpCurrentDirectory,
&info.StartupInfo, opt_out_lpProcessInformation)) {
rc = 0;
} else {
STRACE("CreateProcess() failed w/ %d", GetLastError());
if (GetLastError() == kNtErrorSharingViolation) {
etxtbsy();
} else if (GetLastError() == kNtErrorInvalidName) {
enoent();
}
}
rc = __fix_enotdir(rc, sb->path);
}
} else {
rc = __winerr();
}
// clean up resources
if (alist) {
DeleteProcThreadAttributeList(alist);
}
if (freeme) {
ntspawn_free(freeme);
}
if (dp && dp != GetCurrentProcess()) {
CloseHandle(dp);
}
}
if ((sb = ntspawn_malloc(sizeof(*sb)))) {
rc = ntspawn2(args, sb);
} else {
rc = -1;
}
if (sb)
ntspawn_free(sb);
ALLOW_SIGNALS;
return rc;
}
+1 -1
View File
@@ -27,13 +27,13 @@
#include "libc/mem/mem.h"
#include "libc/runtime/pc.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
#ifdef __x86_64__
+1 -2
View File
@@ -1641,7 +1641,6 @@ static privileged void AllowMmapExec(struct Filter *f) {
//
// - MAP_LOCKED (0x02000)
// - MAP_NONBLOCK (0x10000)
// - MAP_HUGETLB (0x40000)
//
static privileged void AllowMmapNoexec(struct Filter *f) {
static const struct sock_filter fragment[] = {
@@ -1650,7 +1649,7 @@ static privileged void AllowMmapNoexec(struct Filter *f) {
/*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, ~(PROT_READ | PROT_WRITE)),
/*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 8 - 4),
/*L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[3])), // flags
/*L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x52000),
/*L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x12000),
/*L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1),
/*L7*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
/*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
+16 -12
View File
@@ -24,11 +24,13 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/promises.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/pr.h"
#include "libc/sysv/errfuns.h"
@@ -199,22 +201,22 @@
* `__pledge_mode` is available to improve the experience of pledge() on
* Linux. It should specify one of the following penalties:
*
* - `PLEDGE_PENALTY_RETURN_EPERM` causes system calls to just return an
* `EPERM` error instead of killing. This is the default on Linux.
* This is a gentler solution that allows code to display a friendly
* warning. Please note this may lead to weird behaviors if the
* software being sandboxed is lazy about checking error results.
*
* - `PLEDGE_PENALTY_KILL_THREAD` causes the violating thread to be
* killed. This is the default on Linux. It's effectively the same as
* killing the process, since redbean has no threads. The termination
* signal can't be caught and will be either `SIGSYS` or `SIGABRT`.
* Consider enabling stderr logging below so you'll know why your
* program failed. Otherwise check the system log.
* killed. It's effectively the same as killing the process, since
* redbean has no threads. The termination signal can't be caught and
* will be either `SIGSYS` or `SIGABRT`. Consider enabling stderr
* logging below so you'll know why your program failed. Otherwise
* check the system log.
*
* - `PLEDGE_PENALTY_KILL_PROCESS` causes the process and all its
* threads to be killed. This is always the case on OpenBSD.
*
* - `PLEDGE_PENALTY_RETURN_EPERM` causes system calls to just return an
* `EPERM` error instead of killing. This is a gentler solution that
* allows code to display a friendly warning. Please note this may
* lead to weird behaviors if the software being sandboxed is lazy
* about checking error results.
*
* `mode` may optionally bitwise or the following flags:
*
* - `PLEDGE_STDERR_LOGGING` enables friendly error message logging
@@ -240,6 +242,8 @@
int pledge(const char *promises, const char *execpromises) {
int e, rc;
unsigned long ipromises, iexecpromises;
if (_weaken(GetSymbolTable))
_weaken(GetSymbolTable)();
if (!promises) {
// OpenBSD says NULL argument means it doesn't change, i.e.
// pledge(0,0) on OpenBSD does nothing. The Cosmopolitan Libc
+6 -1
View File
@@ -30,6 +30,7 @@
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/stdio/sysparam.h"
#include "libc/sysv/errfuns.h"
/**
@@ -39,7 +40,7 @@
*
* @param fd is something open()'d earlier, noting pipes might not work
* @param buf is copied into, cf. copy_file_range(), sendfile(), etc.
* @param size in range [1..0x7ffff000] is reasonable
* @param size is always saturated to 0x7ffff000 automatically
* @param offset is bytes from start of file at which read begins
* @return [1..size] bytes on success, 0 on EOF, or -1 w/ errno; with
* exception of size==0, in which case return zero means no error
@@ -58,6 +59,10 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
ssize_t rc;
BEGIN_CANCELATION_POINT;
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
// this is inconsistent with Linux which ignores huge requests
size = MIN(size, 0x7ffff000);
if (offset < 0) {
rc = einval();
} else if (fd < 0) {
+43 -7
View File
@@ -28,24 +28,55 @@
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/mem/alloca.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"
static size_t SumIovecBytes(const struct iovec *iov, int iovlen) {
size_t count = 0;
for (int i = 0; i < iovlen; ++i)
if (ckd_add(&count, count, iov[i].iov_len))
count = SIZE_MAX;
return count;
}
static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
int e, i;
size_t got;
ssize_t rc, toto;
if (fd < 0) {
if (fd < 0)
return ebadf();
}
if (iovlen < 0) {
if (iovlen < 0)
return einval();
}
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
return efault();
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
// this is inconsistent with Linux which ignores huge requests
if (!IsLinux()) {
size_t sum, remain = 0x7ffff000;
if ((sum = SumIovecBytes(iov, iovlen)) > remain) {
struct iovec *iov2;
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Walloca-larger-than="
iov2 = alloca(iovlen * sizeof(struct iovec));
CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec));
#pragma GCC pop_options
for (int i = 0; i < iovlen; ++i) {
iov2[i] = iov[i];
if (remain >= iov2[i].iov_len) {
remain -= iov2[i].iov_len;
} else {
iov2[i].iov_len = remain;
remain = 0;
}
}
iov = iov2;
}
}
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
@@ -112,6 +143,11 @@ static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
/**
* Reads with maximum generality.
*
* It's possible for file write request to be partially completed. For
* example, if the sum of `iov` lengths exceeds 0x7ffff000 then bytes
* beyond that will be ignored. This is a Linux behavior that Cosmo
* polyfills across platforms.
*
* @return number of bytes actually read, or -1 w/ errno
* @cancelationpoint
* @asyncsignalsafe
+6 -1
View File
@@ -28,6 +28,7 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/stdio/sysparam.h"
#include "libc/sysv/errfuns.h"
/**
@@ -37,7 +38,7 @@
*
* @param fd is something open()'d earlier, noting pipes might not work
* @param buf is copied from, cf. copy_file_range(), sendfile(), etc.
* @param size in range [1..0x7ffff000] is reasonable
* @param size is always saturated to 0x7ffff000 automatically
* @param offset is bytes from start of file at which write begins,
* which can exceed or overlap the end of file, in which case your
* file will be extended
@@ -53,6 +54,10 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
size_t wrote;
BEGIN_CANCELATION_POINT;
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
// this is inconsistent with Linux which ignores huge requests
size = MIN(size, 0x7ffff000);
if (offset < 0) {
rc = einval();
} else if (fd == -1) {
+44 -10
View File
@@ -28,28 +28,57 @@
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/mem/alloca.h"
#include "libc/runtime/stack.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"
static size_t SumIovecBytes(const struct iovec *iov, int iovlen) {
size_t count = 0;
for (int i = 0; i < iovlen; ++i)
if (ckd_add(&count, count, iov[i].iov_len))
count = SIZE_MAX;
return count;
}
static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
int64_t off) {
int i, e;
size_t sent;
ssize_t rc, toto;
if (fd < 0) {
if (fd < 0)
return ebadf();
}
if (iovlen < 0) {
if (iovlen < 0)
return einval();
}
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
return efault();
}
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)
return ebadf();
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
// this is inconsistent with Linux which ignores huge requests
if (!IsLinux()) {
size_t sum, remain = 0x7ffff000;
if ((sum = SumIovecBytes(iov, iovlen)) > remain) {
struct iovec *iov2;
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Walloca-larger-than="
iov2 = alloca(iovlen * sizeof(struct iovec));
CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec));
#pragma GCC pop_options
for (int i = 0; i < iovlen; ++i) {
iov2[i] = iov[i];
if (remain >= iov2[i].iov_len) {
remain -= iov2[i].iov_len;
} else {
iov2[i].iov_len = remain;
remain = 0;
}
}
iov = iov2;
}
}
if (IsWindows()) {
@@ -116,6 +145,11 @@ static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
* been committed. It can also happen if we need to polyfill this system
* call using pwrite().
*
* It's possible for file write request to be partially completed. For
* example, if the sum of `iov` lengths exceeds 0x7ffff000 then bytes
* beyond that will be ignored. This is a Linux behavior that Cosmo
* polyfills across platforms.
*
* @return number of bytes actually sent, or -1 w/ errno
* @cancelationpoint
* @asyncsignalsafe
+6 -1
View File
@@ -29,6 +29,7 @@
#include "libc/runtime/zipos.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/stdio/sysparam.h"
#include "libc/sysv/errfuns.h"
/**
@@ -41,7 +42,7 @@
*
* @param fd is something open()'d earlier
* @param buf is copied into, cf. copy_file_range(), sendfile(), etc.
* @param size in range [1..0x7ffff000] is reasonable
* @param size is always saturated to 0x7ffff000 automatically
* @return [1..size] bytes on success, 0 on EOF, or -1 w/ errno; with
* exception of size==0, in which case return zero means no error
* @raise EBADF if `fd` is negative or not an open file descriptor
@@ -67,6 +68,10 @@ ssize_t read(int fd, void *buf, size_t size) {
ssize_t rc;
BEGIN_CANCELATION_POINT;
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
// this is inconsistent with Linux which ignores huge requests
size = MIN(size, 0x7ffff000);
if (fd < 0) {
rc = ebadf();
} else if ((!buf && size) || (IsAsan() && !__asan_is_valid(buf, size))) {
+70 -26
View File
@@ -28,10 +28,74 @@
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/mem/alloca.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sock/internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"
static size_t SumIovecBytes(const struct iovec *iov, int iovlen) {
size_t count = 0;
for (int i = 0; i < iovlen; ++i)
if (ckd_add(&count, count, iov[i].iov_len))
count = SIZE_MAX;
return count;
}
static ssize_t readv_impl(int fd, const struct iovec *iov, int iovlen) {
if (fd < 0)
return ebadf();
if (iovlen < 0)
return einval();
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
return efault();
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
// this is inconsistent with Linux which ignores huge requests
if (!IsLinux()) {
size_t sum, remain = 0x7ffff000;
if ((sum = SumIovecBytes(iov, iovlen)) > remain) {
struct iovec *iov2;
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Walloca-larger-than="
iov2 = alloca(iovlen * sizeof(struct iovec));
CheckLargeStackAllocation(iov2, iovlen * sizeof(struct iovec));
#pragma GCC pop_options
for (int i = 0; i < iovlen; ++i) {
iov2[i] = iov[i];
if (remain >= iov2[i].iov_len) {
remain -= iov2[i].iov_len;
} else {
iov2[i].iov_len = remain;
remain = 0;
}
}
iov = iov2;
}
}
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return _weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
if (iovlen == 1) {
return sys_read(fd, iov[0].iov_base, iov[0].iov_len);
} else {
return sys_readv(fd, iov, iovlen);
}
} else if (fd >= g_fds.n) {
return ebadf();
} else if (IsMetal()) {
return sys_readv_metal(fd, iov, iovlen);
} else if (IsWindows()) {
return sys_readv_nt(fd, iov, iovlen);
} else {
return enosys();
}
}
/**
* Reads data to multiple buffers.
*
@@ -42,6 +106,11 @@
* be passed to the kernel as read() instead. This yields a 100 cycle
* performance boost in the case of a single small iovec.
*
* It's possible for file write request to be partially completed. For
* example, if the sum of `iov` lengths exceeds 0x7ffff000 then bytes
* beyond that will be ignored. This is a Linux behavior that Cosmo
* polyfills across platforms.
*
* @return number of bytes actually read, or -1 w/ errno
* @cancelationpoint
* @restartable
@@ -49,32 +118,7 @@
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
ssize_t rc;
BEGIN_CANCELATION_POINT;
if (fd < 0) {
rc = ebadf();
} else if (iovlen < 0) {
rc = einval();
} else if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
rc = efault();
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = _weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
if (iovlen == 1) {
rc = sys_read(fd, iov[0].iov_base, iov[0].iov_len);
} else {
rc = sys_readv(fd, iov, iovlen);
}
} else if (fd >= g_fds.n) {
rc = ebadf();
} else if (IsMetal()) {
rc = sys_readv_metal(fd, iov, iovlen);
} else if (IsWindows()) {
rc = sys_readv_nt(fd, iov, iovlen);
} else {
rc = enosys();
}
rc = readv_impl(fd, iov, iovlen);
END_CANCELATION_POINT;
STRACE("readv(%d, [%s], %d) → %'ld% m", fd, DescribeIovec(rc, iov, iovlen),
iovlen, rc);
+1 -4
View File
@@ -19,7 +19,6 @@
#include "libc/calls/calls.h"
#include "libc/calls/struct/framebuffervirtualscreeninfo.h"
#include "libc/dce.h"
#include "libc/nt/enum/version.h"
#include "libc/nt/system.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
@@ -72,9 +71,7 @@ int reboot(int howto) {
} else {
howto |= kNtShutdownForceSelf;
howto |= kNtShutdownForceOthers;
if (NtGetVersion() >= kNtVersionWindows8) {
howto |= kNtShutdownHybrid;
}
howto |= kNtShutdownHybrid;
if (immediately) {
ok = !!InitiateShutdown(0, 0, 0, howto | kNtShutdownGraceOverride, 0);
} else {
+1 -1
View File
@@ -24,9 +24,9 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/runtime/zipos.internal.h"
/**
* Renames files relative to directories.
+4 -15
View File
@@ -17,14 +17,12 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/cpuset.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nexgen32e/rdtscp.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/nt/struct/processornumber.h"
#include "libc/nt/synchronization.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/errfuns.h"
int sys_getcpu(unsigned *opt_cpu, unsigned *opt_node, void *tcache);
@@ -38,23 +36,14 @@ int sched_getcpu(void) {
unsigned tsc_aux;
rdtscp(&tsc_aux);
return TSC_AUX_CORE(tsc_aux);
} else if (IsAarch64()) {
long tpidr_el0;
asm("mrs\t%0,tpidr_el0" : "=r"(tpidr_el0));
return tpidr_el0 & 255;
} else if (IsWindows()) {
struct NtProcessorNumber pn;
GetCurrentProcessorNumberEx(&pn);
return 64 * pn.Group + pn.Number;
} else if (IsXnuSilicon()) {
if (__syslib->__version >= 9) {
size_t cpu;
errno_t err = __syslib->__pthread_cpu_number_np(&cpu);
if (!err) {
return cpu;
} else {
errno = err;
return -1;
}
} else {
return enosys();
}
} else {
unsigned cpu = 0;
int rc = sys_getcpu(&cpu, 0, 0);
+1 -1
View File
@@ -22,7 +22,7 @@
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/struct/timezone.h"
#include "libc/time.h"
/**
* Changes time.
+27 -75
View File
@@ -301,7 +301,7 @@ static textwindows wontreturn void __sig_tramp(struct SignalFrame *sf) {
}
// sends signal to another specific thread which is ref'd
static int __sig_killer(struct PosixThread *pt, int sig, int sic) {
static textwindows int __sig_killer(struct PosixThread *pt, int sig, int sic) {
unsigned rva = __sighandrvas[sig];
unsigned flags = __sighandflags[sig];
@@ -462,66 +462,7 @@ textwindows void __sig_generate(int sig, int sic) {
ALLOW_SIGNALS;
}
static int __sig_crash_sig(struct NtExceptionPointers *ep, int *code) {
switch (ep->ExceptionRecord->ExceptionCode) {
case kNtSignalBreakpoint:
*code = TRAP_BRKPT;
return SIGTRAP;
case kNtSignalIllegalInstruction:
*code = ILL_ILLOPC;
return SIGILL;
case kNtSignalPrivInstruction:
*code = ILL_PRVOPC;
return SIGILL;
case kNtSignalInPageError:
case kNtStatusStackOverflow:
*code = SEGV_MAPERR;
return SIGSEGV;
case kNtSignalGuardPage:
case kNtSignalAccessViolation:
*code = SEGV_ACCERR;
return SIGSEGV;
case kNtSignalInvalidHandle:
case kNtSignalInvalidParameter:
case kNtSignalAssertionFailure:
*code = SI_USER;
return SIGABRT;
case kNtStatusIntegerOverflow:
*code = FPE_INTOVF;
return SIGFPE;
case kNtSignalFltDivideByZero:
*code = FPE_FLTDIV;
return SIGFPE;
case kNtSignalFltOverflow:
*code = FPE_FLTOVF;
return SIGFPE;
case kNtSignalFltUnderflow:
*code = FPE_FLTUND;
return SIGFPE;
case kNtSignalFltInexactResult:
*code = FPE_FLTRES;
return SIGFPE;
case kNtSignalFltDenormalOperand:
case kNtSignalFltInvalidOperation:
case kNtSignalFltStackCheck:
case kNtSignalIntegerDivideByZero:
case kNtSignalFloatMultipleFaults:
case kNtSignalFloatMultipleTraps:
*code = FPE_FLTINV;
return SIGFPE;
case kNtSignalDllNotFound:
case kNtSignalOrdinalNotFound:
case kNtSignalEntrypointNotFound:
case kNtSignalDllInitFailed:
*code = SI_KERNEL;
return SIGSYS;
default:
*code = ep->ExceptionRecord->ExceptionCode;
return SIGSEGV;
}
}
static char *__sig_stpcpy(char *d, const char *s) {
static textwindows char *__sig_stpcpy(char *d, const char *s) {
size_t i;
for (i = 0;; ++i) {
if (!(d[i] = s[i])) {
@@ -530,8 +471,24 @@ static char *__sig_stpcpy(char *d, const char *s) {
}
}
static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
struct CosmoTib *tib) {
static textwindows wontreturn void __sig_death(int sig, const char *thing) {
#ifndef TINY
intptr_t hStderr;
char sigbuf[21], s[128], *p;
hStderr = GetStdHandle(kNtStdErrorHandle);
p = __sig_stpcpy(s, "Terminating on ");
p = __sig_stpcpy(p, thing);
p = __sig_stpcpy(p, strsignal_r(sig, sigbuf));
p = __sig_stpcpy(p,
". Pass --strace and/or ShowCrashReports() for details.\n");
WriteFile(hStderr, s, p - s, 0, 0);
#endif
__sig_terminate(sig);
}
static textwindows void __sig_unmaskable(struct NtExceptionPointers *ep,
int code, int sig,
struct CosmoTib *tib) {
// log vital crash information reliably for --strace before doing much
// we don't print this without the flag since raw numbers scare people
@@ -549,17 +506,7 @@ static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
// exception, then print a friendly helpful hint message to stderr
unsigned rva = __sighandrvas[sig];
if (rva == (intptr_t)SIG_DFL || rva == (intptr_t)SIG_IGN) {
#ifndef TINY
intptr_t hStderr;
char sigbuf[21], s[128], *p;
hStderr = GetStdHandle(kNtStdErrorHandle);
p = __sig_stpcpy(s, "Terminating on uncaught ");
p = __sig_stpcpy(p, strsignal_r(sig, sigbuf));
p = __sig_stpcpy(
p, ". Pass --strace and/or ShowCrashReports() for details.\n");
WriteFile(hStderr, s, p - s, 0, 0);
#endif
__sig_terminate(sig);
__sig_death(sig, "uncaught ");
}
// if this signal handler is configured to auto-reset to the default
@@ -580,8 +527,9 @@ static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
}
// call the user signal handler
// with a temporarily replaced signal mask
// and a modifiable view of the faulting code's cpu state
// temporarily replace signal mask while calling crash handler
// abort process if sig is already blocked to avoid crash loop
// note ucontext_t is a hefty data structures on top of NtContext
ucontext_t ctx = {0};
siginfo_t si = {.si_signo = sig, .si_code = code, .si_addr = si_addr};
@@ -591,6 +539,10 @@ static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig,
blocksigs |= 1ull << (sig - 1);
ctx.uc_sigmask = atomic_fetch_or_explicit(&tib->tib_sigmask, blocksigs,
memory_order_acquire);
if (ctx.uc_sigmask & (1ull << (sig - 1))) {
__sig_death(sig, "masked ");
__sig_terminate(sig);
}
__sig_handler(rva)(sig, &si, &ctx);
atomic_store_explicit(&tib->tib_sigmask, ctx.uc_sigmask,
memory_order_release);
+4 -2
View File
@@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
#include "libc/calls/struct/sigset.h"
#include "libc/nt/struct/ntexceptionpointers.h"
#include "libc/thread/posixthread.internal.h"
#define SIG_HANDLED_NO_RESTART 1
@@ -17,11 +18,12 @@ extern struct Signals __sig;
bool __sig_ignored(int);
int __sig_check(void);
int __sig_crash_sig(struct NtExceptionPointers *, int *);
int __sig_get(sigset_t);
int __sig_kill(struct PosixThread *, int, int);
int __sig_mask(int, const sigset_t *, sigset_t *);
int __sig_relay(int, int, sigset_t);
int __sig_raise(int, int);
int __sig_get(sigset_t);
int __sig_relay(int, int, sigset_t);
void __sig_delete(int);
void __sig_generate(int, int);
void __sig_init(void);
+7 -1
View File
@@ -252,6 +252,12 @@ static int __sigaction(int sig, const struct sigaction *act,
rc = sys_sigaction(sig, ap, oldact, arg4, arg5);
} else {
rc = _sysret(__syslib->__sigaction(sig, ap, oldact));
// xnu silicon claims to support sa_resethand but it does nothing
// this can be tested, since it clears the bit from flags as well
if (!rc && oldact &&
(((struct sigaction_silicon *)oldact)->sa_flags & SA_RESETHAND)) {
((struct sigaction_silicon *)oldact)->sa_flags |= SA_RESETHAND;
}
}
if (rc != -1) {
sigaction_native2cosmo((union metasigaction *)oldact);
@@ -415,7 +421,7 @@ static int __sigaction(int sig, const struct sigaction *act,
* ctx->uc_mcontext.rip += xedd.length;
* }
*
* void OnCrash(int sig, struct siginfo *si, void *vctx) {
* void OnCrash(int sig, siginfo_t *si, void *vctx) {
* struct ucontext *ctx = vctx;
* SkipOverFaultingInstruction(ctx);
* ContinueOnCrash(); // reinstall here in case *rip faults
+107
View File
@@ -0,0 +1,107 @@
/*-*- 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 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 "libc/calls/sig.internal.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/nt/enum/signal.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/struct/ntexceptionpointers.h"
// this is all a mandatory dependency of winmain
// so, we trade away maintanibility for tininess
// see libc/sysv/consts.sh for canonical magnums
#define SIGILL_ pushpop(4)
#define SIGTRAP_ pushpop(5)
#define SIGABRT_ pushpop(6)
#define SIGFPE_ pushpop(8)
#define SIGSEGV_ pushpop(11)
#define SIGSYS_ pushpop(31)
#define TRAP_BRKPT_ pushpop(1)
#define ILL_ILLOPC_ pushpop(1)
#define ILL_PRVOPC_ pushpop(5)
#define SEGV_MAPERR_ pushpop(1)
#define SEGV_ACCERR_ pushpop(2)
#define SI_USER_ pushpop(0)
#define FPE_FLTDIV_ pushpop(3)
#define FPE_FLTOVF_ pushpop(4)
#define FPE_INTOVF_ pushpop(2)
#define FPE_FLTUND_ pushpop(5)
#define FPE_FLTRES_ pushpop(6)
#define FPE_FLTINV_ pushpop(7)
#define SI_KERNEL_ 0x80
textwindows int __sig_crash_sig(struct NtExceptionPointers *ep, int *code) {
switch (ep->ExceptionRecord->ExceptionCode) {
case kNtSignalBreakpoint:
*code = TRAP_BRKPT_;
return SIGTRAP_;
case kNtSignalIllegalInstruction:
*code = ILL_ILLOPC_;
return SIGILL_;
case kNtSignalPrivInstruction:
*code = ILL_PRVOPC_;
return SIGILL_;
case kNtSignalInPageError:
case kNtStatusStackOverflow:
*code = SEGV_MAPERR_;
return SIGSEGV_;
case kNtSignalGuardPage:
case kNtSignalAccessViolation:
*code = SEGV_ACCERR_;
return SIGSEGV_;
case kNtSignalInvalidHandle:
case kNtSignalInvalidParameter:
case kNtSignalAssertionFailure:
*code = SI_USER_;
return SIGABRT_;
case kNtStatusIntegerOverflow:
*code = FPE_INTOVF_;
return SIGFPE_;
case kNtSignalFltDivideByZero:
*code = FPE_FLTDIV_;
return SIGFPE_;
case kNtSignalFltOverflow:
*code = FPE_FLTOVF_;
return SIGFPE_;
case kNtSignalFltUnderflow:
*code = FPE_FLTUND_;
return SIGFPE_;
case kNtSignalFltInexactResult:
*code = FPE_FLTRES_;
return SIGFPE_;
case kNtSignalFltDenormalOperand:
case kNtSignalFltInvalidOperation:
case kNtSignalFltStackCheck:
case kNtSignalIntegerDivideByZero:
case kNtSignalFloatMultipleFaults:
case kNtSignalFloatMultipleTraps:
*code = FPE_FLTINV_;
return SIGFPE_;
case kNtSignalDllNotFound:
case kNtSignalOrdinalNotFound:
case kNtSignalEntrypointNotFound:
case kNtSignalDllInitFailed:
*code = SI_KERNEL_;
return SIGSYS_;
default:
*code = ep->ExceptionRecord->ExceptionCode;
return SIGSEGV_;
}
}
+1 -1
View File
@@ -31,7 +31,7 @@
#ifdef __x86_64__
privileged void __sigenter_wsl(int sig, struct siginfo *info, ucontext_t *ctx) {
privileged void __sigenter_wsl(int sig, siginfo_t *info, ucontext_t *ctx) {
int rva, flags;
rva = __sighandrvas[sig];
if (rva >= kSigactionMinRva) {
Loaded 100 of 3172 files, more files were not shown because too many files have changed in this diff. Show more