mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 01:58:20 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3093f0e467 | ||
|
|
3609f65de3 | ||
|
|
9906f299bb | ||
|
|
1d8f37a2f0 | ||
|
|
e677460d14 | ||
|
|
4937843f70 | ||
|
|
b003888696 | ||
|
|
2ca491dc56 | ||
|
|
9aa353d88b | ||
|
|
c67faf61df | ||
|
|
165c6b37e2 | ||
|
|
dcd626edf8 | ||
|
|
f032b5570b | ||
|
|
ea081b262c | ||
|
|
fae1c32267 | ||
|
|
9b6718ac99 | ||
|
|
cd672e251f | ||
|
|
500a47bc2f | ||
|
|
e4d25d68e4 | ||
|
|
f31a98d50a | ||
|
|
2816df59b2 | ||
|
|
a05ce3ad9d | ||
|
|
7c8df05042 | ||
|
|
4c77acdfcf | ||
|
|
b74b974cfd | ||
|
|
07cef612c3 | ||
|
|
deaef81463 | ||
|
|
c638eabfe0 | ||
|
|
8e68384e15 | ||
|
|
2f4ca71f26 | ||
|
|
07004ebf04 | ||
|
|
086d7006da | ||
|
|
0a51241f7a | ||
|
|
c68f6599e5 | ||
|
|
af3f62a71a |
No files matched your search
@@ -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
|
||||
Vendored
-108
@@ -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
|
||||
}
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
#define __VSCODE_INTELLISENSE__ 1
|
||||
#include "libc/integral/normalize.inc"
|
||||
@@ -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
|
||||
@@ -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,6 +256,7 @@ 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 # │
|
||||
@@ -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
|
||||
@@ -452,6 +454,7 @@ COSMOPOLITAN_OBJECTS = \
|
||||
LIBC_THREAD \
|
||||
LIBC_PROC \
|
||||
THIRD_PARTY_NSYNC_MEM \
|
||||
CTL \
|
||||
LIBC_MEM \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
LIBC_DLOPEN \
|
||||
@@ -520,6 +523,7 @@ COSMOPOLITAN_H_PKGS = \
|
||||
|
||||
COSMOCC_PKGS = \
|
||||
$(COSMOPOLITAN_H_PKGS) \
|
||||
CTL \
|
||||
THIRD_PARTY_AARCH64 \
|
||||
THIRD_PARTY_LIBCXX \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
@@ -542,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 \
|
||||
@@ -572,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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -715,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
|
||||
|
||||
+15
-26
@@ -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_ */
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+11
-11
@@ -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
|
||||
|
||||
@@ -60,6 +60,7 @@ TMPSAFE = $(TMPDIR)/
|
||||
endif
|
||||
|
||||
BACKTRACES = \
|
||||
-fno-schedule-insns2 \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
@@ -144,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 \
|
||||
@@ -256,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
@@ -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
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
BasedOnStyle: Mozilla
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 80
|
||||
---
|
||||
Language: Cpp
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AlignTrailingComments: false
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
FixNamespaceComments: true
|
||||
---
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+129
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
+2
-1
@@ -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
@@ -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 {
|
||||
|
||||
+6
-2
@@ -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");
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -91,6 +91,7 @@ EXAMPLES_DIRECTDEPS = \
|
||||
THIRD_PARTY_TZ \
|
||||
THIRD_PARTY_VQSORT \
|
||||
THIRD_PARTY_XED \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
THIRD_PARTY_ZLIB \
|
||||
TOOL_ARGS \
|
||||
TOOL_BUILD_LIB \
|
||||
|
||||
+11
-8
@@ -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);
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
@@ -42,6 +42,7 @@ EXAMPLES_PACKAGE_OBJS = \
|
||||
EXAMPLES_PACKAGE_DIRECTDEPS = \
|
||||
EXAMPLES_PACKAGE_LIB \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_STDIO \
|
||||
LIBC_TINYMATH
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
+16
-11
@@ -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
@@ -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
-90
@@ -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))
|
||||
|
||||
@@ -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 $<
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
+5
-14
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -177,9 +177,9 @@ static textwindows int ntspawn2(struct NtSpawnArgs *a, struct SpawnBlock *sb) {
|
||||
if (ok) {
|
||||
struct NtStartupInfoEx info = {
|
||||
.StartupInfo = *a->lpStartupInfo,
|
||||
.StartupInfo.cb = sizeof(info),
|
||||
.lpAttributeList = alist,
|
||||
};
|
||||
info.StartupInfo.cb = sizeof(info);
|
||||
if (ok) {
|
||||
if (CreateProcess(sb->path, sb->cmdline, 0, 0, true,
|
||||
a->dwCreationFlags | kNtCreateUnicodeEnvironment |
|
||||
|
||||
@@ -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__
|
||||
|
||||
|
||||
+6
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
+27
-75
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -421,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
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -43,7 +43,7 @@ privileged void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
|
||||
CheckLargeStackAllocation(&uc, sizeof(uc));
|
||||
#pragma GCC pop_options
|
||||
int rva, flags;
|
||||
struct siginfo si2;
|
||||
siginfo_t si2;
|
||||
rva = __sighandrvas[sig];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
flags = __sighandflags[sig];
|
||||
|
||||
@@ -41,7 +41,7 @@ privileged void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
|
||||
#pragma GCC diagnostic ignored "-Wframe-larger-than="
|
||||
struct Goodies {
|
||||
ucontext_t uc;
|
||||
struct siginfo si;
|
||||
siginfo_t si;
|
||||
} g;
|
||||
CheckLargeStackAllocation(&g, sizeof(g));
|
||||
#pragma GCC pop_options
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
privileged void __siginfo2cosmo(struct siginfo *si,
|
||||
const union siginfo_meta *m) {
|
||||
privileged void __siginfo2cosmo(siginfo_t *si, const union siginfo_meta *m) {
|
||||
void *si_addr;
|
||||
int32_t si_signo;
|
||||
int32_t si_errno;
|
||||
@@ -93,7 +92,7 @@ privileged void __siginfo2cosmo(struct siginfo *si,
|
||||
}
|
||||
}
|
||||
|
||||
*si = (struct siginfo){0};
|
||||
*si = (siginfo_t){0};
|
||||
si->si_signo = si_signo;
|
||||
si->si_errno = si_errno;
|
||||
si->si_code = si_code;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
typedef void (*sigaction_f)(int, struct siginfo *, void *);
|
||||
typedef void (*sigaction_f)(int, siginfo_t *, void *);
|
||||
|
||||
struct sigaction {
|
||||
union {
|
||||
|
||||
@@ -60,11 +60,11 @@ union metasigaction {
|
||||
struct sigaction_xnu_out xnu_out;
|
||||
};
|
||||
|
||||
void __sigenter_xnu(int, struct siginfo *, void *);
|
||||
void __sigenter_wsl(int, struct siginfo *, void *);
|
||||
void __sigenter_netbsd(int, struct siginfo *, void *);
|
||||
void __sigenter_freebsd(int, struct siginfo *, void *);
|
||||
void __sigenter_openbsd(int, struct siginfo *, void *);
|
||||
void __sigenter_xnu(int, siginfo_t *, void *);
|
||||
void __sigenter_wsl(int, siginfo_t *, void *);
|
||||
void __sigenter_netbsd(int, siginfo_t *, void *);
|
||||
void __sigenter_freebsd(int, siginfo_t *, void *);
|
||||
void __sigenter_openbsd(int, siginfo_t *, void *);
|
||||
|
||||
const char *DescribeSigaction(char[256], int, const struct sigaction *);
|
||||
#define DescribeSigaction(rc, sa) DescribeSigaction(alloca(256), rc, sa)
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
union siginfo_meta {
|
||||
struct siginfo linux;
|
||||
siginfo_t linux;
|
||||
struct siginfo_xnu xnu;
|
||||
struct siginfo_freebsd freebsd;
|
||||
struct siginfo_openbsd openbsd;
|
||||
struct siginfo_netbsd netbsd;
|
||||
};
|
||||
|
||||
void __siginfo2cosmo(struct siginfo *, const union siginfo_meta *);
|
||||
void __siginfo2cosmo(siginfo_t *, const union siginfo_meta *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_META_INTERNAL_H_ */
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/version.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/baud.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
@@ -96,9 +95,7 @@ textwindows int tcsetattr_nt(int fd, int opt, const struct termios *tio) {
|
||||
if (!(tio->c_oflag & ONLCR)) {
|
||||
outmode |= kNtDisableNewlineAutoReturn;
|
||||
}
|
||||
if (IsAtLeastWindows10()) {
|
||||
outmode |= kNtEnableVirtualTerminalProcessing;
|
||||
}
|
||||
outmode |= kNtEnableVirtualTerminalProcessing;
|
||||
|
||||
// tune the win32 configuration
|
||||
unassert(SetConsoleMode(hInput, inmode));
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
|
||||
/**
|
||||
* Returns name of terminal.
|
||||
|
||||
+6
-28
@@ -30,7 +30,6 @@
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/computernameformat.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/nt/systeminfo.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
@@ -81,34 +80,13 @@ static textwindows void GetNtName(char *name, int kind) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline textwindows int GetNtMajorVersion(void) {
|
||||
#ifdef __x86_64__
|
||||
return NtGetPeb()->OSMajorVersion;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline textwindows int GetNtMinorVersion(void) {
|
||||
#ifdef __x86_64__
|
||||
return NtGetPeb()->OSMinorVersion;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline textwindows int GetNtBuildNumber(void) {
|
||||
#ifdef __x86_64__
|
||||
return NtGetPeb()->OSBuildNumber;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static textwindows void GetNtVersion(char *p) {
|
||||
p = FormatUint32(p, GetNtMajorVersion()), *p++ = '.';
|
||||
p = FormatUint32(p, GetNtMinorVersion()), *p++ = '-';
|
||||
p = FormatUint32(p, GetNtBuildNumber());
|
||||
// We could ask GetVersionExW() for this information, but it'll simply
|
||||
// report what we put in the MajorOperatingSystemVersion of the PE ape
|
||||
// header fields. Windows doesn't want us detecting versions it seems.
|
||||
// Chances are they bake all old versions of Windows into Windows, and
|
||||
// run us on the intended one, like some kind of Docker container. Heh
|
||||
strcpy(p, "10.0");
|
||||
}
|
||||
|
||||
static const char *Str(int rc, const char *s) {
|
||||
|
||||
@@ -26,9 +26,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/s.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Deletes inode and maybe the file too.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
@@ -39,6 +40,7 @@
|
||||
*
|
||||
* @param fd is open file descriptor
|
||||
* @param buf is copied from, cf. copy_file_range(), sendfile(), etc.
|
||||
* @param size is always saturated to 0x7ffff000 automatically
|
||||
* @return [1..size] bytes on success, or -1 w/ errno; noting zero is
|
||||
* impossible unless size was passed as zero to do an error check
|
||||
* @raise EBADF if `fd` is negative or not an open file descriptor
|
||||
@@ -68,6 +70,10 @@ ssize_t write(int fd, const 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 (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
|
||||
+69
-25
@@ -27,8 +27,71 @@
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/stdckdint.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/vga/vga.internal.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 writev_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();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)
|
||||
return ebadf(); // posix specifies this when not open()'d for writing
|
||||
|
||||
// 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 (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
if (iovlen == 1) {
|
||||
return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
|
||||
} else {
|
||||
return sys_writev(fd, iov, iovlen);
|
||||
}
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_writev_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else if (IsWindows()) {
|
||||
return sys_writev_nt(fd, iov, iovlen);
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data from multiple buffers.
|
||||
@@ -45,6 +108,11 @@
|
||||
* been committed. It can also happen if we need to polyfill this system
|
||||
* call using write().
|
||||
*
|
||||
* 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 handed off, or -1 w/ errno
|
||||
* @cancelationpoint
|
||||
* @restartable
|
||||
@@ -52,31 +120,7 @@
|
||||
ssize_t writev(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 = ebadf(); // posix specifies this when not open()'d for writing
|
||||
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
if (iovlen == 1) {
|
||||
rc = sys_write(fd, iov[0].iov_base, iov[0].iov_len);
|
||||
} else {
|
||||
rc = sys_writev(fd, iov, iovlen);
|
||||
}
|
||||
} else if (fd >= g_fds.n) {
|
||||
rc = ebadf();
|
||||
} else if (IsMetal()) {
|
||||
rc = sys_writev_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_writev_nt(fd, iov, iovlen);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
|
||||
rc = writev_impl(fd, iov, iovlen);
|
||||
END_CANCELATION_POINT;
|
||||
STRACE("writev(%d, %s, %d) → %'ld% m", fd,
|
||||
DescribeIovec(rc != -1 ? rc : -2, iov, iovlen), iovlen, rc);
|
||||
|
||||
+5
-5
@@ -2,12 +2,12 @@
|
||||
#define COSMOPOLITAN_LIBC_COSMO_H_
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
errno_t cosmo_once(_Atomic(uint32_t) *, void (*)(void));
|
||||
errno_t cosmo_once(_Atomic(unsigned) *, void (*)(void)) libcesque;
|
||||
int systemvpe(const char *, char *const[], char *const[]) libcesque;
|
||||
char *GetProgramExecutableName(void);
|
||||
void unleaf(void);
|
||||
int __demangle(char *, const char *, size_t);
|
||||
int __is_mangled(const char *);
|
||||
char *GetProgramExecutableName(void) libcesque;
|
||||
void unleaf(void) libcesque;
|
||||
int __demangle(char *, const char *, size_t) libcesque;
|
||||
int __is_mangled(const char *) libcesque;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_COSMO_H_ */
|
||||
@@ -54,6 +54,8 @@ $(LIBC_DLOPEN_A_OBJS): private \
|
||||
o/$(MODE)/libc/dlopen/foreign_tramp.o: libc/dlopen/foreign_tramp.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
$(LIBC_DLOPEN_A_OBJS): private COPTS += -fno-sanitize=address
|
||||
|
||||
LIBC_DLOPEN_LIBS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x)))
|
||||
LIBC_DLOPEN_SRCS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_DLOPEN_HDRS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x)_HDRS))
|
||||
|
||||
+19
-10
@@ -5,9 +5,9 @@
|
||||
#include "libc/elf/struct/phdr.h"
|
||||
#include "libc/elf/struct/shdr.h"
|
||||
#include "libc/elf/struct/sym.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/serialize.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define GetStr(tab, rva) ((char *)(tab) + (rva))
|
||||
@@ -30,7 +30,8 @@ static inline char *GetStrtab(const Elf64_Ehdr *e, size_t *n) {
|
||||
if (shdr->sh_type == SHT_STRTAB) {
|
||||
name = GetSectionName(e, GetShdr(e, i));
|
||||
if (name && READ64LE(name) == READ64LE(".strtab")) {
|
||||
if (n) *n = shdr->sh_size;
|
||||
if (n)
|
||||
*n = shdr->sh_size;
|
||||
return GetSection(e, shdr);
|
||||
}
|
||||
}
|
||||
@@ -44,7 +45,8 @@ static inline Elf64_Sym *GetSymtab(const Elf64_Ehdr *e, Elf64_Xword *n) {
|
||||
for (i = e->e_shnum; i-- > 0;) {
|
||||
shdr = GetShdr(e, i);
|
||||
if (shdr->sh_type == SHT_SYMTAB) {
|
||||
if (n) *n = shdr->sh_size / sizeof(Elf64_Sym);
|
||||
if (n)
|
||||
*n = shdr->sh_size / sizeof(Elf64_Sym);
|
||||
return GetSection(e, shdr);
|
||||
}
|
||||
}
|
||||
@@ -60,14 +62,19 @@ static inline void GetImageRange(const Elf64_Ehdr *elf, intptr_t *x,
|
||||
end = 0;
|
||||
for (i = 0; i < elf->e_phnum; ++i) {
|
||||
phdr = GetPhdr(elf, i);
|
||||
if (phdr->p_type != PT_LOAD) continue;
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
continue;
|
||||
pstart = phdr->p_vaddr;
|
||||
pend = phdr->p_vaddr + phdr->p_memsz;
|
||||
if (pstart < start) start = pstart;
|
||||
if (pend > end) end = pend;
|
||||
if (pstart < start)
|
||||
start = pstart;
|
||||
if (pend > end)
|
||||
end = pend;
|
||||
}
|
||||
if (x) *x = start;
|
||||
if (y) *y = end;
|
||||
if (x)
|
||||
*x = start;
|
||||
if (y)
|
||||
*y = end;
|
||||
}
|
||||
|
||||
static inline bool GetElfSymbolValue(const Elf64_Ehdr *ehdr, const char *name,
|
||||
@@ -75,8 +82,10 @@ static inline bool GetElfSymbolValue(const Elf64_Ehdr *ehdr, const char *name,
|
||||
Elf64_Xword i, n;
|
||||
const char *stab;
|
||||
const Elf64_Sym *st;
|
||||
if (!(stab = GetStrtab(ehdr, 0))) return false;
|
||||
if (!(st = GetSymtab(ehdr, &n))) return false;
|
||||
if (!(stab = GetStrtab(ehdr, 0)))
|
||||
return false;
|
||||
if (!(st = GetSymtab(ehdr, &n)))
|
||||
return false;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (!__strcmp(GetStr(stab, st[i].st_name), name)) {
|
||||
*res = st[i].st_value;
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ COSMOPOLITAN_C_START_
|
||||
#define errno \
|
||||
(*__extension__({ \
|
||||
errno_t *__ep; \
|
||||
__asm__("sub\t%0,x28,#192-0x3c" : "=r"(__ep)); \
|
||||
__asm__("sub\t%0,x28,#512-0x3c" : "=r"(__ep)); \
|
||||
__ep; \
|
||||
}))
|
||||
#else
|
||||
|
||||
+2
-1
@@ -55,7 +55,8 @@ $(LIBC_FMT_A).pkg: \
|
||||
|
||||
$(LIBC_FMT_A_OBJS): private \
|
||||
CFLAGS += \
|
||||
-fno-jump-tables
|
||||
-fno-jump-tables \
|
||||
-fno-sanitize=address
|
||||
|
||||
o/$(MODE)/libc/fmt/formatint64.o \
|
||||
o/$(MODE)/libc/fmt/formatint64thousands.o \
|
||||
|
||||
+9
-6
@@ -3,13 +3,16 @@
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define CONSUME_SPACES(t, s, c) \
|
||||
if (endptr) *endptr = (t *)(s); \
|
||||
while (c == ' ' || c == '\t') c = *++s
|
||||
#define CONSUME_SPACES(t, s, c) \
|
||||
if (endptr) \
|
||||
*endptr = (t *)(s); \
|
||||
while (c == ' ' || c == '\t') \
|
||||
c = *++s
|
||||
|
||||
#define GET_SIGN(s, c, d) \
|
||||
d = c == '-' ? -1 : 1; \
|
||||
if (c == '-' || c == '+') c = *++s
|
||||
#define GET_SIGN(s, c, d) \
|
||||
d = c == '-' ? -1 : 1; \
|
||||
if (c == '-' || c == '+') \
|
||||
c = *++s
|
||||
|
||||
#define GET_RADIX(s, c, r) \
|
||||
if (!r) { \
|
||||
|
||||
+18
-11
@@ -66,14 +66,15 @@
|
||||
#endif
|
||||
|
||||
#if (!defined(__llvm__) && !__has_builtin(__builtin_assume))
|
||||
#define __builtin_assume(x) \
|
||||
do { \
|
||||
if (!(x)) __builtin_unreachable(); \
|
||||
#define __builtin_assume(x) \
|
||||
do { \
|
||||
if (!(x)) \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ + 0 < 201112
|
||||
#define _Atomic(TYPE) TYPE volatile
|
||||
#define _Atomic(t) volatile t *
|
||||
#endif
|
||||
|
||||
#ifdef __llvm__
|
||||
@@ -106,8 +107,6 @@ typedef __CHAR32_TYPE__ char32_t;
|
||||
#include "libc/stdbool.h"
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_STDINT_H
|
||||
|
||||
typedef int errno_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ssize_t;
|
||||
@@ -540,16 +539,13 @@ typedef struct {
|
||||
#ifdef __x86_64__
|
||||
#define notpossible \
|
||||
do { \
|
||||
__asm__("nop\n\t" \
|
||||
"ud2\n\t" \
|
||||
"nop"); \
|
||||
__asm__("ud2"); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#elif defined(__aarch64__)
|
||||
#define notpossible \
|
||||
do { \
|
||||
__asm__("udf\t#0\n\t" \
|
||||
"nop"); \
|
||||
__asm__("udf\t#0"); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#else
|
||||
@@ -598,10 +594,21 @@ typedef struct {
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define DebugBreak() __asm__("int3")
|
||||
#elif defined(__aarch64__)
|
||||
#define DebugBreak() __asm__("brk\t#0x666")
|
||||
#else
|
||||
#define DebugBreak() __builtin_trap()
|
||||
#endif
|
||||
|
||||
#ifdef __aarch64__
|
||||
/* raise sigill (not sigtrap) like x86 does */
|
||||
#define __builtin_trap() \
|
||||
do { \
|
||||
__asm__("udf\t#0x666"); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* _COSMO_SOURCE */
|
||||
|
||||
#define __veil(CONSTRAINT, EXPRESSION) \
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#endif
|
||||
|
||||
#define __COSMOPOLITAN_MAJOR__ 3
|
||||
#define __COSMOPOLITAN_MINOR__ 3
|
||||
#define __COSMOPOLITAN_PATCH__ 9
|
||||
#define __COSMOPOLITAN_MINOR__ 4
|
||||
#define __COSMOPOLITAN_PATCH__ 0
|
||||
#define __COSMOPOLITAN__ \
|
||||
(100000000 * __COSMOPOLITAN_MAJOR__ + 1000000 * __COSMOPOLITAN_MINOR__ + \
|
||||
__COSMOPOLITAN_PATCH__)
|
||||
|
||||
@@ -86,13 +86,6 @@ o//libc/intrin/memmove.o: private \
|
||||
-finline \
|
||||
-foptimize-sibling-calls
|
||||
|
||||
# make asan stack traces shorter
|
||||
o/$(MODE)/libc/intrin/asanthunk.o: private \
|
||||
CFLAGS += \
|
||||
-Os \
|
||||
$(NO_MAGIC) \
|
||||
-foptimize-sibling-calls
|
||||
|
||||
o/$(MODE)/libc/intrin/bzero.o \
|
||||
o/$(MODE)/libc/intrin/memcmp.o \
|
||||
o/$(MODE)/libc/intrin/memmove.o: private \
|
||||
|
||||
+10
-406
@@ -35,11 +35,9 @@
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/hook.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/gc.internal.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
@@ -57,25 +55,10 @@
|
||||
#include "libc/thread/tls.h"
|
||||
#include "third_party/dlmalloc/dlmalloc.h"
|
||||
#ifdef __x86_64__
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
|
||||
__static_yoink("_init_asan");
|
||||
|
||||
#if IsModeDbg()
|
||||
// MODE=dbg
|
||||
// O(32mb) of morgue memory
|
||||
// Θ(64) bytes of malloc overhead
|
||||
#define ASAN_MORGUE_ITEMS 512
|
||||
#define ASAN_MORGUE_THRESHOLD 65536
|
||||
#define ASAN_TRACE_ITEMS 16
|
||||
#else
|
||||
// MODE=asan
|
||||
// O(32mb) of morgue memory
|
||||
// Θ(32) bytes of malloc overhead
|
||||
#define ASAN_MORGUE_ITEMS 512
|
||||
#define ASAN_MORGUE_THRESHOLD 65536
|
||||
#define ASAN_TRACE_ITEMS 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Address Sanitizer Runtime.
|
||||
*
|
||||
@@ -111,13 +94,6 @@ __static_yoink("_init_asan");
|
||||
|
||||
#define ASAN_LOG(...) (void)0 // kprintf(__VA_ARGS__)
|
||||
|
||||
#define HOOK(HOOK, IMPL) \
|
||||
do { \
|
||||
if (_weaken(HOOK)) { \
|
||||
*_weaken(HOOK) = IMPL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define REQUIRE(FUNC) \
|
||||
do { \
|
||||
if (!_weaken(FUNC)) { \
|
||||
@@ -125,15 +101,6 @@ __static_yoink("_init_asan");
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct AsanTrace {
|
||||
uint32_t p[ASAN_TRACE_ITEMS]; // assumes linkage into 32-bit space
|
||||
};
|
||||
|
||||
struct AsanExtra {
|
||||
uint64_t size;
|
||||
struct AsanTrace bt;
|
||||
};
|
||||
|
||||
struct AsanSourceLocation {
|
||||
char *filename;
|
||||
int line;
|
||||
@@ -159,16 +126,6 @@ struct AsanGlobal {
|
||||
char *odr_indicator;
|
||||
};
|
||||
|
||||
struct ReportOriginHeap {
|
||||
const unsigned char *a;
|
||||
int z;
|
||||
};
|
||||
|
||||
static struct AsanMorgue {
|
||||
_Atomic(unsigned) i;
|
||||
_Atomic(void *) p[ASAN_MORGUE_ITEMS];
|
||||
} __asan_morgue;
|
||||
|
||||
int __asan_option_detect_stack_use_after_return = 0;
|
||||
|
||||
void __asan_version_mismatch_check_v8(void) {
|
||||
@@ -181,26 +138,11 @@ static bool __asan_once(void) {
|
||||
&once, &want, true, memory_order_relaxed, memory_order_relaxed);
|
||||
}
|
||||
|
||||
#define __asan_unreachable() \
|
||||
do { \
|
||||
kprintf("%s:%d: __asan_unreachable()\n", __FILE__, __LINE__); \
|
||||
__builtin_trap(); \
|
||||
} while (0)
|
||||
|
||||
static int __asan_bsf(uint64_t x) {
|
||||
_Static_assert(sizeof(long long) == sizeof(uint64_t), "");
|
||||
return __builtin_ctzll(x);
|
||||
}
|
||||
|
||||
static int __asan_bsr(uint64_t x) {
|
||||
_Static_assert(sizeof(long long) == sizeof(uint64_t), "");
|
||||
return __builtin_clzll(x) ^ 63;
|
||||
}
|
||||
|
||||
static uint64_t __asan_roundup2pow(uint64_t x) {
|
||||
return 2ull << __asan_bsr(x - 1);
|
||||
}
|
||||
|
||||
static char *__asan_utf8cpy(char *p, unsigned c) {
|
||||
uint64_t z;
|
||||
z = tpenc(c);
|
||||
@@ -357,7 +299,7 @@ static void __asan_exit(void) {
|
||||
_Exit(99);
|
||||
}
|
||||
|
||||
static __wur __asan_die_f *__asan_die(void) {
|
||||
__wur __asan_die_f *__asan_die(void) {
|
||||
if (_weaken(__die)) {
|
||||
return _weaken(__die);
|
||||
} else {
|
||||
@@ -411,7 +353,7 @@ void __asan_unpoison(void *p, long n) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool __asan_is_mapped(int x) {
|
||||
bool __asan_is_mapped(int x) {
|
||||
// xxx: we can't lock because no reentrant locks yet
|
||||
int i;
|
||||
bool res;
|
||||
@@ -725,12 +667,6 @@ static const char *__asan_describe_access_poison(signed char kind) {
|
||||
}
|
||||
}
|
||||
|
||||
static __wur __asan_die_f *__asan_report_invalid_pointer(const void *addr) {
|
||||
kprintf("\n\e[J\e[1;31masan error\e[0m: this corruption at %p shadow %p\n",
|
||||
addr, SHADOW(addr));
|
||||
return __asan_die();
|
||||
}
|
||||
|
||||
static char *__asan_format_interval(char *p, intptr_t a, intptr_t b) {
|
||||
p = __asan_hexcpy(p, a, 48), *p++ = '-';
|
||||
p = __asan_hexcpy(p, b, 48);
|
||||
@@ -751,7 +687,7 @@ static char *__asan_format_section(char *p, const void *p1, const void *p2,
|
||||
return p;
|
||||
}
|
||||
|
||||
static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
||||
void __asan_report_memory_origin_image(intptr_t a, int z) {
|
||||
unsigned l, m, r, n, k;
|
||||
struct SymbolTable *st;
|
||||
kprintf("\nthe memory belongs to image symbols\n");
|
||||
@@ -788,32 +724,8 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
||||
}
|
||||
}
|
||||
|
||||
static void __asan_onmemory(void *x, void *y, size_t n, void *a) {
|
||||
const unsigned char *p = x;
|
||||
struct ReportOriginHeap *t = a;
|
||||
if ((p <= t->a && t->a < p + n) ||
|
||||
(p <= t->a + t->z && t->a + t->z < p + n) ||
|
||||
(t->a < p && p + n <= t->a + t->z)) {
|
||||
kprintf("%p %,lu bytes [dlmalloc]", x, n);
|
||||
__asan_print_trace(x);
|
||||
kprintf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void __asan_report_memory_origin_heap(const unsigned char *a, int z) {
|
||||
struct ReportOriginHeap t;
|
||||
kprintf("\nthe memory was allocated by\n");
|
||||
if (_weaken(malloc_inspect_all)) {
|
||||
t.a = a;
|
||||
t.z = z;
|
||||
_weaken(malloc_inspect_all)(__asan_onmemory, &t);
|
||||
} else {
|
||||
kprintf("\tunknown please __static_yoink(\"malloc_inspect_all\");\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void __asan_report_memory_origin(const unsigned char *addr, int size,
|
||||
signed char kind) {
|
||||
void __asan_report_memory_origin(const unsigned char *addr, int size,
|
||||
signed char kind) {
|
||||
switch (kind) {
|
||||
case kAsanStackOverrun:
|
||||
case kAsanGlobalOverrun:
|
||||
@@ -838,7 +750,8 @@ static void __asan_report_memory_origin(const unsigned char *addr, int size,
|
||||
if (__executable_start <= addr && addr < _end) {
|
||||
__asan_report_memory_origin_image((intptr_t)addr, size);
|
||||
} else if (IsAutoFrame((intptr_t)addr >> 16)) {
|
||||
__asan_report_memory_origin_heap(addr, size);
|
||||
if (_weaken(__asan_report_memory_origin_heap))
|
||||
_weaken(__asan_report_memory_origin_heap)(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -973,49 +886,7 @@ static __wur __asan_die_f *__asan_report_memory_fault(void *addr, int size,
|
||||
__asan_fault(SHADOW(addr), -128).kind);
|
||||
}
|
||||
|
||||
static void *__asan_morgue_add(void *p) {
|
||||
return atomic_exchange_explicit(
|
||||
__asan_morgue.p + (atomic_fetch_add_explicit(&__asan_morgue.i, 1,
|
||||
memory_order_acq_rel) &
|
||||
(ARRAYLEN(__asan_morgue.p) - 1)),
|
||||
p, memory_order_acq_rel);
|
||||
}
|
||||
|
||||
__attribute__((__destructor__)) static void __asan_morgue_flush(void) {
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAYLEN(__asan_morgue.p); ++i) {
|
||||
if (atomic_load_explicit(__asan_morgue.p + i, memory_order_acquire)) {
|
||||
_weaken(dlfree)(atomic_exchange_explicit(__asan_morgue.p + i, 0,
|
||||
memory_order_release));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static size_t __asan_heap_size(size_t n) {
|
||||
if (n < 0x7fffffff0000) {
|
||||
n = ROUNDUP(n, _Alignof(struct AsanExtra));
|
||||
return __asan_roundup2pow(n + sizeof(struct AsanExtra));
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void __asan_write48(uint64_t *value, uint64_t x) {
|
||||
uint64_t cookie;
|
||||
cookie = 'J' | 'T' << 8;
|
||||
cookie ^= x & 0xffff;
|
||||
*value = (x & 0xffffffffffff) | cookie << 48;
|
||||
}
|
||||
|
||||
static bool __asan_read48(uint64_t value, uint64_t *x) {
|
||||
uint64_t cookie;
|
||||
cookie = value >> 48;
|
||||
cookie ^= value & 0xffff;
|
||||
*x = (int64_t)(value << 16) >> 16;
|
||||
return cookie == ('J' | 'T' << 8);
|
||||
}
|
||||
|
||||
static void __asan_rawtrace(struct AsanTrace *bt, const struct StackFrame *bp) {
|
||||
void __asan_rawtrace(struct AsanTrace *bt, const struct StackFrame *bp) {
|
||||
size_t i;
|
||||
for (i = 0; bp && i < ARRAYLEN(bt->p); ++i, bp = bp->next) {
|
||||
if (kisdangerous(bp))
|
||||
@@ -1059,237 +930,6 @@ static void __asan_trace(struct AsanTrace *bt, const struct StackFrame *bp) {
|
||||
}
|
||||
}
|
||||
|
||||
#define __asan_trace __asan_rawtrace
|
||||
|
||||
static void *__asan_allocate(size_t a, size_t n, struct AsanTrace *bt,
|
||||
int underrun, int overrun, int initializer) {
|
||||
char *p;
|
||||
size_t c;
|
||||
struct AsanExtra *e;
|
||||
if ((p = _weaken(dlmemalign)(a, __asan_heap_size(n)))) {
|
||||
c = _weaken(dlmalloc_usable_size)(p);
|
||||
e = (struct AsanExtra *)(p + c - sizeof(*e));
|
||||
__asan_unpoison(p, n);
|
||||
__asan_poison(p - 16, 16, underrun); /* see dlmalloc design */
|
||||
__asan_poison(p + n, c - n, overrun);
|
||||
__asan_memset(p, initializer, n);
|
||||
__asan_write48(&e->size, n);
|
||||
__asan_memcpy(&e->bt, bt, sizeof(*bt));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static void *__asan_allocate_heap(size_t a, size_t n, struct AsanTrace *bt) {
|
||||
return __asan_allocate(a, n, bt, kAsanHeapUnderrun, kAsanHeapOverrun, 0xf9);
|
||||
}
|
||||
|
||||
static struct AsanExtra *__asan_get_extra(const void *p, size_t *c) {
|
||||
int f;
|
||||
long x, n;
|
||||
struct AsanExtra *e;
|
||||
f = (intptr_t)p >> 16;
|
||||
if (!kisdangerous(p) &&
|
||||
(n = _weaken(dlmalloc_usable_size)((void *)p)) > sizeof(*e) &&
|
||||
!ckd_add(&x, (intptr_t)p, n) && x <= 0x800000000000 &&
|
||||
(LIKELY(f == (int)((x - 1) >> 16)) || !kisdangerous((void *)(x - 1))) &&
|
||||
(LIKELY(f == (int)((x = x - sizeof(*e)) >> 16)) ||
|
||||
__asan_is_mapped(x >> 16)) &&
|
||||
!(x & (_Alignof(struct AsanExtra) - 1))) {
|
||||
*c = n;
|
||||
return (struct AsanExtra *)x;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t __asan_get_heap_size(const void *p) {
|
||||
size_t n, c;
|
||||
struct AsanExtra *e;
|
||||
if ((e = __asan_get_extra(p, &c)) && __asan_read48(e->size, &n)) {
|
||||
return n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t __asan_malloc_usable_size(void *p) {
|
||||
size_t n, c;
|
||||
struct AsanExtra *e;
|
||||
if ((e = __asan_get_extra(p, &c)) && __asan_read48(e->size, &n)) {
|
||||
return n;
|
||||
}
|
||||
__asan_report_invalid_pointer(p)();
|
||||
__asan_unreachable();
|
||||
}
|
||||
|
||||
int __asan_print_trace(void *p) {
|
||||
size_t c, i, n;
|
||||
struct AsanExtra *e;
|
||||
if (!(e = __asan_get_extra(p, &c))) {
|
||||
kprintf(" bad pointer");
|
||||
return einval();
|
||||
}
|
||||
if (!__asan_read48(e->size, &n)) {
|
||||
kprintf(" bad cookie");
|
||||
return -1;
|
||||
}
|
||||
kprintf("\n%p %,lu bytes [asan]", (char *)p, n);
|
||||
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16)) {
|
||||
kprintf(" (shadow not mapped?!)");
|
||||
}
|
||||
for (i = 0; i < ARRAYLEN(e->bt.p) && e->bt.p[i]; ++i) {
|
||||
kprintf("\n%*lx %s", 12, e->bt.p[i],
|
||||
_weaken(GetSymbolByAddr)
|
||||
? _weaken(GetSymbolByAddr)(e->bt.p[i])
|
||||
: "please __static_yoink(\"GetSymbolByAddr\")");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns true if `p` was allocated by an IGNORE_LEAKS(function).
|
||||
int __asan_is_leaky(void *p) {
|
||||
int sym;
|
||||
size_t c, i, n;
|
||||
intptr_t f, *l;
|
||||
struct AsanExtra *e;
|
||||
struct SymbolTable *st;
|
||||
if (!_weaken(GetSymbolTable))
|
||||
notpossible;
|
||||
if (!(e = __asan_get_extra(p, &c)))
|
||||
return 0;
|
||||
if (!__asan_read48(e->size, &n))
|
||||
return 0;
|
||||
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16))
|
||||
return 0;
|
||||
if (!(st = GetSymbolTable()))
|
||||
return 0;
|
||||
for (i = 0; i < ARRAYLEN(e->bt.p) && e->bt.p[i]; ++i) {
|
||||
if ((sym = _weaken(__get_symbol)(st, e->bt.p[i])) == -1)
|
||||
continue;
|
||||
f = st->addr_base + st->symbols[sym].x;
|
||||
for (l = _leaky_start; l < _leaky_end; ++l) {
|
||||
if (f == *l) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __asan_deallocate(char *p, long kind) {
|
||||
size_t c, n;
|
||||
struct AsanExtra *e;
|
||||
if ((e = __asan_get_extra(p, &c))) {
|
||||
if (__asan_read48(e->size, &n)) {
|
||||
__asan_poison(p, c, kind);
|
||||
if (c <= ASAN_MORGUE_THRESHOLD) {
|
||||
p = __asan_morgue_add(p);
|
||||
}
|
||||
_weaken(dlfree)(p);
|
||||
} else {
|
||||
__asan_report_invalid_pointer(p)();
|
||||
__asan_unreachable();
|
||||
}
|
||||
} else {
|
||||
__asan_report_invalid_pointer(p)();
|
||||
__asan_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
void __asan_free(void *p) {
|
||||
if (!p)
|
||||
return;
|
||||
__asan_deallocate(p, kAsanHeapFree);
|
||||
}
|
||||
|
||||
size_t __asan_bulk_free(void *p[], size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (p[i]) {
|
||||
__asan_deallocate(p[i], kAsanHeapFree);
|
||||
p[i] = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *__asan_realloc_nogrow(void *p, size_t n, size_t m,
|
||||
struct AsanTrace *bt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *__asan_realloc_grow(void *p, size_t n, size_t m,
|
||||
struct AsanTrace *bt) {
|
||||
char *q;
|
||||
if ((q = __asan_allocate_heap(16, n, bt))) {
|
||||
__asan_memcpy(q, p, m);
|
||||
__asan_deallocate(p, kAsanHeapRelocated);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
static void *__asan_realloc_impl(void *p, size_t n,
|
||||
void *grow(void *, size_t, size_t,
|
||||
struct AsanTrace *)) {
|
||||
size_t c, m;
|
||||
struct AsanExtra *e;
|
||||
if ((e = __asan_get_extra(p, &c))) {
|
||||
if (__asan_read48(e->size, &m)) {
|
||||
if (n <= m) { // shrink
|
||||
__asan_poison((char *)p + n, m - n, kAsanHeapOverrun);
|
||||
__asan_write48(&e->size, n);
|
||||
return p;
|
||||
} else if (n <= c - sizeof(struct AsanExtra)) { // small growth
|
||||
__asan_unpoison((char *)p + m, n - m);
|
||||
__asan_write48(&e->size, n);
|
||||
return p;
|
||||
} else { // exponential growth
|
||||
return grow(p, n, m, &e->bt);
|
||||
}
|
||||
}
|
||||
}
|
||||
__asan_report_invalid_pointer(p)();
|
||||
__asan_unreachable();
|
||||
}
|
||||
|
||||
void *__asan_malloc(size_t size) {
|
||||
struct AsanTrace bt;
|
||||
__asan_trace(&bt, RBP);
|
||||
return __asan_allocate_heap(16, size, &bt);
|
||||
}
|
||||
|
||||
void *__asan_memalign(size_t align, size_t size) {
|
||||
struct AsanTrace bt;
|
||||
__asan_trace(&bt, RBP);
|
||||
return __asan_allocate_heap(align, size, &bt);
|
||||
}
|
||||
|
||||
void *__asan_calloc(size_t n, size_t m) {
|
||||
struct AsanTrace bt;
|
||||
__asan_trace(&bt, RBP);
|
||||
if (ckd_mul(&n, n, m))
|
||||
n = -1;
|
||||
return __asan_allocate(16, n, &bt, kAsanHeapUnderrun, kAsanHeapOverrun, 0x00);
|
||||
}
|
||||
|
||||
void *__asan_realloc(void *p, size_t n) {
|
||||
struct AsanTrace bt;
|
||||
if (p) {
|
||||
return __asan_realloc_impl(p, n, __asan_realloc_grow);
|
||||
} else {
|
||||
__asan_trace(&bt, RBP);
|
||||
return __asan_allocate_heap(16, n, &bt);
|
||||
}
|
||||
}
|
||||
|
||||
void *__asan_realloc_in_place(void *p, size_t n) {
|
||||
return p ? __asan_realloc_impl(p, n, __asan_realloc_nogrow) : 0;
|
||||
}
|
||||
|
||||
int __asan_malloc_trim(size_t pad) {
|
||||
__asan_morgue_flush();
|
||||
return _weaken(dlmalloc_trim) ? _weaken(dlmalloc_trim)(pad) : 0;
|
||||
}
|
||||
|
||||
void __asan_register_globals(struct AsanGlobal g[], int n) {
|
||||
int i;
|
||||
__asan_poison(g, sizeof(*g) * n, kAsanProtected);
|
||||
@@ -1332,19 +972,6 @@ void __asan_report_store(uint8_t *addr, int size) {
|
||||
__asan_unreachable();
|
||||
}
|
||||
|
||||
void *__asan_stack_malloc(size_t size, int classid) {
|
||||
struct AsanTrace bt;
|
||||
ASAN_LOG("__asan_stack_malloc(%zu, %d)\n", size, classid);
|
||||
__asan_trace(&bt, RBP);
|
||||
return __asan_allocate(16, size, &bt, kAsanStackUnderrun, kAsanStackOverrun,
|
||||
0xf9);
|
||||
}
|
||||
|
||||
void __asan_stack_free(char *p, size_t size, int classid) {
|
||||
ASAN_LOG("__asan_stack_free(%p, %zu, %d)\n", p, size, classid);
|
||||
__asan_deallocate(p, kAsanStackFree);
|
||||
}
|
||||
|
||||
void __asan_handle_no_return(void) {
|
||||
// this check is stupid and has far-reaching toilsome ramifications
|
||||
}
|
||||
@@ -1406,18 +1033,6 @@ void __asan_after_dynamic_init(void) {
|
||||
ASAN_LOG("__asan_after_dynamic_init()\n");
|
||||
}
|
||||
|
||||
void __asan_install_malloc_hooks(void) {
|
||||
HOOK(hook_free, __asan_free);
|
||||
HOOK(hook_malloc, __asan_malloc);
|
||||
HOOK(hook_calloc, __asan_calloc);
|
||||
HOOK(hook_realloc, __asan_realloc);
|
||||
HOOK(hook_memalign, __asan_memalign);
|
||||
HOOK(hook_bulk_free, __asan_bulk_free);
|
||||
HOOK(hook_malloc_trim, __asan_malloc_trim);
|
||||
HOOK(hook_realloc_in_place, __asan_realloc_in_place);
|
||||
HOOK(hook_malloc_usable_size, __asan_malloc_usable_size);
|
||||
}
|
||||
|
||||
void __asan_map_shadow(uintptr_t p, size_t n) {
|
||||
// assume _mmi.lock is held
|
||||
void *addr;
|
||||
@@ -1500,17 +1115,6 @@ void __asan_init(int argc, char **argv, char **envp, unsigned long *auxv) {
|
||||
static bool once;
|
||||
if (!_cmpxchg(&once, false, true))
|
||||
return;
|
||||
if (IsWindows() && NtGetVersion() < kNtVersionWindows10) {
|
||||
__write_str("error: asan binaries require windows10\r\n");
|
||||
_Exit(0); /* So `make MODE=dbg test` passes w/ Windows7 */
|
||||
}
|
||||
if (_weaken(hook_malloc) || _weaken(hook_calloc) || _weaken(hook_realloc) ||
|
||||
_weaken(hook_realloc_in_place) || _weaken(hook_free) ||
|
||||
_weaken(hook_malloc_usable_size)) {
|
||||
REQUIRE(dlfree);
|
||||
REQUIRE(dlmemalign);
|
||||
REQUIRE(dlmalloc_usable_size);
|
||||
}
|
||||
__asan_shadow_existing_mappings();
|
||||
__asan_map_shadow((uintptr_t)__executable_start, _end - __executable_start);
|
||||
__asan_map_shadow(0, 4096);
|
||||
@@ -1518,7 +1122,6 @@ void __asan_init(int argc, char **argv, char **envp, unsigned long *auxv) {
|
||||
if (!IsWindows()) {
|
||||
sys_mprotect((void *)0x7fff8000, 0x10000, PROT_READ);
|
||||
}
|
||||
__asan_install_malloc_hooks();
|
||||
STRACE(" _ ____ _ _ _ ");
|
||||
STRACE(" / \\ / ___| / \\ | \\ | |");
|
||||
STRACE(" / _ \\ \\___ \\ / _ \\ | \\| |");
|
||||
@@ -1530,4 +1133,5 @@ void __asan_init(int argc, char **argv, char **envp, unsigned long *auxv) {
|
||||
__weak_reference(__asan_poison, __asan_poison_memory_region);
|
||||
__weak_reference(__asan_unpoison, __asan_unpoison_memory_region);
|
||||
|
||||
#endif /* __SANITIZE_ADDRESS__ */
|
||||
#endif /* __x86_64__ */
|
||||
+35
-10
@@ -3,10 +3,33 @@
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#ifdef MODE_DBG
|
||||
// MODE=dbg
|
||||
// O(32mb) of morgue memory
|
||||
// Θ(64) bytes of malloc overhead
|
||||
#define ASAN_MORGUE_ITEMS 512
|
||||
#define ASAN_MORGUE_THRESHOLD 65536
|
||||
#define ASAN_TRACE_ITEMS 16
|
||||
#else
|
||||
// MODE=asan
|
||||
// O(32mb) of morgue memory
|
||||
// Θ(32) bytes of malloc overhead
|
||||
#define ASAN_MORGUE_ITEMS 512
|
||||
#define ASAN_MORGUE_THRESHOLD 65536
|
||||
#define ASAN_TRACE_ITEMS 4
|
||||
#endif
|
||||
|
||||
#define SHADOW(x) ((signed char *)(((intptr_t)(x) >> kAsanScale) + kAsanMagic))
|
||||
#define UNSHADOW(x) ((void *)(MAX(0, (intptr_t)(x)-kAsanMagic) << kAsanScale))
|
||||
#define UNSHADOW(x) ((void *)(MAX(0, (intptr_t)(x) - kAsanMagic) << kAsanScale))
|
||||
|
||||
#define __asan_unreachable() \
|
||||
do { \
|
||||
kprintf("%s:%d: __asan_unreachable()\n", __FILE__, __LINE__); \
|
||||
__builtin_trap(); \
|
||||
} while (0)
|
||||
|
||||
typedef void __asan_die_f(void);
|
||||
|
||||
@@ -15,6 +38,10 @@ struct AsanFault {
|
||||
const signed char *shadow;
|
||||
};
|
||||
|
||||
struct AsanTrace {
|
||||
uint32_t p[ASAN_TRACE_ITEMS]; // assumes linkage into 32-bit space
|
||||
};
|
||||
|
||||
void __asan_unpoison(void *, long);
|
||||
void __asan_poison(void *, long, signed char);
|
||||
void __asan_verify(const void *, size_t);
|
||||
@@ -27,19 +54,17 @@ bool __asan_is_valid_iov(const struct iovec *, int) nosideeffect;
|
||||
struct AsanFault __asan_check(const void *, long) nosideeffect;
|
||||
struct AsanFault __asan_check_str(const char *) nosideeffect;
|
||||
|
||||
void __asan_free(void *);
|
||||
void *__asan_malloc(size_t);
|
||||
bool __asan_is_mapped(int);
|
||||
int __asan_is_leaky(void *);
|
||||
int __asan_malloc_trim(size_t);
|
||||
int __asan_print_trace(void *);
|
||||
void *__asan_calloc(size_t, size_t);
|
||||
void *__asan_realloc(void *, size_t);
|
||||
void *__asan_memalign(size_t, size_t);
|
||||
size_t __asan_get_heap_size(const void *);
|
||||
void *__asan_realloc_in_place(void *, size_t);
|
||||
|
||||
__asan_die_f *__asan_die(void) __wur;
|
||||
void __asan_memset(void *, char, size_t);
|
||||
size_t __asan_get_heap_size(const void *);
|
||||
void *__asan_memcpy(void *, const void *, size_t);
|
||||
void __asan_rawtrace(struct AsanTrace *, const struct StackFrame *);
|
||||
void __asan_report_memory_origin(const unsigned char *, int, signed char);
|
||||
void __asan_report_memory_origin_image(intptr_t, int);
|
||||
void __asan_report_memory_origin_heap(const unsigned char *, int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_ASAN_H_ */
|
||||
@@ -25,6 +25,7 @@
|
||||
mov %r13,%rsi
|
||||
mov %r14,%rdx
|
||||
mov %r15,%rcx
|
||||
.weak __asan_init
|
||||
call __asan_init
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
|
||||
@@ -12,16 +12,14 @@
|
||||
* @see libc/atomic.h
|
||||
*/
|
||||
|
||||
typedef int memory_order;
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
memory_order_relaxed,
|
||||
memory_order_consume,
|
||||
memory_order_acquire,
|
||||
memory_order_release,
|
||||
memory_order_acq_rel,
|
||||
memory_order_seq_cst,
|
||||
};
|
||||
} memory_order;
|
||||
|
||||
#define ATOMIC_VAR_INIT(...) __VA_ARGS__
|
||||
#define atomic_is_lock_free(obj) ((void)(obj), sizeof(obj) <= sizeof(void *))
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -17,34 +17,66 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/describebacktrace.internal.h"
|
||||
#include "libc/intrin/iscall.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
|
||||
#define N 160
|
||||
|
||||
static bool IsDangerous(const void *ptr) {
|
||||
if (_weaken(kisdangerous))
|
||||
return _weaken(kisdangerous)(ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *FormatHex(char *p, unsigned long x) {
|
||||
int k = x ? (__builtin_clzl(x) ^ 63) + 1 : 1;
|
||||
k = (k + 3) & -4;
|
||||
while (k > 0)
|
||||
*p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||
*p = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
dontinstrument const char *(DescribeBacktrace)(char buf[N],
|
||||
struct StackFrame *fr) {
|
||||
const struct StackFrame *fr) {
|
||||
char *p = buf;
|
||||
char *pe = p + N;
|
||||
bool gotsome = false;
|
||||
while (fr) {
|
||||
if (_weaken(kisdangerous) && _weaken(kisdangerous)(fr)) {
|
||||
if (IsDangerous(fr)) {
|
||||
if (p + 1 + 1 + 1 < pe) {
|
||||
if (gotsome)
|
||||
*p++ = ' ';
|
||||
*p = '!';
|
||||
if (p + 16 + 1 < pe) {
|
||||
*p++ = ' ';
|
||||
p = FormatHex(p, (long)fr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (p + 16 + 1 + 1 <= pe) {
|
||||
if (gotsome) {
|
||||
if (p + 16 + 1 < pe) {
|
||||
unsigned char *ip = (unsigned char *)fr->addr;
|
||||
#ifdef __x86_64__
|
||||
// x86 advances the progrem counter before an instruction
|
||||
// begins executing. return addresses in backtraces shall
|
||||
// point to code after the call, which means addr2line is
|
||||
// going to print unrelated code unless we fixup the addr
|
||||
if (!IsDangerous(ip))
|
||||
ip -= __is_call(ip);
|
||||
#endif
|
||||
if (gotsome)
|
||||
*p++ = ' ';
|
||||
} else {
|
||||
else
|
||||
gotsome = true;
|
||||
}
|
||||
p = __hexcpy(p, fr->addr);
|
||||
p = FormatHex(p, (long)ip);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
fr = fr->next;
|
||||
}
|
||||
*p = 0;
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
const char *DescribeBacktrace(char[160], struct StackFrame *) libcesque;
|
||||
const char *DescribeBacktrace(char[160], const struct StackFrame *) libcesque;
|
||||
#define DescribeBacktrace(x) DescribeBacktrace(alloca(160), x)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
||||
+6
-3
@@ -33,19 +33,22 @@ static inline struct Dll *dll_last(struct Dll *list) {
|
||||
|
||||
static inline struct Dll *dll_first(struct Dll *list) {
|
||||
struct Dll *first = 0;
|
||||
if (list) first = list->next;
|
||||
if (list)
|
||||
first = list->next;
|
||||
return first;
|
||||
}
|
||||
|
||||
static inline struct Dll *dll_next(struct Dll *list, struct Dll *e) {
|
||||
struct Dll *next = 0;
|
||||
if (e != list) next = e->next;
|
||||
if (e != list)
|
||||
next = e->next;
|
||||
return next;
|
||||
}
|
||||
|
||||
static inline struct Dll *dll_prev(struct Dll *list, struct Dll *e) {
|
||||
struct Dll *prev = 0;
|
||||
if (e != list->next) prev = e->prev;
|
||||
if (e != list->next)
|
||||
prev = e->prev;
|
||||
return prev;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
#define asint(x) ((union pun){x}).i
|
||||
#define isnan(x) (((x) & 0x7fff) > 0x7c00)
|
||||
#define isnan(x) (((x)&0x7fff) > 0x7c00)
|
||||
|
||||
union pun {
|
||||
_Float16 f;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-*- 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 2023 Justine Alexandra Roberts Tunney │
|
||||
│ 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 │
|
||||
@@ -16,12 +16,22 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/nt/version.h"
|
||||
#include "libc/intrin/iscall.internal.h"
|
||||
|
||||
bool32(IsAtLeastWindows10)(void) {
|
||||
#ifdef __x86_64__
|
||||
return IsAtLeastWindows10();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
// returns true if `p` is preceded by x86 call instruction
|
||||
// this is actually impossible to do but we'll do our best
|
||||
dontinstrument int __is_call(const unsigned char *p) {
|
||||
if (p[-5] == 0xe8)
|
||||
return 5; // call Jvds
|
||||
if (p[-2] == 0xff && (p[-1] & 070) == 020)
|
||||
return 2; // call %reg
|
||||
if (p[-4] == 0xff && (p[-3] & 070) == 020)
|
||||
return 4; // call disp8(%reg,%reg)
|
||||
if (p[-3] == 0xff && (p[-2] & 070) == 020)
|
||||
return 3; // call disp8(%reg)
|
||||
if (p[-7] == 0xff && (p[-6] & 070) == 020)
|
||||
return 7; // call disp32(%reg,%reg)
|
||||
if (p[-6] == 0xff && (p[-5] & 070) == 020)
|
||||
return 6; // call disp32(%reg)
|
||||
return 0;
|
||||
}
|
||||
Loaded 100 of 2461 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user