Merge branch 'master' into fastcall-wrapup

merging with 363d2ec436
This commit is contained in:
ahgamut 2022-05-09 13:38:05 +05:30
commit 4b85809dd8
4529 changed files with 199703 additions and 268223 deletions

View file

@ -15,7 +15,7 @@
"alignas(x)",
"alignof(x)",
"artificial=",
"nodiscard=",
"dontdiscard=",
"mayalias=",
"forceinline=",
"forcealign(x)=",
@ -48,7 +48,7 @@
"nosideeffect=",
"unreachable=",
"thatispacked=",
"nothrow=",
"dontthrow=",
"nocallback=",
"relegated=",
"hidden=",

View file

@ -37,7 +37,7 @@
#
# # basic debugging
# make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
# o/dbg/examples/crashreport.com
# o/examples/crashreport.com
# less examples/crashreport.c
#
# # extremely tiny binaries
@ -60,7 +60,7 @@
# build/config.mk
SHELL = /bin/sh
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win7 win10
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win7 win10 xnu
SANITY := $(shell build/sanitycheck $$PPID)
.SUFFIXES:
@ -69,7 +69,10 @@ SANITY := $(shell build/sanitycheck $$PPID)
.PHONY: all o bins check test depend tags
all: o
o: o/$(MODE)/ape \
o: o/$(MODE)
o/$(MODE): \
o/$(MODE)/ape \
o/$(MODE)/dsp \
o/$(MODE)/net \
o/$(MODE)/libc \
@ -108,13 +111,13 @@ include libc/rand/rand.mk # │
include libc/unicode/unicode.mk # │
include third_party/dlmalloc/dlmalloc.mk #─┘
include libc/mem/mem.mk #─┐
include libc/ohmyplus/ohmyplus.mk # ├──DYNAMIC RUNTIME
include libc/zipos/zipos.mk # │ You can now use stdio
include third_party/gdtoa/gdtoa.mk # │ You can finally call malloc()
include libc/time/time.mk # │
include libc/zipos/zipos.mk # ├──DYNAMIC RUNTIME
include third_party/gdtoa/gdtoa.mk # │ You can now use stdio
include libc/time/time.mk # │ You can finally call malloc()
include libc/thread/thread.mk # │
include libc/alg/alg.mk # │
include libc/stdio/stdio.mk # │
include libc/thread/thread.mk # │
include third_party/libcxx/libcxx.mk # │
include net/net.mk # │
include libc/log/log.mk # │
include third_party/bzip2/bzip2.mk # │
@ -138,14 +141,16 @@ include third_party/third_party.mk
include libc/testlib/testlib.mk
include tool/viz/lib/vizlib.mk
include third_party/linenoise/linenoise.mk
include third_party/maxmind/maxmind.mk
include third_party/lua/lua.mk
include third_party/make/make.mk
include third_party/argon2/argon2.mk
include third_party/smallz4/smallz4.mk
include third_party/sqlite3/sqlite3.mk
include third_party/mbedtls/test/test.mk
include third_party/quickjs/quickjs.mk
include third_party/lz4cli/lz4cli.mk
include third_party/infozip/infozip.mk
include third_party/zip/zip.mk
include tool/build/lib/buildlib.mk
include third_party/chibicc/chibicc.mk
include third_party/chibicc/test/test.mk
@ -157,6 +162,11 @@ include examples/examples.mk
include examples/pyapp/pyapp.mk
include tool/decode/lib/decodelib.mk
include tool/decode/decode.mk
include tool/lambda/lib/lib.mk
include tool/lambda/lambda.mk
include tool/plinko/lib/lib.mk
include tool/plinko/plinko.mk
include test/tool/plinko/test.mk
include tool/hash/hash.mk
include tool/net/net.mk
include tool/viz/viz.mk
@ -167,6 +177,7 @@ include test/libc/intrin/test.mk
include test/libc/mem/test.mk
include test/libc/nexgen32e/test.mk
include test/libc/runtime/test.mk
include test/libc/thread/test.mk
include test/libc/sock/test.mk
include test/libc/bits/test.mk
include test/libc/str/test.mk
@ -210,7 +221,7 @@ CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
bins: $(BINS)
check: $(CHECKS)
test: $(TESTS) all
test: $(TESTS)
depend: o/$(MODE)/depend
tags: TAGS HTAGS
@ -249,7 +260,6 @@ COSMOPOLITAN_OBJECTS = \
LIBC_NT_WS2_32 \
LIBC_NT_IPHLPAPI \
LIBC_NT_MSWSOCK \
LIBC_OHMYPLUS \
LIBC_X \
THIRD_PARTY_GETOPT \
LIBC_LOG \
@ -270,7 +280,9 @@ COSMOPOLITAN_OBJECTS = \
LIBC_CALLS \
LIBC_RAND \
LIBC_SYSV_CALLS \
LIBC_NT_KERNELBASE \
LIBC_NT_PSAPI \
LIBC_NT_POWRPROF \
LIBC_NT_PDH \
LIBC_NT_SHELL32 \
LIBC_NT_GDI32 \
LIBC_NT_COMDLG32 \
@ -283,6 +295,7 @@ COSMOPOLITAN_OBJECTS = \
THIRD_PARTY_COMPILER_RT \
LIBC_THREAD \
LIBC_TINYMATH \
THIRD_PARTY_XED \
LIBC_STR \
LIBC_SYSV \
LIBC_INTRIN \
@ -302,11 +315,11 @@ COSMOPOLITAN_HEADERS = \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT \
LIBC_OHMYPLUS \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
THIRD_PARTY_XED \
LIBC_STR \
LIBC_SYSV \
LIBC_THREAD \

View file

@ -22,8 +22,8 @@ If you're doing your development work on Linux or BSD then you need just
five files to get started. Here's what you do on Linux:
```sh
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-1.0.zip
unzip cosmopolitan-amalgamation-1.0.zip
wget https://justine.lol/cosmopolitan/cosmopolitan.zip
unzip cosmopolitan.zip
printf 'main() { printf("hello world\\n"); }\n' >hello.c
gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
-fno-omit-frame-pointer -pg -mnop-mcount \
@ -72,14 +72,45 @@ repository that bootstraps using a vendored static gcc9 executable.
No further dependencies are required.
```sh
wget https://justine.lol/cosmopolitan/cosmopolitan-1.0.tar.gz
tar xf cosmopolitan-1.0.tar.gz # see releases page
wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
tar xf cosmopolitan.tar.gz # see releases page
cd cosmopolitan
make -j16
o//examples/hello.com
find o -name \*.com | xargs ls -rShal | less
```
## GDB
Here's the recommended `~/.gdbinit` config:
```
set host-charset UTF-8
set target-charset UTF-8
set target-wide-charset UTF-8
set osabi none
set complaints 0
set confirm off
set history save on
set history filename ~/.gdb_history
define asm
layout asm
layout reg
end
define src
layout src
layout reg
end
src
```
You normally run the `.com.dbg` file under gdb. If you need to debug the
`.com` file itself, then you can load the debug symbols independently as
```
gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
```
## Support Vector
| Platform | Min Version | Circa |

View file

@ -660,6 +660,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
#if SupportsSystemv() || SupportsMetal()
.section .elf.phdrs,"a",@progbits
.long PT_LOAD
.long PF_R|PF_X
.stub ape_rom_offset,quad
@ -668,6 +669,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.stub ape_rom_filesz,quad
.stub ape_rom_memsz,quad
.stub ape_rom_align,quad
.long PT_LOAD
.long PF_R|PF_W
.stub ape_ram_offset,quad
@ -676,14 +678,32 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.stub ape_ram_filesz,quad
.stub ape_ram_memsz,quad
.stub ape_ram_align,quad
// APE Stack Configuration
//
// We actually respect this when allocating a deterministically
// addressed stack on Windows and other operating systems. However
// there's a few caveats:
//
// - If ape_stack_pf has PF_X then OpenBSD probably won't work
// - We don't bother creating a deterministic stack in MODE=tiny
//
// With that said, here's some examples of configuration:
//
// STATIC_SYMBOL("ape_stack_pf", "7"); // RWX
// STATIC_STACK_ADDR(0x6fffffff0000);
// STATIC_STACK_SIZE(65536);
//
// @see ape.lds for defaults
.long PT_GNU_STACK
.long PF_R|PF_W
.stub ape_stack_offset,quad
.stub ape_stack_vaddr,quad
.stub ape_stack_paddr,quad
.stub ape_stack_filesz,quad
.stub ape_stack_memsz,quad
.stub ape_stack_align,quad
.stub ape_stack_pf,long # override w/ PF_X for execstack
.stub ape_stack_offset,quad # ignored
.stub ape_stack_vaddr,quad # is mmap()'d with MAP_FIXED
.stub ape_stack_paddr,quad # ignored
.stub ape_stack_filesz,quad # ignored
.stub ape_stack_memsz,quad # is mmap(size) argument
.stub ape_stack_align,quad # must be 16+
#if SupportsOpenbsd() || SupportsNetbsd()
.long PT_NOTE
.long PF_R
@ -1070,18 +1090,12 @@ str.error:
str.crlf:
.asciz "\r\n"
.endobj str.crlf
str.cpuid:
.asciz "cpuid"
.endobj str.cpuid
str.oldskool:
.asciz "oldskool"
.endobj str.oldskool
str.e820:
.asciz "e820"
.endobj str.e820
str.long:
.asciz "nolong"
.endobj str.long
str.oldcpu:
.asciz "oldcpu"
.endobj str.oldcpu
// Serial Line Configuration (8250 UART 16550)
// If it's hacked, it'll at least get hacked very slowly.
@ -1264,7 +1278,7 @@ longmodeloader:
lcheck: pushf # check for i8086 / i8088 / i80186
pop %ax
test $0x80,%ah # see intel manual volume 1 20.1.2
jnz 9f # we now assume 32bit is supported
jnz 10f # we now assume 32bit is supported
pushfl # now check for i386 or early i486
pop %eax # test ability to change cpuid bit
mov %eax,%ecx
@ -1275,7 +1289,7 @@ lcheck: pushf # check for i8086 / i8088 / i80186
pushfl
pop %eax
cmp %eax,%ecx
je 12f # we assume cpuid inst is available
je 10f # we assume cpuid inst is available
or %ebx,%eax # puts cpuid bit in the on position
push %eax
popfl
@ -1293,11 +1307,7 @@ lcheck: pushf # check for i8086 / i8088 / i80186
jne 10f
xor %ax,%ax
1: ret
9: mov $REAL(str.oldskool),%di
jmp 20f
10: mov $REAL(str.long),%di
jmp 20f
12: mov $REAL(str.cpuid),%di
10: mov $REAL(str.oldcpu),%di
20: call rldie
.endfn lcheck
@ -1615,5 +1625,26 @@ ape_idata_ro:
__data_start:
.previous
.section .dataepilogue,"aw",@progbits
.type __data_end,@object
.globl __data_end
.hidden __data_end
__data_end:
.previous
.section .bssprologue,"aw",@nobits
.type __bss_start,@object
.globl __bss_start
.hidden __bss_start
__bss_start:
.previous
.section .bssepilogue,"aw",@nobits
.type __bss_end,@object
.globl __bss_end
.hidden __bss_end
__bss_end:
.previous
.end


View file

@ -177,6 +177,8 @@
#include "ape/macros.internal.h"
#include "ape/relocations.h"
#include "libc/dce.h"
#include "libc/elf/def.h"
#include "libc/elf/pf2prot.internal.h"
#include "libc/nt/pedef.internal.h"
#include "libc/zip.h"
@ -342,7 +344,7 @@ SECTIONS {
/*END: Read Only Data (only needed for initialization) */
/*END: Read Only Data */
} :Rom
.tdata . : {
_tdata_start = .;
*(SORT_BY_ALIGNMENT(.tdata))
@ -358,6 +360,8 @@ SECTIONS {
.data . : {
/*BEGIN: Read/Write Data */
KEEP(*(SORT_BY_NAME(.piro.data.sort.iat.*)))
/*BEGIN: NT FORK COPYING */
KEEP(*(.dataprologue))
*(.data .data.*)
KEEP(*(SORT_BY_NAME(.sort.data.*)))
@ -378,6 +382,8 @@ SECTIONS {
. = ALIGN(__SIZEOF_POINTER__);
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
KEEP(*(.piro.pad.data))
KEEP(*(.dataepilogue))
/*END: NT FORK COPYING */
. = ALIGN(PAGESIZE);
HIDDEN(_edata = .);
PROVIDE_HIDDEN(edata = .);
@ -404,6 +410,8 @@ SECTIONS {
/*BEGIN: bss memory that's addressable */
.bss ALIGN(64) : {
/*BEGIN: NT FORK COPYING */
KEEP(*(.bssprologue))
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
*(.piro.bss)
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
@ -418,6 +426,8 @@ SECTIONS {
KEEP(*(SORT_BY_NAME(.sort.bss.*)))
KEEP(*(.bssepilogue))
/*END: NT FORK COPYING */
. = ALIGN(FRAMESIZE); /* for brk()/sbrk() allocation */
HIDDEN(_end = .);
PROVIDE_HIDDEN(end = .);
@ -477,9 +487,9 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
PFSTUB4(ape_elf_shnum, 0);
PFSTUB4(ape_elf_shstrndx, 0);
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
ROUNDDOWN(__privileged_start, PAGESIZE)));
ROUNDDOWN(__privileged_start, PAGESIZE)));
HIDDEN(ape_rom_offset = 0);
HIDDEN(ape_rom_vaddr = ADDR(.head));
@ -497,6 +507,8 @@ HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
HIDDEN(ape_ram_align = PAGESIZE);
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
HIDDEN(ape_stack_pf = DEFINED(ape_stack_pf) ? ape_stack_pf : PF_R | PF_W);
HIDDEN(ape_stack_prot = _PF2PROT(ape_stack_pf));
HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz);
HIDDEN(ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000 - STACKSIZE);
HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -5,6 +5,7 @@
#
# - `make`
# - Backtraces
# - Syscall tracing
# - Function tracing
# - Reasonably small
# - Reasonably optimized
@ -13,6 +14,7 @@ ifeq ($(MODE),)
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-DSYSDEBUG \
-Og
TARGET_ARCH ?= \
-msse3
@ -23,6 +25,8 @@ endif
# - `make MODE=opt`
# - Backtraces
# - More optimized
# - Syscall tracing
# - Function tracing
# - Reasonably small
# - No memory corruption detection
# - assert() / CHECK_xx() may leak code into binary for debuggability
@ -35,7 +39,9 @@ CONFIG_CPPFLAGS += \
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-O3
-DSYSDEBUG \
-O3 \
-fmerge-all-constants
TARGET_ARCH ?= \
-march=native
endif
@ -55,7 +61,7 @@ CONFIG_CPPFLAGS += \
-Wa,-msse2avx \
-DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += \
-O3
-O3 -fmerge-all-constants
DEFAULT_COPTS += \
-mred-zone
TARGET_ARCH ?= \
@ -122,10 +128,12 @@ CONFIG_CPPFLAGS += \
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-DSYSDEBUG \
-O2 \
-fno-inline
CONFIG_COPTS += \
-fsanitize=address
-fsanitize=address \
-fsanitize=undefined
TARGET_ARCH ?= \
-msse3
OVERRIDE_CCFLAGS += \
@ -287,7 +295,7 @@ endif
# LLVM Mode
ifeq ($(MODE), llvm)
TARGET_ARCH ?= -msse3
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O2
AS = clang
CC = clang
CXX = clang++

View file

@ -100,7 +100,8 @@ SANITIZER = \
NO_MAGIC = \
-mno-fentry \
-fno-stack-protector \
-fwrapv
-fwrapv \
-fno-sanitize=all
OLD_CODE = \
-fno-strict-aliasing \
@ -148,7 +149,6 @@ DEFAULT_CFLAGS = \
-std=gnu2x
DEFAULT_CXXFLAGS = \
-std=gnu++11 \
-fno-rtti \
-fno-exceptions \
-fuse-cxa-atexit \
@ -169,7 +169,7 @@ DEFAULT_LDFLAGS = \
--gc-sections \
--build-id=none \
--no-dynamic-linker \
-zmax-page-size=0x1000
-zmax-page-size=0x1000 #--cref -Map=$@.map
ZIPOBJ_FLAGS = \
-b$(IMAGE_BASE_VIRTUAL)
@ -301,6 +301,9 @@ OBJECTIFY.greg.c = \
-fno-instrument-functions \
-fno-optimize-sibling-calls \
-fno-sanitize=all \
-ffreestanding \
-mno-fentry \
-fwrapv \
-c
OBJECTIFY.ansi.c = $(CC) $(OBJECTIFY.c.flags) -ansi -Wextra -Werror -pedantic-errors -c

View file

@ -48,7 +48,7 @@
set -- --regex-c='/^\(\(hidden\|extern\|const\) \)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)/\4/b' "$@"
# ctags doesn't understand function prototypes, e.g.
# bool isheap(void *p) nothrow nocallback;
# bool isheap(void *p) dontthrow nocallback;
set -- --regex-c='/^[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)(.*/\2/b' "$@"
# ctags doesn't understand function pointers, e.g.

View file

@ -31,7 +31,7 @@ o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds)
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
o/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
o/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
o/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
o/%.okk: % ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/%.zip.o: o/% ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
@ -60,7 +60,8 @@ o/$(MODE)/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx
o/$(MODE)/%.o: o/$(MODE)/%.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
o/$(MODE)/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
o/$(MODE)/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
o/$(MODE)/%.hh.ok: %.hh ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
o/$(MODE)/%.okk: % ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
o/$(MODE)/%.cxx.o: %.c ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) -xc++ $(OUTPUT_OPTION) $<
o/$(MODE)/%.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
@ -77,7 +78,9 @@ o/$(MODE)/%.runs: o/$(MODE)/% ; @$(COMPILE) -ACHECK -tT$@ $< $(TESTARGS)
o/$(MODE)/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
o/$(MODE)/%.zip.o: % ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-gcc.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: CC = $(CLANG)
o/%.a:

View file

@ -37,4 +37,3 @@ sad16x8n:
jnz 0b
1: .leafepilogue
.endfn sad16x8n,globl,hidden
.source __FILE__

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.source __FILE__
clamp4int256$core:
.leafprologue

View file

@ -72,7 +72,8 @@ static const float PLM_VIDEO_PIXEL_ASPECT_RATIO[] = {
0.6735, /* 3:4? */
0.7031, /* MPEG-1 / MPEG-2 video encoding divergence? */
0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815,
1.0255, 1.0695, 1.0950, 1.1575, 1.2051};
1.0255, 1.0695, 1.0950, 1.1575, 1.2051,
};
static const float PLM_VIDEO_PICTURE_RATE[] = {
23.976, /* NTSC-Film */

View file

@ -101,7 +101,7 @@ struct SamplingSolution *ComputeSamplingSolution(long dn, long sn, double dar,
if (!off) off = (dar - 1) / 2;
f = dar < 1 ? 1 / dar : dar;
s = 3 * f + 4;
fweights = gc(xcalloc(s, sizeof(double)));
fweights = gc(xcalloc(s + /*xxx*/ 2, sizeof(double)));
res = NewSamplingSolution(dn, s);
weights = res->weights;
indices = res->indices;

View file

@ -19,6 +19,7 @@
#include "dsp/tty/tty.h"
#include "libc/bits/pushpop.h"
#include "libc/dce.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"
#include "libc/nt/console.h"
#include "libc/nt/runtime.h"
@ -30,7 +31,7 @@
static int ttysetcursor(int fd, bool visible) {
struct NtConsoleCursorInfo ntcursor;
char code[8] = "\e[?25l";
if (IsTerminalInarticulate()) return 0;
if (__nocolor) return 0;
if (visible) code[5] = 'h';
if (SupportsWindows()) {
GetConsoleCursorInfo(GetStdHandle(kNtStdOutputHandle), &ntcursor);

View file

@ -31,13 +31,6 @@ int ttysetraw(struct termios *conf, int64_t flags) {
conf->c_cflag &= ~(CSIZE | PARENB);
conf->c_cflag |= CS8;
conf->c_iflag |= IUTF8;
/* if (flags & kTtyLfToCrLf) { */
/* /\* conf->c_oflag &= ~(OLCUC | OCRNL | ONLRET | OFILL | OFDEL); *\/ */
/* /\* conf->c_oflag |= ONLCR | ONOCR; *\/ */
/* conf->c_oflag |= ONLCR; */
/* } else { */
/* conf->c_oflag &= ~OPOST; */
/* } */
if (!(flags & kTtySigs)) {
conf->c_iflag &= ~(IGNBRK | BRKINT);
conf->c_lflag &= ~(ISIG);

View file

@ -731,19 +731,19 @@ static bool ChunkEq(struct TtyRgb c[hasatleast 4],
}
static struct TtyRgb *CopyChunk(struct TtyRgb chunk[hasatleast 4],
const struct TtyRgb *c, size_t n) {
chunk[TL] = c[0 + 0];
chunk[TR] = c[0 + 1];
chunk[BL] = c[n + 0];
chunk[BR] = c[n + 1];
const struct TtyRgb *c, size_t xn) {
chunk[TL] = c[00 + 0];
chunk[TR] = c[00 + 1];
chunk[BL] = c[xn + 0];
chunk[BR] = c[xn + 1];
return chunk;
}
static dontinline char *CopyRun(char *v, size_t n,
struct TtyRgb lastchunk[hasatleast 4],
const struct TtyRgb **c, size_t *x,
struct TtyRgb *bg, struct TtyRgb *fg,
struct Glyph *glyph) {
struct TtyRgb lastchunk[hasatleast 4],
const struct TtyRgb **c, size_t *x,
struct TtyRgb *bg, struct TtyRgb *fg,
struct Glyph *glyph) {
struct TtyRgb chunk[4];
if (memcmp(glyph, &kGlyphs[1][0], sizeof(*glyph)) == 0) {
if (!ttyeq(*bg, *fg)) {
@ -766,17 +766,18 @@ static dontinline char *CopyRun(char *v, size_t n,
/**
* Maps 2×2 pixel chunks onto ANSI UNICODE cells.
* @note h/t Nick Black for his quadrant blitting work on notcurses
* @note yn and xn need to be even
*/
char *ttyraster(char *v, const struct TtyRgb *c, size_t yn, size_t n,
char *ttyraster(char *v, const struct TtyRgb *c, size_t yn, size_t xn,
struct TtyRgb bg, struct TtyRgb fg) {
unsigned y, x;
struct Pick p;
struct Glyph glyph;
struct TtyRgb chun[4], lastchunk[4];
for (y = 0; y < yn; y += 2, c += n) {
for (y = 0; y < yn; y += 2, c += xn) {
if (y) *v++ = '\r', *v++ = '\n';
for (x = 0; x < n; x += 2, c += 2) {
CopyChunk(chun, c, n);
for (x = 0; x < xn; x += 2, c += 2) {
CopyChunk(chun, c, xn);
if (ttyquant()->alg == kTtyQuantTrue) {
if (ttyquant()->blocks == kTtyBlocksCp437) {
p = PickBlockCp437True(chun[TL], chun[TR], chun[BL], chun[BR]);

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.source __FILE__
// Returns index of minimum uint16 in array.
//

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.source __FILE__
// Returns index of minimum positive int16 in array.
//

View file

@ -18,7 +18,6 @@
*/
#include "libc/nexgen32e/x86feature.h"
#include "libc/macros.internal.h"
.source __FILE__
// Dispatches to fastest windex() implementation.
.initbss 300,_init_windex

View file

@ -18,9 +18,12 @@
* make -j12 o//examples/auto-launch-gdb-on-crash.com
* o//examples/auto-launch-gdb-on-crash.com
*
* Backtrace is logged instead if run outside interactive terminal.
* Environmental factors such as GDB, MAKEFLAGS, ADDR2LINE, TERM, and
* isatty(STDERR_FILENO) should also be taken into consideration:
* Backtrace is logged instead if run outside interactive terminal. We
* also don't auto-launch GDB on non-Linux since the development tools
* on other platforms generally can't be relied upon to correctly debug
* binaries built with a Linux toolchain. Environmental factors such as
* GDB, MAKEFLAGS, ADDR2LINE, TERM, and isatty(STDERR_FILENO) should
* also be taken into consideration:
*
* $ export GDB=eoatuhshtuone
* $ o//examples/auto-launch-gdb-on-crash.com
@ -37,7 +40,7 @@
*/
int main(int argc, char *argv[]) {
showcrashreports();
ShowCrashReports();
asm("int3"); /* cf. __die(), perror("msg"), abort(), exit(1), _Exit(1) */
return 0;
}

View file

@ -0,0 +1,62 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/bits/bits.h"
#include "libc/dce.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
/**
* ASAN static memory safety crash example.
*
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash.com
* o/dbg/examples/auto-memory-safety-crash.com
*
* You should see:
*
* global redzone 1-byte store at 0x42700d shadow 0x8007ce01
* ./o/dbg/examples/auto-memory-safety-crash.com
* x
* ........................................GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
* |0 |0 |0 |0 |5 |-18 |-18 |-18 |-18
*  f.ä     f.ä     fD  hello                                                
* 000000400000-000000427000 .text
* 000000427000-000000429000 .data address
* 00007fff0000-00008000ffff
* 000080070000-00008008ffff shadow
* 0e007fff0000-0e008000ffff
* 100047d20000-100047d3ffff
* 6ffffffe0000-6fffffffffff
* the memory in question belongs to the symbols
* buffer [0x427000,0x42700c] size 13
* the crash was caused by
* 0x00000000004046f3: __die at libc/log/die.c:40
* 0x0000000000404aed: __asan_report_store at libc/intrin/asan.c:1183
* 0x0000000000402552: main at examples/auto-memory-safety-crash.c:27
* 0x000000000040268d: cosmo at libc/runtime/cosmo.S:64
* 0x00000000004021ae: _start at libc/crt/crt.S:77
*
* @see libc/intrin/asancodes.h for meaning of G, etc. and negative numbers
* @see libc/nexgen32e/kcp437.S for meaning of symbols
*/
char buffer[13] = "hello";
int main(int argc, char *argv[]) {
if (!IsAsan()) {
printf("this example is intended for MODE=asan or MODE=dbg\n");
exit(1);
}
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
int i = 13;
asm("" : "+r"(i)); /* prevent compiler being smart */
buffer[i] = 1;
return 0;
}

View file

@ -0,0 +1,74 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/bits/bits.h"
#include "libc/dce.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
/**
* ASAN heap memory safety crash example.
*
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash2.com
* o/dbg/examples/auto-memory-safety-crash2.com
*
* You should see:
*
* heap overrun 1-byte store at 0x10008004002d shadow 0x20090000005
* ./o/dbg/examples/auto-memory-safety-crash2.com
* x
* OOOOOOOOOOOUUUUUUUUUUUUUUUU.............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
* |-7 |-6 |-6 |0 |5 |-7 |-7 |-7 |-7
*    »!@     ÿ:Y= S       hello                 GT&@     á+@     »!@  
* 000000400000-00000042b000 .text
* 00000042b000-00000042d000 .data
* 00007fff0000-00008000ffff
* 000080070000-00008008ffff
* 02008fff0000-02009000ffff shadow
* 0e007fff0000-0e008000ffff
* 10003ab90000-10003abaffff
* 100080000000-10008000ffff address
* 6ffffffe0000-6fffffffffff
*
* the memory was allocated by
* 0x100080040020 64 bytes [dlmalloc]
* 0x100080040030 13 bytes [actual]
* 402608 main
* 402ba0 cosmo
* 4021af _start
*
* the crash was caused by
* 0x0000000000404793: __die at libc/log/die.c:40
* 0x0000000000404f56: __asan_report_store at libc/intrin/asan.c:1183
* 0x0000000000402579: main at examples/auto-memory-safety-crash2.c:30
* 0x000000000040270f: cosmo at libc/runtime/cosmo.S:64
* 0x00000000004021ae: _start at libc/crt/crt.S:77
*
* @see libc/intrin/asancodes.h for meaning of U, O, etc. and negative numbers
* @see libc/nexgen32e/kcp437.S for meaning of symbols
*/
int main(int argc, char *argv[]) {
if (!IsAsan()) {
printf("this example is intended for MODE=asan or MODE=dbg\n");
exit(1);
}
char *buffer;
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
buffer = malloc(13);
strcpy(buffer, "hello");
int i = 13;
asm("" : "+r"(i)); /* prevent compiler being smart */
buffer[i] = 1;
asm("" : "+r"(buffer)); /* prevent compiler being smart */
return 0;
}

View file

@ -0,0 +1,39 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/bits/bits.h"
#include "libc/dce.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
/**
* ASAN use-after-free memory safety crash example.
*
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash3.com
* o/dbg/examples/auto-memory-safety-crash3.com
*
*/
int main(int argc, char *argv[]) {
if (!IsAsan()) {
printf("this example is intended for MODE=asan or MODE=dbg\n");
exit(1);
}
char *buffer;
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
buffer = malloc(13);
strcpy(buffer, "hello");
free(buffer);
asm("" : "+r"(buffer)); /* prevent compiler being smart */
buffer[0] = 1;
return 0;
}

View file

@ -7,19 +7,30 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/intrin/kprintf.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdio/stdio.h"
int main(int argc, char *argv[]) {
showcrashreports();
ShowCrashReports();
if (IsDebuggerPresent(false)) {
printf("debugger found!\r\n");
DebugBreak();
return 0;
kprintf("debugger found!%n");
} else {
kprintf("try running: gdb %s%n", argv[0]);
kprintf("try running: o//tool/build/strace.com %s%n", argv[0]);
}
printf("try running: gdb %s\r\n", argv[0]);
return 1;
asm volatile("mov\t%4,%%r10\n\t"
"mov\t%5,%%r8\n\t"
"mov\t%6,%%r9\n\t"
"int3"
: /* no outputs */
: "a"(0), "D"(1), "S"(2), "d"(3), "g"(4), "g"(5), "g"(6)
: "r8", "r9", "r10");
printf("recovered from SIGTRAP without handler\r\n");
return 0;
}

View file

@ -73,14 +73,14 @@ void GetOpts(int argc, char *argv[]) {
int cp(const char *src, const char *dst) {
if (endswith(dst, "/") || isdirectory(dst)) {
dst = _gc(xasprintf("%s/%s", dst, basename));
dst = _gc(xasprintf("%s/%s", dst, basename(src)));
}
if (!force && access(dst, W_OK) == -1 && errno != ENOENT) goto OnFail;
if (copyfile(src, dst, flags) == -1) goto OnFail;
return 0;
OnFail:
fprintf(stderr, "%s %s %s: %s\n", "error: cp", src, dst, strerror(errno));
return 1;
return -1;
}
int main(int argc, char *argv[]) {

38
examples/cplusplus-stl.cc Normal file
View file

@ -0,0 +1,38 @@
/*-*-mode:c++;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8-*-│
vi: set net ft=c++ ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/stdio.h"
#include "third_party/libcxx/map"
#include "third_party/libcxx/string"
int main(int argc, char *argv[]) {
printf("std::map + std::string example\n");
std::map<std::string, int> m{
{"CPU", 10},
{"GPU", 15},
{"RAM", 20},
};
printf("m[\"CPU\"] is %d\n", m["CPU"]);
printf("m[\"RAM\"] is %d\n", m["RAM"]);
printf("m[\"GPU\"] is %d\n", m["GPU"]);
printf("setting cpu to 25\n");
m["CPU"] = 25; // update an existing value
printf("m[\"CPU\"] is %d\n", m["CPU"]);
printf("m[\"RAM\"] is %d\n", m["RAM"]);
printf("m[\"GPU\"] is %d\n", m["GPU"]);
}

View file

@ -24,6 +24,6 @@
int main(int argc, char *argv[]) {
volatile int64_t x;
showcrashreports();
ShowCrashReports();
return 1 / (x = 0);
}

52
examples/crashreport2.c Normal file
View file

@ -0,0 +1,52 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/log/log.h"
#include "libc/stdio/stdio.h"
/**
* @fileoverview CTRL+\ debugging example
*
* make -j8 -O o//examples/crashreport2.com
* o//examples/crashreport2.com
*
* Assuming you call ShowCrashReports() from main(), you can press
* `CTRL+\` at anny time to generate a `SIGQUIT` message that lets you
* debug wrongness and freezups.
*
* On supported platforms, this will cause GDB to automatically attach.
* The nice thing about this, is you can start stepping through your
* code at the precice instruction where the interrupt happened. See
* `libc/log/attachdebugger.c` to see how it works.
*
* If you wish to suppress the auto-GDB behavior, then:
*
* export GDB=
*
* Or alternatively:
*
* extern int __isworker;
* __isworker = true;
*
* Will cause your `SIGQUIT` handler to just print a crash report
* instead. This is useful for production software that might be running
* in a terminal environment like GNU Screen, but it's not desirable to
* have ten worker processes trying to attach GDB at once.
*/
int main(int argc, char *argv[]) {
volatile int64_t x;
ShowCrashReports();
printf("please press ctrl+\\ and see what happens...\n");
sigsuspend(0);
printf("\n\n");
printf("congratulations! your program is now resuming\n");
return 0;
}

View file

@ -36,7 +36,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "This echos stdio until Ctrl+C is pressed.\n");
CHECK_NE(-1, sigaction(SIGINT, &saint, NULL));
for (;;) {
rc = read(0, buf, BUFSIZ);
rc = read(0, buf, 512);
if (rc != -1) {
got = rc;
} else {

View file

@ -65,11 +65,26 @@
#define HeaderEqualCase(H, S) \
SlicesEqualCase(S, strlen(S), HeaderData(H), HeaderLength(H))
int sock;
static bool TuneSocket(int fd, int a, int b, int x) {
if (!b) return false;
return setsockopt(fd, a, b, &x, sizeof(x)) != -1;
}
static void Write(const void *p, size_t n) {
ssize_t rc;
rc = write(1, p, n);
if (rc == -1 && errno == EPIPE) {
close(sock);
exit(128 + SIGPIPE);
}
if (rc != n) {
fprintf(stderr, "write failed: %m\n");
exit(1);
}
}
static int TlsSend(void *c, const unsigned char *p, size_t n) {
int rc;
NOISEF("begin send %zu", n);
@ -106,8 +121,7 @@ static wontreturn void PrintUsage(FILE *f, int rc) {
}
int main(int argc, char *argv[]) {
if (!NoDebug()) showcrashreports();
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
if (!NoDebug()) ShowCrashReports();
/*
* Read flags.
@ -226,19 +240,17 @@ int main(int argc, char *argv[]) {
*/
mbedtls_ssl_config conf;
mbedtls_ssl_context ssl;
mbedtls_x509_crt *cachain = 0;
mbedtls_ctr_drbg_context drbg;
if (usessl) {
mbedtls_ssl_init(&ssl);
mbedtls_ctr_drbg_init(&drbg);
mbedtls_ssl_config_init(&conf);
cachain = GetSslRoots();
CHECK_EQ(0, mbedtls_ctr_drbg_seed(&drbg, GetEntropy, 0, "justine", 7));
CHECK_EQ(0, mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT));
mbedtls_ssl_conf_authmode(&conf, authmode);
mbedtls_ssl_conf_ca_chain(&conf, cachain, 0);
mbedtls_ssl_conf_ca_chain(&conf, GetSslRoots(), 0);
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &drbg);
if (!IsTiny()) mbedtls_ssl_conf_dbg(&conf, TlsDebug, 0);
CHECK_EQ(0, mbedtls_ssl_setup(&ssl, &conf));
@ -258,7 +270,7 @@ int main(int argc, char *argv[]) {
/*
* Connect to server.
*/
int ret, sock;
int ret;
CHECK_NE(-1, (sock = GoodSocket(addr->ai_family, addr->ai_socktype,
addr->ai_protocol, false,
&(struct timeval){-60})));
@ -283,6 +295,8 @@ int main(int argc, char *argv[]) {
CHECK_EQ(n, write(sock, request, n));
}
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
/*
* Handle response.
*/
@ -330,7 +344,7 @@ int main(int argc, char *argv[]) {
break;
}
if (method == kHttpHead) {
CHECK_EQ(hdrlen, write(1, p, hdrlen));
Write(p, hdrlen);
goto Finished;
} else if (msg.status == 204 || msg.status == 304) {
goto Finished;
@ -348,32 +362,32 @@ int main(int argc, char *argv[]) {
t = kHttpClientStateBodyLengthed;
paylen = rc;
if (paylen > i - hdrlen) {
CHECK_EQ(i - hdrlen, write(1, p + hdrlen, i - hdrlen));
Write(p + hdrlen, i - hdrlen);
} else {
CHECK_EQ(paylen, write(1, p + hdrlen, paylen));
Write(p + hdrlen, paylen);
goto Finished;
}
} else {
t = kHttpClientStateBody;
CHECK_EQ(i - hdrlen, write(1, p + hdrlen, i - hdrlen));
Write(p + hdrlen, i - hdrlen);
}
}
break;
case kHttpClientStateBody:
if (!g) goto Finished;
CHECK_EQ(g, write(1, p + i - g, g));
Write(p + i - g, g);
break;
case kHttpClientStateBodyLengthed:
CHECK(g);
if (i - hdrlen > paylen) g = hdrlen + paylen - (i - g);
CHECK_EQ(g, write(1, p + i - g, g));
Write(p + i - g, g);
if (i - hdrlen >= paylen) goto Finished;
break;
case kHttpClientStateBodyChunked:
Chunked:
CHECK_NE(-1, (rc = Unchunk(&u, p + hdrlen, i - hdrlen, &paylen)));
if (rc) {
CHECK_EQ(paylen, write(1, p + hdrlen, paylen));
Write(p + hdrlen, paylen);
goto Finished;
}
break;
@ -397,7 +411,6 @@ Finished:
mbedtls_ssl_free(&ssl);
mbedtls_ctr_drbg_free(&drbg);
mbedtls_ssl_config_free(&conf);
mbedtls_x509_crt_free(cachain);
mbedtls_ctr_drbg_free(&drbg);
}

62
examples/datauri.c Normal file
View file

@ -0,0 +1,62 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/log/log.h"
#include "libc/runtime/gc.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/x/x.h"
#include "net/http/escape.h"
#include "net/http/http.h"
#include "third_party/getopt/getopt.h"
#include "third_party/stb/stb_image.h"
#define USAGE \
" [FLAGS] FILE...\n\
Utility for printing data:base64 URIs.\n\
\n\
FLAGS\n\
\n\
-h Help\n"
void PrintUsage(int rc, FILE *f) {
fputs("Usage: ", f);
fputs(program_invocation_name, f);
fputs(USAGE, f);
exit(rc);
}
void PrintUri(const char *path) {
size_t n;
void *img, *src, *mime;
int opt, i;
if (!(img = gc(xslurp(path, &n)))) exit(2);
fputs("data:", stdout);
fputs(FindContentType(path, -1), stdout);
fputs(";base64,", stdout);
fputs(gc(EncodeBase64(img, n, 0)), stdout);
}
int main(int argc, char *argv[]) {
int i;
while ((i = getopt(argc, argv, "?h")) != -1) {
switch (i) {
case '?':
case 'h':
PrintUsage(0, stdout);
default:
PrintUsage(1, stderr);
}
}
if (optind == argc) {
PrintUsage(1, stderr);
}
for (i = optind; i < argc; ++i) {
PrintUri(argv[i]);
}
}

View file

@ -8,135 +8,146 @@ EXAMPLES_MAINS_S = $(filter %.S,$(EXAMPLES_FILES))
EXAMPLES_MAINS_C = $(filter %.c,$(EXAMPLES_FILES))
EXAMPLES_MAINS_CC = $(filter %.cc,$(EXAMPLES_FILES))
EXAMPLES_SRCS = \
$(EXAMPLES_MAINS_S) \
$(EXAMPLES_MAINS_C) \
EXAMPLES_SRCS = \
$(EXAMPLES_MAINS_S) \
$(EXAMPLES_MAINS_C) \
$(EXAMPLES_MAINS_CC)
EXAMPLES_MAINS = \
$(EXAMPLES_MAINS_S) \
$(EXAMPLES_MAINS_C) \
EXAMPLES_MAINS = \
$(EXAMPLES_MAINS_S) \
$(EXAMPLES_MAINS_C) \
$(EXAMPLES_MAINS_CC)
EXAMPLES_OBJS = \
$(EXAMPLES_MAINS_S:%.S=o/$(MODE)/%.o) \
$(EXAMPLES_MAINS_C:%.c=o/$(MODE)/%.o) \
EXAMPLES_OBJS = \
$(EXAMPLES_MAINS_S:%.S=o/$(MODE)/%.o) \
$(EXAMPLES_MAINS_C:%.c=o/$(MODE)/%.o) \
$(EXAMPLES_MAINS_CC:%.cc=o/$(MODE)/%.o)
EXAMPLES_COMS = \
$(EXAMPLES_MAINS_S:%.S=o/$(MODE)/%.com) \
$(EXAMPLES_MAINS_C:%.c=o/$(MODE)/%.com) \
EXAMPLES_COMS = \
$(EXAMPLES_MAINS_S:%.S=o/$(MODE)/%.com) \
$(EXAMPLES_MAINS_C:%.c=o/$(MODE)/%.com) \
$(EXAMPLES_MAINS_CC:%.cc=o/$(MODE)/%.com)
EXAMPLES_BINS = \
$(EXAMPLES_COMS) \
EXAMPLES_BINS = \
$(EXAMPLES_COMS) \
$(EXAMPLES_COMS:%=%.dbg)
EXAMPLES_DIRECTDEPS = \
DSP_CORE \
DSP_SCALE \
DSP_TTY \
LIBC_ALG \
LIBC_BITS \
LIBC_CALLS \
LIBC_DNS \
LIBC_FMT \
LIBC_INTRIN \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_NT_ADVAPI32 \
LIBC_OHMYPLUS \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_TESTLIB \
LIBC_THREAD \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_UNICODE \
LIBC_X \
LIBC_ZIPOS \
NET_HTTP \
NET_HTTPS \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_LINENOISE \
THIRD_PARTY_LUA \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_MUSL \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_STB \
THIRD_PARTY_XED \
THIRD_PARTY_ZLIB \
TOOL_BUILD_LIB \
EXAMPLES_DIRECTDEPS = \
DSP_CORE \
DSP_SCALE \
DSP_TTY \
LIBC_ALG \
LIBC_BITS \
LIBC_CALLS \
LIBC_DNS \
LIBC_FMT \
LIBC_INTRIN \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_NT_ADVAPI32 \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_TESTLIB \
LIBC_THREAD \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_UNICODE \
LIBC_X \
LIBC_ZIPOS \
NET_HTTP \
NET_HTTPS \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_LINENOISE \
THIRD_PARTY_LUA \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_MUSL \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_STB \
THIRD_PARTY_XED \
THIRD_PARTY_ZLIB \
TOOL_BUILD_LIB \
TOOL_VIZ_LIB
EXAMPLES_DEPS := \
EXAMPLES_DEPS := \
$(call uniq,$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x))))
o/$(MODE)/examples/examples.pkg: \
$(EXAMPLES_OBJS) \
o/$(MODE)/examples/examples.pkg: \
$(EXAMPLES_OBJS) \
$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/examples/unbourne.o: \
OVERRIDE_CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED
o/$(MODE)/examples/unbourne.o: \
OVERRIDE_CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED \
-fpie
o/$(MODE)/examples/%.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/%.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
o/$(MODE)/examples/%.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/%.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE)
@$(APELINK)
o/$(MODE)/examples/hellolua.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/hellolua.o \
o/$(MODE)/examples/hellolua.lua.zip.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
o/$(MODE)/examples/hellolua.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/hellolua.o \
o/$(MODE)/examples/hellolua.lua.zip.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE)
@$(APELINK)
o/$(MODE)/examples/ispell.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/ispell.o \
o/$(MODE)/usr/share/dict/words.zip.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
o/$(MODE)/examples/ispell.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/ispell.o \
o/$(MODE)/usr/share/dict/words.zip.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE)
@$(APELINK)
o/$(MODE)/examples/nesemu1.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/nesemu1.o \
o/$(MODE)/usr/share/rom/mario.nes.zip.o \
o/$(MODE)/usr/share/rom/zelda.nes.zip.o \
o/$(MODE)/usr/share/rom/tetris.nes.zip.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
o/$(MODE)/examples/nesemu1.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/nesemu1.o \
o/$(MODE)/usr/share/rom/mario.nes.zip.o \
o/$(MODE)/usr/share/rom/zelda.nes.zip.o \
o/$(MODE)/usr/share/rom/tetris.nes.zip.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE)
@$(APELINK)
o/$(MODE)/examples/hello.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/hello.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
o/$(MODE)/examples/nesemu1.com: \
o/$(MODE)/examples/nesemu1.com.dbg \
o/$(MODE)/third_party/zip/zip.com \
o/$(MODE)/tool/build/symtab.com
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
@$(COMPILE) -ASYMTAB o/$(MODE)/tool/build/symtab.com \
-o o/$(MODE)/examples/.nesemu1/.symtab $<
@$(COMPILE) -AZIP -T$@ o/$(MODE)/third_party/zip/zip.com -0qj $@ \
o/$(MODE)/examples/.nesemu1/.symtab
o/$(MODE)/examples/hello.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/hello.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
@ -149,6 +160,6 @@ usr/share/dict/words: usr/share/dict/words.gz
@$(GZ) $(ZFLAGS) -d <$< >$@
.PHONY: o/$(MODE)/examples
o/$(MODE)/examples: \
o/$(MODE)/examples/package \
o/$(MODE)/examples: \
o/$(MODE)/examples/package \
$(EXAMPLES_BINS)

View file

@ -8,14 +8,26 @@
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/struct/sigset.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/sig.h"
STATIC_YOINK("strerror");
int main(int argc, char *argv[]) {
if (argc < 3) {
fputs("USAGE: EXEC.COM PROG ARGV₀ [ARGV₁...]\n", stderr);
sigset_t ss;
if (argc < 2) {
fputs("USAGE: EXEC.COM PROG [ARGV₀...]\n", stderr);
return 1;
}
// block arbitrary signal so __printargs() looks cooler
sigemptyset(&ss);
sigaddset(&ss, SIGPWR);
sigprocmask(SIG_BLOCK, &ss, 0);
execv(argv[1], argv + 2);
return 127;
}

23
examples/forkexec.c Normal file
View file

@ -0,0 +1,23 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/stdio/stdio.h"
int main(int argc, char *argv[]) {
int pid;
if (argc < 3) {
fputs("USAGE: FORKEXEC.COM PROG ARGV₀ [ARGV₁...]\n", stderr);
return 1;
}
if (!fork()) {
execv(argv[1], argv + 2);
return 127;
}
}

25
examples/forkexecwait.c Normal file
View file

@ -0,0 +1,25 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/stdio/stdio.h"
int main(int argc, char *argv[]) {
int pid;
volatile void *p;
if (argc < 3) {
fputs("USAGE: FORKEXECWAIT.COM PROG ARGV₀ [ARGV₁...]\n", stderr);
return 1;
}
if (!fork()) {
execv(argv[1], argv + 2);
return 127;
}
wait(0);
}

View file

@ -8,13 +8,17 @@
*/
#endif
#include "libc/calls/calls.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/nt/nt/process.h"
#include "libc/rand/rand.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
dontinline void dostuff(const char *s) {
int i, us;

View file

@ -14,11 +14,11 @@
int main(int argc, char *argv[]) {
int c, n;
char a[22];
char a[22], *p;
if ((c = GetCpuCount())) {
n = int64toarray_radix10(c, a);
a[n++] = '\n';
return write(1, a, n) == n ? 0 : 1;
p = FormatInt64(a, c);
*p++ = '\n';
return write(1, a, p - a) == p - a ? 0 : 1;
} else {
return 1;
}

View file

@ -209,6 +209,7 @@ const struct Function {
{"getrandom", GetRandom}, //
{"inc", inc}, //
{"knuth", knuth}, //
{"lemur64", lemur64}, //
{"libc", libc}, //
{"moby", moby}, //
{"mt19937", _mt19937}, //

View file

@ -44,8 +44,8 @@
#include "libc/str/str.h"
#include "libc/time/time.h"
#include "third_party/zlib/zlib.h"
// clang-format off
/* clang-format off */
#define DICT "usr/share/dict/hangman"
#define MAXERR 7
#define MINSCORE 0

View file

@ -9,6 +9,8 @@
#endif
#include "libc/stdio/stdio.h"
STATIC_YOINK("mmap"); // TODO: fix bandaid for MODE=asan
int main() {
printf("%s\n", "hello world");
return 0;

View file

@ -7,23 +7,98 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/dce.h"
#include "libc/log/log.h"
#include "libc/runtime/gc.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/x/x.h"
#include "net/http/escape.h"
#include "net/http/http.h"
#include "third_party/getopt/getopt.h"
#include "third_party/stb/stb_image.h"
/**
* @fileoverview Utility for printing HTML <img> tags.
*/
#define USAGE \
" [FLAGS] IMG...\n\
Utility for printing HTML <img> tags.\n\
\n\
FLAGS\n\
\n\
-h Help\n\
-a Wrap with <a> tag\n\
-u Embed data:base64 URI\n"
int scale;
bool linktag;
bool datauri;
bool sizeonly;
void PrintUsage(int rc, FILE *f) {
fputs("Usage: ", f);
fputs(program_invocation_name, f);
fputs(USAGE, f);
exit(rc);
}
void PrintImg(const char *path) {
size_t n;
int opt, i, yn, xn, cn, w, h;
void *img, *pix, *src, *mime;
if (!(img = gc(xslurp(path, &n)))) exit(2);
if (!(pix = gc(stbi_load_from_memory(img, n, &xn, &yn, &cn, 0)))) exit(3);
if (linktag) {
printf("<a href=\"%s\"\n >", path);
}
src = path;
if (datauri) {
src = xasprintf("data:%s;base64,%s", FindContentType(path, -1),
gc(EncodeBase64(img, n, &n)));
}
w = (xn + (1 << scale) / 2) >> scale;
h = (yn + (1 << scale) / 2) >> scale;
if (sizeonly) {
printf("width=\"%d\" height=\"%d\"", w, h);
} else {
printf("<img width=\"%d\" height=\"%d\" alt=\"[%s]\"\n src=\"%s\">", w,
h, path, src);
}
if (linktag) {
printf("</a>");
}
printf("\n");
}
int main(int argc, char *argv[]) {
void *p;
size_t n;
int yn, xn, cn;
if (argc != 2) return 1;
if (!(p = xslurp(argv[1], &n))) return 2;
if (!(p = stbi_load_from_memory(p, n, &xn, &yn, &cn, 0))) return 3;
printf("<img src=\"%s\" width=\"%d\" height=\"%d\"\n"
" alt=\"[%s]\">\n",
argv[1], (xn + 1) >> 1, (yn + 1) >> 1, argv[1]);
return 0;
if (!NoDebug()) ShowCrashReports();
int i;
while ((i = getopt(argc, argv, "?huas01234")) != -1) {
switch (i) {
case '0':
case '1':
case '2':
case '3':
case '4':
scale = i - '0';
break;
case 's':
sizeonly = true;
break;
case 'a':
linktag = true;
break;
case 'u':
datauri = true;
break;
case '?':
case 'h':
PrintUsage(0, stdout);
default:
PrintUsage(1, stderr);
}
}
if (optind == argc) {
PrintUsage(1, stderr);
}
for (i = optind; i < argc; ++i) {
PrintImg(argv[i]);
}
}

View file

@ -121,7 +121,7 @@ void SpellChecker(void) {
printf("word: ");
fflush(stdout);
if (getline(&line, &linesize, stdin) > 0) {
query = strtolower(chomp(line));
query = strtolower(_chomp(line));
if (critbit0_contains(&words, query)) {
printf("ok\r\n");
} else {
@ -147,13 +147,13 @@ void SpellChecker(void) {
void LoadWords(void) {
CHECK_NOTNULL((f = fopen("/zip/usr/share/dict/words", "r")));
while (getline(&line, &linesize, f) > 0) {
critbit0_insert(&words, strtolower(chomp(line)));
critbit0_insert(&words, strtolower(_chomp(line)));
}
CHECK_NE(-1, fclose(f));
}
int main(int argc, char *argv[]) {
showcrashreports();
if (!NoDebug()) ShowCrashReports();
LoadWords();
SpellChecker();
return 0;

View file

@ -154,7 +154,7 @@ void editorSetStatusMessage(const char *fmt, ...);
* matches and keywords. The file name matches are used in order to match
* a given syntax with a given file name: if a match pattern starts with a
* dot, it is matched as the last past of the filename, for example ".c".
* Otherwise the pattern is just searched inside the filenme, like "Makefile").
* Otherwise the pattern is just searched inside the filename, like "Makefile").
*
* The list of keywords to highlight is just a list of words, however if they
* a trailing '|' character is added at the end, they are highlighted in
@ -249,7 +249,10 @@ fatal:
int editorReadKey(int64_t fd) {
int nread;
char c, seq[3];
if ((nread = read(fd, &c, 1)) == -1) exit(1);
do {
nread = read(fd, &c, 1);
if (nread == -1) exit(1);
} while (!nread);
while (1) {
switch (c) {
@ -390,7 +393,7 @@ int is_separator(int c) {
/* Return true if the specified row last char is part of a multi line comment
* that starts at this row or at one before, and does not end at the end
* of the row but spawns to the next row. */
* of the row but spans to the next row. */
int editorRowHasOpenComment(erow *row) {
if (row->hl && row->rsize && row->hl[row->rsize - 1] == HL_MLCOMMENT &&
(row->rsize < 2 || (row->render[row->rsize - 2] != '*' ||
@ -651,7 +654,7 @@ void editorFreeRow(erow *row) {
free(row->hl);
}
/* Remove the row at the specified position, shifting the remainign on the
/* Remove the row at the specified position, shifting the remaining on the
* top. */
void editorDelRow(int at) {
erow *row;
@ -667,7 +670,7 @@ void editorDelRow(int at) {
/* Turn the editor rows into a single heap-allocated string.
* Returns the pointer to the heap-allocated string and populate the
* integer pointed by 'buflen' with the size of the string, escluding
* integer pointed by 'buflen' with the size of the string, excluding
* the final nulterm. */
char *editorRowsToString(int *buflen) {
char *buf = NULL, *p;

23
examples/linenoise.c Normal file
View file

@ -0,0 +1,23 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "third_party/linenoise/linenoise.h"
int main(int argc, char *argv[]) {
char *line;
while ((line = linenoiseWithHistory("IN> ", "foo"))) {
fputs("OUT> ", stdout);
fputs(line, stdout);
fputs("\n", stdout);
free(line);
}
return 0;
}

20
examples/loadavg.c Normal file
View file

@ -0,0 +1,20 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/log/check.h"
#include "libc/stdio/stdio.h"
#include "libc/time/time.h"
int main(int argc, char *argv[]) {
double x[3];
CHECK_NE(-1, getloadavg(x, 3));
printf("%g %g %g\n", x[0], x[1], x[2]);
return 0;
}

View file

@ -26,7 +26,6 @@
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/ohmyplus/vector.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/stdio/stdio.h"
@ -43,6 +42,7 @@
#include "libc/zip.h"
#include "libc/zipos/zipos.internal.h"
#include "third_party/getopt/getopt.h"
#include "third_party/libcxx/vector"
#include "tool/viz/lib/knobs.h"
STATIC_YOINK("zip_uri_support");
@ -1673,7 +1673,7 @@ char* GetLine(void) {
static char* line;
static size_t linesize;
if (getline(&line, &linesize, stdin) > 0) {
return chomp(line);
return _chomp(line);
} else {
return NULL;
}
@ -1703,7 +1703,7 @@ int PlayGame(const char* romfile, const char* opt_tasfile) {
if ((ffplay = commandvenv("FFPLAY", "ffplay"))) {
devnull = open("/dev/null", O_WRONLY | O_CLOEXEC);
pipe2(pipefds, O_CLOEXEC);
if (!(playpid_ = vfork())) {
if (!(playpid_ = fork())) {
const char* const args[] = {
"ffplay", "-nodisp", "-loglevel", "quiet", "-fflags",
"nobuffer", "-ac", "1", "-ar", "1789773",

View file

@ -12,6 +12,7 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h"
#include "libc/dce.h"
#include "libc/log/check.h"
#include "libc/log/gdb.h"
#include "libc/log/log.h"
@ -152,7 +153,7 @@ void Draw(void) {
int main(int argc, char *argv[]) {
struct sigaction sa[2] = {{.sa_handler = OnShutdown},
{.sa_handler = OnInvalidate}};
showcrashreports();
if (!NoDebug()) ShowCrashReports();
Setup();
Enter();
GetTtySize();

View file

@ -7,94 +7,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/nt/process.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
const struct AuxiliaryValue {
const char *fmt;
long *id;
const char *name;
const char *description;
} kAuxiliaryValues[] = {
{"%012lx", &AT_EXECFD, "AT_EXECFD", "file descriptor of program"},
{"%012lx", &AT_PHDR, "AT_PHDR", "address of elf program headers"},
{"%012lx", &AT_PHENT, "AT_PHENT", "size of program header entry"},
{"%012lx", &AT_PHNUM, "AT_PHNUM", "number of program headers"},
{"%012lx", &AT_PAGESZ, "AT_PAGESZ", "system page size"},
{"%012lx", &AT_BASE, "AT_BASE", "base address of the program interpreter"},
{"%012lx", &AT_ENTRY, "AT_ENTRY", "entry address of executable"},
{"%012lx", &AT_NOTELF, "AT_NOTELF", "set if not an elf"},
{"%-12d", &AT_UID, "AT_UID", "real user id of thread"},
{"%-12d", &AT_EUID, "AT_EUID", "effective user id of thread"},
{"%-12d", &AT_GID, "AT_GID", "real group id of thread"},
{"%-12d", &AT_EGID, "AT_EGID", "effective group id of thread"},
{"%-12d", &AT_CLKTCK, "AT_CLKTCK", "frequency of times() counts"},
{"%012lx", &AT_OSRELDATE, "AT_OSRELDATE",
"freebsd release number, e.g. 1200086"},
{"%012lx", &AT_PLATFORM, "AT_PLATFORM",
"string identifying hardware platform"},
{"%012lx", &AT_DCACHEBSIZE, "AT_DCACHEBSIZE", "data cache block size"},
{"%012lx", &AT_ICACHEBSIZE, "AT_ICACHEBSIZE",
"instruction cache block size"},
{"%012lx", &AT_UCACHEBSIZE, "AT_UCACHEBSIZE", "unified cache block size"},
{"%012lx", &AT_SECURE, "AT_SECURE",
"for set{u,g}id binz & security blankets"},
{"%-12s", &AT_BASE_PLATFORM, "AT_BASE_PLATFORM",
"string identifying real platform"},
{"%012lx", &AT_RANDOM, "AT_RANDOM", "address of sixteen random bytes"},
{"%-12s", &AT_EXECFN, "AT_EXECFN", "pathname used to execute program"},
{"%012lx", &AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR",
"linux virtual dso page address"},
{"%012lx", &AT_FLAGS, "AT_FLAGS", "unused?"},
{"%012lx", &AT_HWCAP, "AT_HWCAP", "cpu stuff"},
{"%012lx", &AT_HWCAP2, "AT_HWCAP2", "more cpu stuff"},
};
const struct AuxiliaryValue *DescribeAuxv(unsigned long x) {
int i;
for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) {
if (x == *kAuxiliaryValues[i].id) {
return kAuxiliaryValues + i;
}
}
return NULL;
}
int main(int argc, char *argv[], char **envp) {
long key;
unsigned i;
unsigned long *auxp;
char fmt[64], **env;
struct AuxiliaryValue *auxinfo;
uint32_t varlen;
char16_t var[PATH_MAX];
printf("\nArguments:\n");
for (i = 0; i < __argc; ++i) {
printf(" ☼ %s\n", argv[i]);
}
printf("\nEnvironment:\n");
for (env = envp; *env; ++env) {
printf(" ☼ %s\n", *env);
}
printf("\nAuxiliary Values:\n");
for (auxp = __auxv; *auxp; auxp += 2) {
if ((auxinfo = DescribeAuxv(auxp[0]))) {
stpcpy(stpcpy(stpcpy(fmt, "%16s[%4ld] = "), auxinfo->fmt), " # %s\n");
printf(fmt, auxinfo->name, auxp[0], auxp[1], auxinfo->description);
} else {
printf("%16s[%4ld] = %012lx\n", "unknown", auxp[0], auxp[1]);
}
}
printf("\nSpecial Directories:\n");
printf(" ☼ kTmpPath = %`'s\n", kTmpPath);
printf(" ☼ kNtSystemDirectory = %`'s\n", kNtSystemDirectory);
printf(" ☼ kNtWindowsDirectory = %`'s\n", kNtWindowsDirectory);
printf(" ☼ program_executable_name = %`'s\n", program_executable_name);
return 0;
int main() {
__printargs("");
}

View file

@ -27,7 +27,7 @@ int main(int argc, char *argv[]) {
}
}
if (isprime) {
int64toarray_radix10(i, buf);
FormatInt64(buf, i);
fputs(buf, stdout);
fputc('\n', stdout);
if (k++ % 100 == 0) {

72
examples/rlimit.c Normal file
View file

@ -0,0 +1,72 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/rlimit.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/color.internal.h"
#include "libc/macros.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/rlim.h"
#include "libc/sysv/consts/rlimit.h"
/**
* @fileoverview tool for printing and changing system resource limits
*
* This is what you do if you want to not accidentally bomb your system
* with runaway code. If you haven't accidentally bombed your UNIX
* system before then you're not pushing it hard enough.
*/
static void SetLimit(int resource, uint64_t soft, uint64_t hard) {
struct rlimit old;
struct rlimit lim = {soft, hard};
if (resource == 127) return;
if (setrlimit(resource, &lim) == -1) {
if (!getrlimit(resource, &old)) {
lim.rlim_max = MIN(hard, old.rlim_max);
lim.rlim_cur = MIN(soft, lim.rlim_max);
if (!setrlimit(resource, &lim)) {
fprintf(stderr, "%sNOTE: SETRLIMIT(%s) DOWNGRADED TO {%,ld, %,ld}\n",
__strace_rlimit_name(resource), lim.rlim_cur, lim.rlim_max);
return;
}
}
fprintf(stderr, "ERROR: SETRLIMIT(%s, %,ld, %,ld) FAILED %m%n",
__strace_rlimit_name(resource), soft, hard);
exit(1);
}
}
int main(int argc, char *argv[]) {
int i, rc;
struct rlimit rlim;
// // example of how you might change the limits
// SetLimit(RLIMIT_CPU, 3, 33);
// SetLimit(RLIMIT_NPROC, 4, 128);
// SetLimit(RLIMIT_NOFILE, 32, 128);
// SetLimit(RLIMIT_SIGPENDING, 16, 1024);
// SetLimit(RLIMIT_AS, 8 * 1024 * 1024, 1l * 1024 * 1024 * 1024);
// SetLimit(RLIMIT_RSS, 8 * 1024 * 1024, 1l * 1024 * 1024 * 1024);
// SetLimit(RLIMIT_DATA, 8 * 1024 * 1024, 1l * 1024 * 1024 * 1024);
// SetLimit(RLIMIT_FSIZE, 8 * 1000 * 1000, 1l * 1000 * 1000 * 1000);
for (i = 0; i < RLIM_NLIMITS; ++i) {
rc = getrlimit(i, &rlim);
printf("SETRLIMIT(%-20s, %,16ld, %,16ld) → %d %s\n",
__strace_rlimit_name(i), rlim.rlim_cur, rlim.rlim_max, rc,
!rc ? "" : strerror(errno));
}
return 0;
}

View file

@ -101,7 +101,7 @@ int main(int argc, char *argv[]) {
sigaddset(&chldmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
ts1 = nowl();
CHECK_NE(-1, (pid = vfork()));
CHECK_NE(-1, (pid = fork()));
if (!pid) {
sigaction(SIGINT, &dflt, 0);
sigaction(SIGQUIT, &dflt, 0);

View file

@ -7,8 +7,9 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/fmt/conv.h"
#include "libc/stdio/stdio.h"
#include "libc/fmt/itoa.h"
/**
* @fileoverview Prints sequence of numbers.
@ -16,6 +17,7 @@
int main(int argc, char *argv[]) {
long a, b, i;
char buf[21], *p;
switch (argc) {
case 2:
a = 1;
@ -29,6 +31,9 @@ int main(int argc, char *argv[]) {
return 1;
}
for (i = a; i <= b; ++i) {
printf("%ld\n", i);
p = buf;
p = FormatInt64(p, i);
*p++ = '\n';
write(1, buf, p - buf);
}
}

72
examples/setitimer.c Normal file
View file

@ -0,0 +1,72 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/ucontext.h"
#include "libc/log/check.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/itimer.h"
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
#include "libc/time/time.h"
volatile bool gotalrm;
void OnSigAlrm(int sig, siginfo_t *si, ucontext_t *ctx) {
gotalrm = true;
}
int main() {
//////////////////////////////////////////////////////////////////////////////
printf("first tutorial: set singleshot alarm for 1.5 seconds from now\n");
// setup alarm in 1.5 seconds
// this timer tears itself down once it's handled
struct itimerval shot = {{0, 0}, {1, 500000}};
struct sigaction handler = {.sa_sigaction = OnSigAlrm,
.sa_flags = SA_RESETHAND | SA_SIGINFO};
CHECK_EQ(0, sigaction(SIGALRM, &handler, 0));
CHECK_EQ(0, setitimer(ITIMER_REAL, &shot, 0));
// wait for alarm
pause();
printf("got singleshot alarm!\n\n");
//////////////////////////////////////////////////////////////////////////////
printf("second tutorial: interval timer\n");
// setup timer every 1.5 seconds
struct sigaction oldalrm;
struct sigaction sigalrm = {.sa_sigaction = OnSigAlrm,
.sa_flags = SA_SIGINFO};
CHECK_EQ(0, sigaction(SIGALRM, &sigalrm, &oldalrm));
struct itimerval oldtimer;
struct itimerval timer = {{1, 500000}, {1, 500000}};
CHECK_EQ(0, setitimer(ITIMER_REAL, &timer, &oldtimer));
// wait for three timeouts
int i = 0;
int n = 3;
while (i < n) {
pause();
if (gotalrm) {
++i;
printf("got timeout %d out of %d\n", i, n);
gotalrm = false;
}
}
// teardown timer
CHECK_EQ(0, setitimer(ITIMER_REAL, &oldtimer, 0));
CHECK_EQ(0, sigaction(SIGALRM, &oldalrm, 0));
}

View file

@ -47,8 +47,8 @@ void PrintMetric(const char *name, long double d) {
mils = fmodl(d * 1000, 1000);
mics = fmodl(d * 1000000, 1000);
p = stpcpy(p, name), *p++ = '\t';
p += int64toarray_radix10(mins, p), *p++ = 'm';
p += int64toarray_radix10(secs, p), *p++ = '.';
p = FormatInt64(p, mins), *p++ = 'm';
p = FormatInt64(p, secs), *p++ = '.';
*p++ = '0' + mils / 100;
*p++ = '0' + mils / 10 % 10;
*p++ = '0' + mils % 10;
@ -69,7 +69,7 @@ int main(int argc, char *argv[]) {
long double real;
char exebuf[PATH_MAX];
if (argc >= 2) {
if ((exepath = commandv(argv[1], exebuf))) {
if ((exepath = commandv(argv[1], exebuf, sizeof(exebuf)))) {
real = nowl();
argv[1] = exepath;
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {

View file

@ -20,7 +20,7 @@
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; ++i) {
if (touch(argv[i], 0644) == -1) {
if (touch(argv[i], 0666) == -1) {
fprintf(stderr, "ERROR: %s: %s\n", argv[i], strerror(errno));
exit(1);
}

View file

@ -27,6 +27,7 @@
#include "libc/x/x.h"
#define CTRL(C) ((C) ^ 0b01000000)
#define WRITE(FD, SLIT) write(FD, SLIT, strlen(SLIT))
#define ENABLE_SAFE_PASTE "\e[?2004h"
#define ENABLE_MOUSE_TRACKING "\e[?1000;1002;1015;1006h"
#define DISABLE_MOUSE_TRACKING "\e[?1000;1002;1015;1006l"
@ -46,7 +47,7 @@ void onkilled(int sig) {
}
void restoretty(void) {
write(1, DISABLE_MOUSE_TRACKING, strlen(DISABLE_MOUSE_TRACKING));
WRITE(1, DISABLE_MOUSE_TRACKING);
ioctl(1, TCSETS, &oldterm);
}
@ -72,9 +73,9 @@ int rawmode(void) {
t.c_cflag |= CS8;
t.c_iflag |= IUTF8;
ioctl(1, TCSETS, &t);
write(1, ENABLE_SAFE_PASTE, strlen(ENABLE_SAFE_PASTE));
write(1, ENABLE_MOUSE_TRACKING, strlen(ENABLE_MOUSE_TRACKING));
write(1, PROBE_DISPLAY_SIZE, strlen(PROBE_DISPLAY_SIZE));
WRITE(1, ENABLE_SAFE_PASTE);
WRITE(1, ENABLE_MOUSE_TRACKING);
WRITE(1, PROBE_DISPLAY_SIZE);
return 0;
}

View file

@ -16,12 +16,22 @@
#include "libc/sysv/consts/sig.h"
#include "third_party/xed/x86.h"
/**
* @fileoverview How to change CPU state on signal delivery
*
* This program redefines division by zero so that it has a definition.
* The definition is the meaning of life, the universe, and everything.
* Normally crash signals like `SIGSEGV`, `SIGILL`, and `SIGFPE` aren't
* recoverable. This example shows how it actually can be done with Xed
* and this example should work on all supported platforms even Windows
*/
void handler(int sig, siginfo_t *si, ucontext_t *ctx) {
struct XedDecodedInst xedd;
xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64);
xed_instruction_length_decode(&xedd, (void *)ctx->uc_mcontext.rip, 15);
ctx->uc_mcontext.rip += xedd.length;
ctx->uc_mcontext.rax = 42;
ctx->uc_mcontext.rax = 42; // set the DIV result registers rdx:rax
ctx->uc_mcontext.rdx = 0;
}

24
examples/uname.c Normal file
View file

@ -0,0 +1,24 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/utsname.h"
#include "libc/stdio/stdio.h"
int main(int argc, char *argv[]) {
struct utsname names;
if (uname(&names)) return 1;
printf("%-10s %s\n", "sysname", names.sysname);
printf("%-10s %s\n", "nodename", names.nodename);
printf("%-10s %s\n", "release", names.release);
printf("%-10s %s\n", "version", names.version);
printf("%-10s %s\n", "machine", names.machine);
printf("%-10s %s\n", "domainname", names.domainname);
return 0;
}

View file

@ -5731,7 +5731,7 @@ retry:
linenoiseSetFreeHintsCallback(free);
linenoiseSetHintsCallback(ShellHint);
linenoiseSetCompletionCallback(ShellCompletion);
if ((p = linenoiseWithHistory("$ ", "unbourne"))) {
if ((p = linenoiseWithHistory(">: ", "unbourne"))) {
nr = min(strlen(p), IBUFSIZ - 2);
memcpy(buf, p, nr);
buf[nr++] = '\n';

View file

@ -55,8 +55,8 @@ int fgethex(FILE *f) {
}
int main(int argc, char *argv[argc]) {
int err;
unsigned c, i, j, l;
enum XedError err;
struct XedDecodedInst xedd;
unsigned char buf[XED_MAX_INSTRUCTION_BYTES];
memset(buf, 0, sizeof(buf));

View file

@ -8,10 +8,10 @@ COSMOPOLITAN_C_START_
void *bsearch(const void *, const void *, size_t, size_t,
int cmp(const void *, const void *))
paramsnonnull() nothrow nosideeffect;
paramsnonnull() dontthrow nosideeffect;
void *bsearch_r(const void *, const void *, size_t, size_t,
int cmp(const void *, const void *, void *), void *)
paramsnonnull((1, 2, 5)) nothrow nosideeffect;
paramsnonnull((1, 2, 5)) dontthrow nosideeffect;
void djbsort(int32_t *, size_t);
void qsort(void *, size_t, size_t, int (*)(const void *, const void *))
paramsnonnull();
@ -19,9 +19,9 @@ void qsort_r(void *, size_t, size_t,
int cmp(const void *, const void *, void *), void *arg)
paramsnonnull((1, 4));
int tarjan(int, const int (*)[2], int, int[], int[], int *)
paramsnonnull((2, 4)) nocallback nothrow;
paramsnonnull((2, 4)) nocallback dontthrow;
#define __algalloc returnspointerwithnoaliases nothrow nocallback nodiscard
#define __algalloc returnspointerwithnoaliases dontthrow nocallback dontdiscard
char *replacestr(const char *, const char *, const char *)
paramsnonnull() __algalloc;

View file

@ -14,7 +14,7 @@ forceinline void *bisect(const void *k, const void *data, size_t n, size_t size,
r = n - 1;
p = data;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1);
c = cmp(k, p + m * size, arg);
if (c > 0) {
l = m + 1;

View file

@ -11,15 +11,15 @@ struct critbit0 {
size_t count;
};
bool critbit0_contains(struct critbit0 *, const char *) nothrow nosideeffect
bool critbit0_contains(struct critbit0 *, const char *) dontthrow nosideeffect
paramsnonnull();
bool critbit0_insert(struct critbit0 *, const char *) paramsnonnull();
bool critbit0_delete(struct critbit0 *, const char *) nothrow paramsnonnull();
void critbit0_clear(struct critbit0 *) nothrow paramsnonnull();
bool critbit0_delete(struct critbit0 *, const char *) dontthrow paramsnonnull();
void critbit0_clear(struct critbit0 *) dontthrow paramsnonnull();
char *critbit0_get(struct critbit0 *, const char *);
intptr_t critbit0_allprefixed(struct critbit0 *, const char *,
intptr_t (*)(const char *, void *), void *)
paramsnonnull((1, 2, 3)) nothrow;
paramsnonnull((1, 2, 3)) dontthrow;
bool critbit0_emplace(struct critbit0 *, char *, size_t) paramsnonnull();
COSMOPOLITAN_C_END_

View file

@ -12,7 +12,9 @@ void __assert_fail(const char *, const char *, int) hidden wontreturn relegated;
((void)((EXPR) || (__assert_fail(#EXPR, __FILE__, __LINE__), 0)))
#endif
#ifndef __cplusplus
#define static_assert _Static_assert
#endif
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

34
libc/bits/asmflag.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef COSMOPOLITAN_LIBC_BITS_ASMFLAG_H_
#define COSMOPOLITAN_LIBC_BITS_ASMFLAG_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/*
* Constraints for virtual machine flags.
* @note we beseech clang devs for flag constraints
*/
#ifdef __GCC_ASM_FLAG_OUTPUTS__ /* GCC6+ CLANG10+ */
#define CFLAG_CONSTRAINT "=@ccc"
#define CFLAG_ASM(OP) OP
#define ZFLAG_CONSTRAINT "=@ccz"
#define ZFLAG_ASM(OP) OP
#define OFLAG_CONSTRAINT "=@cco"
#define OFLAG_ASM(OP) OP
#define SFLAG_CONSTRAINT "=@ccs"
#define SFLAG_ASM(SP) SP
#define ABOVE_CONSTRAINT "=@cca" /* i.e. !ZF && !CF */
#define ABOVEFLAG_ASM(OP) OP
#else
#define CFLAG_CONSTRAINT "=q"
#define CFLAG_ASM(OP) OP "\n\tsetc\t%b0"
#define ZFLAG_CONSTRAINT "=q"
#define ZFLAG_ASM(OP) OP "\n\tsetz\t%b0"
#define OFLAG_CONSTRAINT "=q"
#define OFLAG_ASM(OP) OP "\n\tseto\t%b0"
#define SFLAG_CONSTRAINT "=q"
#define SFLAG_ASM(SP) OP "\n\tsets\t%b0"
#define ABOVE_CONSTRAINT "=@cca"
#define ABOVEFLAG_ASM(OP) OP "\n\tseta\t%b0"
#endif
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_BITS_ASMFLAG_H_ */

View file

@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_BITS_ATOMIC_H_
#define COSMOPOLITAN_LIBC_BITS_ATOMIC_H_
#include "libc/bits/bits.h"
#include "libc/intrin/lockcmpxchg.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -31,8 +32,8 @@ COSMOPOLITAN_C_START_
})
#define atomic_init(PTR, VAL) atomic_store(PTR, VAL)
#define atomic_exchange(PTR, VAL) lockxchg(PTR, &(VAL))
#define atomic_compare_exchange_strong(X, Y, Z) lockcmpxchg(X, Y, Z)
#define atomic_compare_exchange_weak(X, Y, Z) lockcmpxchg(X, Y, Z)
#define atomic_compare_exchange_strong(X, Y, Z) _lockcmpxchg(X, Y, Z)
#define atomic_compare_exchange_weak(X, Y, Z) _lockcmpxchg(X, Y, Z)
#define atomic_load_explicit(PTR, ORDER) atomic_load(PTR)
#define atomic_store_explicit(PTR, VAL, ORDER) atomic_store(PTR, VAL)
#define atomic_flag_clear_explicit(PTR, ORDER) atomic_store(PTR, 0)

45
libc/bits/bitop.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef COSMOPOLITAN_LIBC_BITS_BITOP_H_
#define COSMOPOLITAN_LIBC_BITS_BITOP_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define bts(MEM, BIT) __BitOp("bts", BIT, MEM) /** bit test and set */
#define btr(MEM, BIT) __BitOp("btr", BIT, MEM) /** bit test and reset */
#define btc(MEM, BIT) __BitOp("btc", BIT, MEM) /** bit test and complement */
#define lockbts(MEM, BIT) __BitOp("lock bts", BIT, MEM)
#define lockbtr(MEM, BIT) __BitOp("lock btr", BIT, MEM)
#define lockbtc(MEM, BIT) __BitOp("lock btc", BIT, MEM)
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define __BitOp(OP, BIT, MEM) \
({ \
bool OldBit; \
if (__builtin_constant_p(BIT)) { \
asm(CFLAG_ASM(OP "%z1\t%2,%1") \
: CFLAG_CONSTRAINT(OldBit), \
"+m"((MEM)[(BIT) / (sizeof((MEM)[0]) * CHAR_BIT)]) \
: "J"((BIT) % (sizeof((MEM)[0]) * CHAR_BIT)) \
: "cc"); \
} else if (sizeof((MEM)[0]) == 2) { \
asm(CFLAG_ASM(OP "\t%w2,%1") \
: CFLAG_CONSTRAINT(OldBit), "+m"((MEM)[0]) \
: "r"(BIT) \
: "cc"); \
} else if (sizeof((MEM)[0]) == 4) { \
asm(CFLAG_ASM(OP "\t%k2,%1") \
: CFLAG_CONSTRAINT(OldBit), "+m"((MEM)[0]) \
: "r"(BIT) \
: "cc"); \
} else if (sizeof((MEM)[0]) == 8) { \
asm(CFLAG_ASM(OP "\t%q2,%1") \
: CFLAG_CONSTRAINT(OldBit), "+m"((MEM)[0]) \
: "r"(BIT) \
: "cc"); \
} \
OldBit; \
})
#endif /* __GNUC__ && !__STRICT_ANSI__ */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_BITS_BITOP_H_ */

View file

@ -21,11 +21,6 @@ unsigned long roundup2pow(unsigned long) libcesque pureconst;
unsigned long roundup2log(unsigned long) libcesque pureconst;
unsigned long rounddown2pow(unsigned long) libcesque pureconst;
unsigned long hamming(unsigned long, unsigned long) pureconst;
intptr_t lockxchg(void *, void *, size_t);
bool cmpxchg(void *, intptr_t, intptr_t, size_t);
bool lockcmpxchg(void *, intptr_t, intptr_t, size_t);
intptr_t atomic_load(void *, size_t);
intptr_t atomic_store(void *, intptr_t, size_t);
unsigned bextra(const unsigned *, size_t, char);
/*───────────────────────────────────────────────────────────────────────────│─╗
@ -136,84 +131,6 @@ unsigned bextra(const unsigned *, size_t, char);
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
/*
* Constraints for virtual machine flags.
* @note we beseech clang devs for flag constraints
*/
#ifdef __GCC_ASM_FLAG_OUTPUTS__ /* GCC6+ CLANG10+ */
#define CFLAG_CONSTRAINT "=@ccc"
#define CFLAG_ASM(OP) OP
#define ZFLAG_CONSTRAINT "=@ccz"
#define ZFLAG_ASM(OP) OP
#define OFLAG_CONSTRAINT "=@cco"
#define OFLAG_ASM(OP) OP
#define SFLAG_CONSTRAINT "=@ccs"
#define SFLAG_ASM(SP) SP
#define ABOVE_CONSTRAINT "=@cca" /* i.e. !ZF && !CF */
#define ABOVEFLAG_ASM(OP) OP
#else
#define CFLAG_CONSTRAINT "=q"
#define CFLAG_ASM(OP) OP "\n\tsetc\t%b0"
#define ZFLAG_CONSTRAINT "=q"
#define ZFLAG_ASM(OP) OP "\n\tsetz\t%b0"
#define OFLAG_CONSTRAINT "=q"
#define OFLAG_ASM(OP) OP "\n\tseto\t%b0"
#define SFLAG_CONSTRAINT "=q"
#define SFLAG_ASM(SP) OP "\n\tsets\t%b0"
#define ABOVE_CONSTRAINT "=@cca"
#define ABOVEFLAG_ASM(OP) OP "\n\tseta\t%b0"
#endif
/**
* Reads scalar from memory w/ one operation.
*
* @param MEM is alignas(𝑘) uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @return *(MEM)
* @note defeats compiler load tearing optimizations
* @note alignas(𝑘) is implied if compiler knows type
* @note alignas(𝑘) only avoids multi-core / cross-page edge cases
* @see Intel's Six-Thousand Page Manual V.3A §8.2.3.1
* @see atomic_store()
*/
#define atomic_load(MEM) \
({ \
autotype(MEM) Mem = (MEM); \
typeof(*Mem) Reg; \
asm("mov\t%1,%0" : "=r"(Reg) : "m"(*Mem)); \
Reg; \
})
/**
* Saves scalar to memory w/ one operation.
*
* This is guaranteed to happen in either one or zero operations,
* depending on whether or not it's possible for *(MEM) to be read
* afterwards. This macro only forbids compiler from using >1 ops.
*
* @param MEM is alignas(𝑘) uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @param VAL is uint𝑘_t w/ better encoding for immediates (constexpr)
* @return VAL
* @note alignas(𝑘) on nexgen32e only needed for end of page gotcha
* @note alignas(𝑘) is implied if compiler knows type
* @note needed to defeat store tearing optimizations
* @see Intel Six-Thousand Page Manual Manual V.3A §8.2.3.1
* @see atomic_load()
*/
#define atomic_store(MEM, VAL) \
({ \
autotype(VAL) Val = (VAL); \
typeof(&Val) Mem = (MEM); \
asm("mov%z1\t%1,%0" : "=m"(*Mem) : "r"(Val)); \
Val; \
})
#define bts(MEM, BIT) __BitOp("bts", BIT, MEM) /** bit test and set */
#define btr(MEM, BIT) __BitOp("btr", BIT, MEM) /** bit test and reset */
#define btc(MEM, BIT) __BitOp("btc", BIT, MEM) /** bit test and complement */
#define lockbts(MEM, BIT) __BitOp("lock bts", BIT, MEM)
#define lockbtr(MEM, BIT) __BitOp("lock btr", BIT, MEM)
#define lockbtc(MEM, BIT) __BitOp("lock btc", BIT, MEM)
#define lockinc(MEM) __ArithmeticOp1("lock inc", MEM)
#define lockdec(MEM) __ArithmeticOp1("lock dec", MEM)
#define locknot(MEM) __ArithmeticOp1("lock not", MEM)
@ -225,66 +142,6 @@ unsigned bextra(const unsigned *, size_t, char);
#define lockandeq(MEM, VAL) __ArithmeticOp2("lock and", VAL, MEM)
#define lockoreq(MEM, VAL) __ArithmeticOp2("lock or", VAL, MEM)
/**
* Exchanges *MEMORY into *LOCALVAR w/ one operation.
*
* @param MEMORY is uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @param LOCALVAR is uint𝑘_t[hasatleast 1]
* @return LOCALVAR[0]
* @see xchg()
*/
#define lockxchg(MEMORY, LOCALVAR) \
({ \
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
*(LOCALVAR); \
})
/**
* Compares and exchanges.
*
* @param IFTHING is uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @return true if value was exchanged, otherwise false
* @see lockcmpxchg()
*/
#define cmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
bool DidIt; \
autotype(IFTHING) IfThing = (IFTHING); \
typeof(*IfThing) IsEqualToMe = (ISEQUALTOME); \
typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME); \
asm volatile(ZFLAG_ASM("cmpxchg\t%3,%1") \
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
: "r"(ReplaceItWithMe) \
: "cc"); \
DidIt; \
})
/**
* Compares and exchanges w/ one operation.
*
* @param IFTHING is uint𝑘_t[hasatleast 1] where 𝑘 {8,16,32,64}
* @return true if value was exchanged, otherwise false
* @see lockcmpxchg()
*/
#define lockcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
({ \
bool DidIt; \
autotype(IFTHING) IfThing = (IFTHING); \
typeof(*IfThing) IsEqualToMe = (ISEQUALTOME); \
typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME); \
asm volatile(ZFLAG_ASM("lock cmpxchg\t%3,%1") \
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
: "r"(ReplaceItWithMe) \
: "cc"); \
DidIt; \
})
#define IsAddressCanonicalForm(P) \
({ \
intptr_t p2 = (intptr_t)(P); \
(0xffff800000000000l <= p2 && p2 <= 0x00007fffffffffffl); \
})
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § bits » implementation details
*/
@ -301,44 +158,6 @@ unsigned bextra(const unsigned *, size_t, char);
MEM; \
})
#define __BitOp(OP, BIT, MEM) \
({ \
bool OldBit; \
if (__builtin_constant_p(BIT)) { \
asm(CFLAG_ASM(OP "%z1\t%2,%1") \
: CFLAG_CONSTRAINT(OldBit), \
"+m"((MEM)[(BIT) / (sizeof((MEM)[0]) * CHAR_BIT)]) \
: "J"((BIT) % (sizeof((MEM)[0]) * CHAR_BIT)) \
: "cc"); \
} else if (sizeof((MEM)[0]) == 2) { \
asm(CFLAG_ASM(OP "\t%w2,%1") \
: CFLAG_CONSTRAINT(OldBit), "+m"((MEM)[0]) \
: "r"(BIT) \
: "cc"); \
} else if (sizeof((MEM)[0]) == 4) { \
asm(CFLAG_ASM(OP "\t%k2,%1") \
: CFLAG_CONSTRAINT(OldBit), "+m"((MEM)[0]) \
: "r"(BIT) \
: "cc"); \
} else if (sizeof((MEM)[0]) == 8) { \
asm(CFLAG_ASM(OP "\t%q2,%1") \
: CFLAG_CONSTRAINT(OldBit), "+m"((MEM)[0]) \
: "r"(BIT) \
: "cc"); \
} \
OldBit; \
})
#else
#define cmpxchg(MEM, CMP, VAL) \
cmpxchg(MEM, (intptr_t)(CMP), (intptr_t)(VAL), sizeof(*(MEM)))
#define lockcmpxchg(MEM, CMP, VAL) \
lockcmpxchg(MEM, (intptr_t)(CMP), (intptr_t)(VAL), sizeof(*(MEM)))
#define lockxchg(MEM, VAR) \
lockxchg(MEM, VAR, sizeof(*(MEM)) / (sizeof(*(MEM)) == sizeof(*(VAR))))
#define atomic_store(MEM, VAL) \
atomic_store(MEM, VAL, sizeof(*(MEM)) / (sizeof(*(MEM)) == sizeof(*(VAL))))
#define atomic_load(MEM) atomic_load(MEM, sizeof(*(MEM)))
#endif /* __GNUC__ && !__STRICT_ANSI__ */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

32
libc/bits/midpoint.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef COSMOPOLITAN_LIBC_BITS_MIDPOINT_H_
#define COSMOPOLITAN_LIBC_BITS_MIDPOINT_H_
#include "libc/assert.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86__)
/**
* Computes `(a + b) / 2` assuming unsigned.
*
* This implementation is the fastest on AMD Zen architecture.
*/
#define _midpoint(a, b) \
({ \
typeof((a) + (b)) a_ = (a); \
typeof(a_) b_ = (b); \
assert(a_ >= 0); \
assert(b_ >= 0); \
asm("add\t%1,%0\n\t" \
"rcr\t%0" \
: "+r"(a_) \
: "r"(b_)); \
a_; \
})
#else
/**
* Computes `(a + b) / 2` assuming unsigned.
*/
#define _midpoint(a, b) (((a) & (b)) + ((a) ^ (b)) / 2)
#endif /* __GNUC__ && !__STRICT_ANSI__ && x86 */
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_BITS_MIDPOINT_H_ */

View file

@ -19,7 +19,7 @@
#include "libc/calls/math.h"
/**
* Adds two microsecond timestamps.
* Adds two nanosecond timestamps.
*/
struct timespec AddTimespec(struct timespec x, struct timespec y) {
x.tv_sec += y.tv_sec;

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
@ -41,7 +41,7 @@ int atfork(void *fn, void *arg) {
for (;;) {
i = g_atfork.i;
if (i == ARRAYLEN(g_atfork.p)) return enomem();
if (cmpxchg(&g_atfork.i, i, i + 1)) {
if (_cmpxchg(&g_atfork.i, i, i + 1)) {
g_atfork.p[i] = (struct AtForkCallback){.fn = fn, .arg = arg};
return 0;
}

View file

@ -17,6 +17,10 @@
#include "libc/sysv/consts/s.h"
#include "libc/sysv/consts/sig.h"
#define _POSIX_VERSION 200809L
#define _POSIX2_VERSION _POSIX_VERSION
#define _XOPEN_VERSION 700
#define EOF -1 /* end of file */
#define WEOF -1u /* end of file (multibyte) */
#define _IOFBF 0 /* fully buffered */
@ -48,14 +52,14 @@
#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode)&S_IFMT) == S_IFSOCK)
#define WCOREDUMP(s) ((s)&0x80)
#define WEXITSTATUS(s) (((s)&0xff00) >> 8)
#define WCOREDUMP(s) (0x80 & (s))
#define WEXITSTATUS(s) ((0xff00 & (s)) >> 8)
#define WIFCONTINUED(s) ((s) == 0xffff)
#define WIFEXITED(s) (!WTERMSIG(s))
#define WIFSIGNALED(s) (((s)&0xffff) - 1u < 0xffu)
#define WIFSTOPPED(s) ((short)((((s)&0xffff) * 0x10001) >> 8) > 0x7f00)
#define WIFSIGNALED(s) ((0xffff & (s)) - 1u < 0xffu)
#define WIFSTOPPED(s) ((short)(((0xffff & (s)) * 0x10001) >> 8) > 0x7f00)
#define WSTOPSIG(s) WEXITSTATUS(s)
#define WTERMSIG(s) ((s)&0x7f)
#define WTERMSIG(s) (127 & (s))
#define W_STOPCODE(s) ((s) << 8 | 0177)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
@ -66,8 +70,8 @@ COSMOPOLITAN_C_START_
typedef int sig_atomic_t;
DIR *fdopendir(int) nodiscard;
DIR *opendir(const char *) nodiscard;
DIR *fdopendir(int) dontdiscard;
DIR *opendir(const char *) dontdiscard;
bool fileexists(const char *);
bool isdirectory(const char *);
bool isexecutable(const char *);
@ -75,19 +79,18 @@ bool isregularfile(const char *);
bool issymlink(const char *);
bool32 isatty(int) nosideeffect;
bool32 ischardev(int) nosideeffect;
char *commandv(const char *, char[hasatleast PATH_MAX]);
char *get_current_dir_name(void) nodiscard;
char *commandv(const char *, char *, size_t);
char *get_current_dir_name(void) dontdiscard;
char *getcwd(char *, size_t);
char *realpath(const char *, char *);
char *replaceuser(const char *) nodiscard;
char *replaceuser(const char *) dontdiscard;
char *ttyname(int);
int access(const char *, int) nothrow;
int access(const char *, int) dontthrow;
int arch_prctl();
int chdir(const char *);
int chmod(const char *, uint32_t);
int chown(const char *, uint32_t, uint32_t);
int chroot(const char *);
int clone(int (*)(void *), void *, int, void *, ...);
int close(int);
int closedir(DIR *);
int creat(const char *, uint32_t);
@ -105,7 +108,7 @@ int execvpe(const char *, char *const[], char *const[]);
int faccessat(int, const char *, int, uint32_t);
int fadvise(int, uint64_t, uint64_t, int);
int fchdir(int);
int fchmod(int, uint32_t) nothrow;
int fchmod(int, uint32_t) dontthrow;
int fchmodat(int, const char *, uint32_t, int);
int fchown(int, uint32_t, uint32_t);
int fchownat(int, const char *, uint32_t, uint32_t, int);
@ -120,16 +123,24 @@ int fsync(int);
int ftruncate(int, int64_t);
int getdents(unsigned, void *, unsigned, long *);
int getdomainname(char *, size_t);
int getegid(void) nosideeffect;
int geteuid(void) nosideeffect;
int getgid(void) nosideeffect;
int gethostname(char *, size_t);
int getloadavg(double *, int);
int getpgid(int);
int getpgrp(void) nosideeffect;
int getpid(void);
int getppid(void);
int getpriority(int, unsigned);
int getrlimit(int, struct rlimit *);
int getrusage(int, struct rusage *);
int getsid(int) nosideeffect;
int gettid(void);
int getuid(void) nosideeffect;
int kill(int, int);
int killpg(int, int);
int link(const char *, const char *) nothrow;
int link(const char *, const char *) dontthrow;
int linkat(int, const char *, int, const char *, int);
int lstat(const char *, struct stat *);
int lutimes(const char *, const struct timeval[2]);
@ -147,7 +158,6 @@ int munlock(const void *, size_t);
int munlockall(void);
int nice(int);
int open(const char *, int, ...);
int openanon(char *, unsigned);
int openat(int, const char *, int, ...);
int pause(void);
int personality(uint64_t);
@ -155,7 +165,7 @@ int pipe(int[hasatleast 2]);
int pipe2(int[hasatleast 2], int);
int posix_fadvise(int, uint64_t, uint64_t, int);
int posix_madvise(void *, uint64_t, int);
int prctl();
int prctl(int, ...);
int raise(int);
int reboot(int);
int remove(const char *);
@ -166,18 +176,22 @@ int rmdir(const char *);
int sched_getaffinity(int, uint64_t, void *);
int sched_setaffinity(int, uint64_t, const void *);
int sched_yield(void);
int seccomp(unsigned, unsigned, void *);
int setegid(uint32_t);
int seteuid(uint32_t);
int setgid(uint32_t);
int setgid(int);
int setpgid(int, int);
int setpgrp(void);
int setpriority(int, unsigned, int);
int setregid(uint32_t, uint32_t);
int setresgid(uint32_t, uint32_t, uint32_t);
int setresuid(uint32_t, uint32_t, uint32_t);
int getresgid(uint32_t *, uint32_t *, uint32_t *);
int getresuid(uint32_t *, uint32_t *, uint32_t *);
int setreuid(uint32_t, uint32_t);
int setrlimit(int, const struct rlimit *);
int setsid(void);
int setuid(uint32_t);
int setuid(int);
int sigignore(int);
int siginterrupt(int, int);
int sigprocmask(int, const struct sigset *, struct sigset *);
@ -192,6 +206,7 @@ int sysinfo(struct sysinfo *);
int touch(const char *, uint32_t);
int truncate(const char *, uint64_t);
int ttyname_r(int, char *, size_t);
int umask(int);
int uname(struct utsname *);
int unlink(const char *);
int unlink_s(const char **);
@ -202,13 +217,13 @@ int wait3(int *, int, struct rusage *);
int wait4(int, int *, int, struct rusage *);
int waitpid(int, int *, int);
intptr_t syscall(int, ...);
long ptrace(int, int, void *, void *);
long ptrace(int, ...);
long telldir(DIR *);
long times(struct tms *);
size_t GetFileSize(const char *);
size_t getfiledescriptorsize(int);
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t getfiledescriptorsize(int);
ssize_t lseek(int, int64_t, unsigned);
ssize_t pread(int, void *, size_t, int64_t);
ssize_t preadv(int, struct iovec *, int, int64_t);
@ -222,16 +237,12 @@ ssize_t splice(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t);
ssize_t write(int, const void *, size_t);
struct dirent *readdir(DIR *);
uint32_t getegid(void) nosideeffect;
uint32_t geteuid(void) nosideeffect;
uint32_t getgid(void) nosideeffect;
uint32_t getpgrp(void) nosideeffect;
uint32_t getsid(int) nosideeffect;
uint32_t gettid(void) nosideeffect;
uint32_t getuid(void) nosideeffect;
uint32_t umask(int32_t);
void rewinddir(DIR *);
void sync(void);
int pledge(const char *, const char *);
int clone(int (*)(void *), void *, size_t, int, void *, int *, void *, size_t,
int *);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § system calls » formatting

View file

@ -44,7 +44,9 @@ LIBC_CALLS_A_DIRECTDEPS = \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_POWERPROF \
LIBC_NT_PDH \
LIBC_NT_PSAPI \
LIBC_NT_POWRPROF \
LIBC_NT_WS2_32 \
LIBC_STR \
LIBC_STUBS \
@ -63,8 +65,12 @@ $(LIBC_CALLS_A).pkg: \
$(LIBC_CALLS_A_OBJS) \
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/calls/vdsofunc.greg.o \
o/$(MODE)/libc/calls/directmap.o \
o/$(MODE)/libc/calls/directmap-nt.o \
o/$(MODE)/libc/calls/raise.o: \
OVERRIDE_COPTS += \
-ffreestanding \
$(NO_MAGIC)
o/$(MODE)/libc/calls/termios2linux.o \
@ -78,6 +84,9 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: \
-O3
# TODO(jart): make va_arg optimize well in default mode
o//libc/calls/open.o \
o//libc/calls/openat.o \
o//libc/calls/prctl.o \
o//libc/calls/ioctl.o \
o//libc/calls/ioctl_default.o \
o//libc/calls/ioctl_fioclex-nt.o \
@ -96,11 +105,18 @@ o//libc/calls/fcntl.o: \
OVERRIDE_CFLAGS += \
-Os
# must use alloca() or path_max*2*2
o/$(MODE)/libc/calls/execl.o \
o/$(MODE)/libc/calls/execle.o \
o/$(MODE)/libc/calls/execlp.o \
o/$(MODE)/libc/calls/copyfile.o \
o/$(MODE)/libc/calls/execve-nt.o \
o/$(MODE)/libc/calls/linkat-nt.o \
o/$(MODE)/libc/calls/renameat-nt.o \
o/$(MODE)/libc/calls/execve-sysv.o \
o/$(MODE)/libc/calls/symlinkat-nt.o \
o/$(MODE)/libc/calls/readlinkat-nt.o \
o/$(MODE)/libc/calls/describeopenflags.greg.o \
o/$(MODE)/libc/calls/mkntenvblock.o: \
OVERRIDE_CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/errno.h"
#include "libc/macros.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
@ -27,9 +28,10 @@
textwindows int sys_chdir_nt(const char *path) {
uint32_t n;
int e, ms, len;
int e, ms, err, len;
char16_t path16[PATH_MAX], var[4];
if ((len = __mkntpath(path, path16)) == -1) return -1;
if (!len) return enoent();
if (len && path16[len - 1] != u'\\') {
if (len + 2 > PATH_MAX) return enametoolong();
path16[len + 0] = u'\\';
@ -39,7 +41,7 @@ textwindows int sys_chdir_nt(const char *path) {
* chdir() seems flaky on windows 7
* in a similar way to rmdir() sigh
*/
for (ms = 1;; ms *= 2) {
for (err = errno, ms = 1;; ms *= 2) {
if (SetCurrentDirectory(path16)) {
/*
* Now we need to set a magic environment variable.
@ -68,12 +70,12 @@ textwindows int sys_chdir_nt(const char *path) {
if (ms <= 512 &&
(e == kNtErrorFileNotFound || e == kNtErrorAccessDenied)) {
Sleep(ms);
errno = err;
continue;
} else {
break;
}
}
}
errno = e;
return -1;
return __fix_enotdir(-1, path16);
}

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
@ -30,10 +31,14 @@
* @see fchdir()
*/
int chdir(const char *path) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) {
return sys_chdir(path);
int rc;
if (!path || (IsAsan() && !__asan_is_valid(path, 1))) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_chdir(path);
} else {
return sys_chdir_nt(path);
rc = sys_chdir_nt(path);
}
STRACE("%s(%#s) → %d% m", "chdir", path, rc);
return rc;
}

33
libc/calls/chroot.c Normal file
View file

@ -0,0 +1,33 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Changes root directory.
*
* @raise ENOSYS on Windows
*/
int chroot(const char *path) {
int rc;
rc = sys_chroot(path);
STRACE("chroot(%s) → %d% m", path, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/timeval.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h"
@ -25,6 +26,8 @@
#include "libc/nt/synchronization.h"
#include "libc/sysv/errfuns.h"
static typeof(sys_clock_gettime) *__clock_gettime = sys_clock_gettime;
/**
* Returns nanosecond time.
*
@ -39,14 +42,20 @@
* @see strftime(), gettimeofday()
* @asyncsignalsafe
*/
int clock_gettime(int clockid, struct timespec *ts) {
int rc;
noinstrument int clock_gettime(int clockid, struct timespec *ts) {
int rc, e;
axdx_t ad;
if (!ts) return efault();
if (IsAsan() && !__asan_is_valid(ts, sizeof(*ts))) return efault();
if (clockid == -1) return einval();
if (!IsWindows()) {
if ((rc = sys_clock_gettime(clockid, ts)) == -1 && errno == ENOSYS) {
char buf[45];
if (!ts) {
rc = efault();
} else if (IsAsan() && !__asan_is_valid(ts, sizeof(*ts))) {
rc = efault();
} else if (clockid == -1) {
rc = einval();
} else if (!IsWindows()) {
e = errno;
if ((rc = __clock_gettime(clockid, ts))) {
errno = e;
ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL);
assert(ad.ax != -1);
if (SupportsXnu() && ad.ax) {
@ -56,8 +65,32 @@ int clock_gettime(int clockid, struct timespec *ts) {
ts->tv_nsec *= 1000;
rc = 0;
}
return rc;
} else {
return sys_clock_gettime_nt(clockid, ts);
rc = sys_clock_gettime_nt(clockid, ts);
}
if (!__time_critical) {
STRACE("clock_gettime(%d, [%s]) → %d% m", clockid,
__strace_timespec(buf, sizeof(buf), rc, ts), rc);
}
return rc;
}
/**
* Returns fast system clock_gettime() if it exists.
*/
void *__get_clock_gettime(void) {
void *vdso;
static bool once;
static void *result;
if (!once) {
if ((vdso = __vdsofunc("__vdso_clock_gettime"))) {
__clock_gettime = result = vdso;
}
once = true;
}
return result;
}
const void *const __clock_gettime_ctor[] initarray = {
__get_clock_gettime,
};

View file

@ -16,25 +16,41 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/filetype.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sock/ntstdin.internal.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_close_nt(struct Fd *fd) {
bool32 ok;
if (fd->kind == kFdFile && GetFileType(fd->handle) == kNtFileTypeDisk) {
/*
* Like Linux, closing a file on Windows doesn't guarantee it's
* immediately synced to disk. But unlike Linux, this could cause
* subsequent operations, e.g. unlink() to break w/ access error.
*/
int e;
bool ok = true;
if (fd->kind == kFdFile && ((fd->flags & O_ACCMODE) != O_RDONLY &&
GetFileType(fd->handle) == kNtFileTypeDisk)) {
// Like Linux, closing a file on Windows doesn't guarantee it's
// immediately synced to disk. But unlike Linux, this could cause
// subsequent operations, e.g. unlink() to break w/ access error.
e = errno;
FlushFileBuffers(fd->handle);
errno = e;
}
// if this file descriptor is wrapped in a named pipe worker thread
// then we need to close our copy of the worker thread handle. it's
// also required that whatever install a worker use malloc, so free
if (fd->worker) {
if (!weaken(UnrefNtStdinWorker)(fd->worker)) ok = false;
fd->worker = 0;
} else {
if (!CloseHandle(fd->handle)) ok = false;
}
ok = CloseHandle(fd->handle);
if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
ok &= CloseHandle(fd->extra);
if (!CloseHandle(fd->extra)) ok = false;
}
return ok ? 0 : __winerr();
return ok ? 0 : -1;
}

View file

@ -19,7 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
@ -31,36 +31,52 @@
* This function may be used for file descriptors returned by socket,
* accept, epoll_create, and zipos file descriptors too.
*
* This function should never be called twice for the same file
* descriptor, regardless of whether or not an error happened. However
* that doesn't mean the error should be ignored.
*
* @return 0 on success, or -1 w/ errno
* @error EINTR means a signal was received while closing (possibly
* because linger is enabled) in which case close() does not need to
* be called again, since the fd will close in the background, and
* chances are that on linux, the fd is already closed, even if the
* underlying resource isn't closed yet
* @asyncsignalsafe
* @vforksafe
*/
int close(int fd) {
int rc;
if (fd == -1) return 0;
if (fd < 0) return einval();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = weaken(__zipos_close)(fd);
if (fd == -1) {
rc = 0;
} else if (fd < 0) {
rc = einval();
} else {
if (!IsWindows() && !IsMetal()) {
rc = sys_close(fd);
} else if (IsMetal()) {
rc = 0;
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
rc = weaken(__zipos_close)(fd);
} else {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdEpoll) {
rc = weaken(sys_close_epoll_nt)(fd);
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
rc = weaken(sys_closesocket_nt)(g_fds.p + fd);
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdFile ||
g_fds.p[fd].kind == kFdConsole ||
g_fds.p[fd].kind == kFdProcess)) {
rc = sys_close_nt(g_fds.p + fd);
if (!IsWindows() && !IsMetal()) {
rc = sys_close(fd);
} else if (IsMetal()) {
rc = 0;
} else {
rc = ebadf();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdEpoll) {
rc = weaken(sys_close_epoll_nt)(fd);
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
rc = weaken(sys_closesocket_nt)(g_fds.p + fd);
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdFile ||
g_fds.p[fd].kind == kFdConsole ||
g_fds.p[fd].kind == kFdProcess)) {
rc = sys_close_nt(g_fds.p + fd);
} else {
STRACE("close(%d) unknown kind: %d", fd, g_fds.p[fd].kind);
rc = ebadf();
}
}
}
if (!__vforked) {
__releasefd(fd);
}
}
__releasefd(fd);
SYSDEBUG("close(%d) -> %d", fd, rc);
STRACE("%s(%d) → %d% m", "close", fd, rc);
return rc;
}

View file

@ -16,60 +16,69 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/log/libfatal.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/errfuns.h"
static noasan bool EndsWithIgnoreCase(const char *p, size_t n, const char *s) {
size_t i, m;
m = __strlen(s);
if (n >= m) {
for (i = n - m; i < n; ++i) {
if (kToLower[p[i] & 255] != (*s++ & 255)) {
return false;
}
}
return true;
} else {
return false;
}
static bool IsExePath(const char *s, size_t n) {
return n >= 4 && (READ32LE(s + n - 4) == READ32LE(".exe") ||
READ32LE(s + n - 4) == READ32LE(".EXE"));
}
static noasan bool AccessCommand(const char *name,
char path[hasatleast PATH_MAX], size_t namelen,
const char *suffix, size_t pathlen) {
static bool IsComPath(const char *s, size_t n) {
return n >= 4 && (READ32LE(s + n - 4) == READ32LE(".com") ||
READ32LE(s + n - 4) == READ32LE(".COM"));
}
static bool IsComDbgPath(const char *s, size_t n) {
return n >= 8 && (READ64LE(s + n - 8) == READ64LE(".com.dbg") ||
READ64LE(s + n - 8) == READ64LE(".COM.DBG"));
}
static bool AccessCommand(const char *name, char *path, size_t pathsz,
size_t namelen, int *err, const char *suffix,
size_t pathlen) {
size_t suffixlen;
suffixlen = __strlen(suffix);
if (pathlen + 1 + namelen + suffixlen + 1 > PATH_MAX) return -1;
suffixlen = strlen(suffix);
if (pathlen + 1 + namelen + suffixlen + 1 > pathsz) return false;
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
path[pathlen] = !IsWindows() ? '/'
: __memchr(path, '\\', pathlen) ? '\\'
: '/';
path[pathlen] = !IsWindows() ? '/'
: memchr(path, '\\', pathlen) ? '\\'
: '/';
pathlen++;
}
__repmovsb(path + pathlen, name, namelen);
__repmovsb(path + pathlen + namelen, suffix, suffixlen + 1);
return isexecutable(path);
memcpy(path + pathlen, name, namelen);
memcpy(path + pathlen + namelen, suffix, suffixlen + 1);
if (!access(path, X_OK)) return true;
if (errno == EACCES || *err != EACCES) *err = errno;
return false;
}
static noasan bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
size_t namelen, const char *suffix) {
static bool SearchPath(const char *name, char *path, size_t pathsz,
size_t namelen, int *err, const char *suffix) {
char sep;
size_t i;
const char *p;
p = firstnonnull(emptytonull(getenv("PATH")), "/bin:/usr/local/bin:/usr/bin");
if (!(p = getenv("PATH"))) p = "/bin:/usr/local/bin:/usr/bin";
sep = IsWindows() && strchr(p, ';') ? ';' : ':';
for (;;) {
for (i = 0; p[i] && p[i] != ':' && p[i] != ';'; ++i) {
if (i < PATH_MAX) {
for (i = 0; p[i] && p[i] != sep; ++i) {
if (i < pathsz) {
path[i] = p[i];
}
}
if (AccessCommand(name, path, namelen, suffix, i)) {
if (AccessCommand(name, path, pathsz, namelen, err, suffix, i)) {
return true;
}
if (p[i] == ':' || p[i] == ';') {
if (p[i] == sep) {
p += i + 1;
} else {
break;
@ -78,21 +87,36 @@ static noasan bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
return false;
}
static noasan bool FindCommand(const char *name,
char pathbuf[hasatleast PATH_MAX],
size_t namelen, const char *suffix) {
if (memchr(name, '/', namelen) || memchr(name, '\\', namelen)) {
pathbuf[0] = 0;
return AccessCommand(name, pathbuf, namelen, suffix, 0);
static bool FindCommand(const char *name, char *pb, size_t pbsz, size_t namelen,
bool pri, const char *suffix, int *err) {
if (pri && (memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
pb[0] = 0;
return AccessCommand(name, pb, pbsz, namelen, err, suffix, 0);
}
return ((IsWindows() &&
(AccessCommand(name, pathbuf, namelen, suffix,
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
AccessCommand(name, pathbuf, namelen, suffix,
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf) ||
AccessCommand(name, pathbuf, namelen, suffix,
stpcpy(pathbuf, ".") - pathbuf))) ||
SearchPath(name, pathbuf, namelen, suffix));
if (IsWindows() && pri &&
pbsz > max(strlen(kNtSystemDirectory), strlen(kNtWindowsDirectory))) {
return AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, kNtSystemDirectory) - pb) ||
AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, kNtWindowsDirectory) - pb);
}
return (IsWindows() &&
(pbsz > 1 && AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, ".") - pb))) ||
SearchPath(name, pb, pbsz, namelen, err, suffix);
}
static bool FindVerbatim(const char *name, char *pb, size_t pbsz,
size_t namelen, bool pri, int *err) {
return FindCommand(name, pb, pbsz, namelen, pri, "", err);
}
static bool FindSuffixed(const char *name, char *pb, size_t pbsz,
size_t namelen, bool pri, int *err) {
return !IsExePath(name, namelen) && !IsComPath(name, namelen) &&
!IsComDbgPath(name, namelen) &&
(FindCommand(name, pb, pbsz, namelen, pri, ".com", err) ||
FindCommand(name, pb, pbsz, namelen, pri, ".exe", err));
}
/**
@ -104,29 +128,36 @@ static noasan bool FindCommand(const char *name,
* @asyncsignalsafe
* @vforksafe
*/
noasan char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
int olderr;
char *commandv(const char *name, char *pathbuf, size_t pathbufsz) {
int e, f;
char *res;
size_t namelen;
res = 0;
if (!name) {
efault();
return 0;
}
if (!(namelen = __strlen(name))) {
} else if (!(namelen = strlen(name))) {
enoent();
return 0;
}
if (namelen + 1 > PATH_MAX) {
} else if (namelen + 1 > pathbufsz) {
enametoolong();
return 0;
}
if (FindCommand(name, pathbuf, namelen, "") ||
(!EndsWithIgnoreCase(name, namelen, ".exe") &&
!EndsWithIgnoreCase(name, namelen, ".com") &&
!EndsWithIgnoreCase(name, namelen, ".com.dbg") &&
(FindCommand(name, pathbuf, namelen, ".com") ||
FindCommand(name, pathbuf, namelen, ".exe")))) {
return pathbuf;
} else {
return 0;
e = errno;
f = ENOENT;
if ((IsWindows() &&
(FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f))) ||
(!IsWindows() &&
(FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f)))) {
errno = e;
res = pathbuf;
} else {
errno = f;
}
}
STRACE("commandv(%#s, %p, %'zu) → %#s% m", name, pathbuf, pathbufsz, res);
return res;
}

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
@ -27,6 +28,7 @@
#include "libc/nt/enum/filesharemode.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/o.h"
@ -66,12 +68,12 @@ static int sys_copyfile(const char *src, const char *dst, int flags) {
int64_t inoffset, outoffset;
int rc, srcfd, dstfd, oflags, omode;
rc = -1;
if ((srcfd = sys_openat(AT_FDCWD, src, O_RDONLY, 0)) != -1) {
if (sys_fstat(srcfd, &st) != -1) {
if ((srcfd = openat(AT_FDCWD, src, O_RDONLY, 0)) != -1) {
if (fstat(srcfd, &st) != -1) {
omode = st.st_mode & 0777;
oflags = O_WRONLY | O_CREAT;
if (flags & COPYFILE_NOCLOBBER) oflags |= O_EXCL;
if ((dstfd = sys_openat(AT_FDCWD, dst, oflags, omode)) != -1) {
if ((dstfd = openat(AT_FDCWD, dst, oflags, omode)) != -1) {
remaining = st.st_size;
ftruncate(dstfd, remaining);
inoffset = 0;
@ -86,13 +88,13 @@ static int sys_copyfile(const char *src, const char *dst, int flags) {
if (flags & COPYFILE_PRESERVE_TIMESTAMPS) {
amtime[0] = st.st_atim;
amtime[1] = st.st_mtim;
sys_utimensat(dstfd, NULL, amtime, 0);
utimensat(dstfd, NULL, amtime, 0);
}
}
rc |= sys_close(dstfd);
rc |= close(dstfd);
}
}
rc |= sys_close(srcfd);
rc |= close(srcfd);
}
return rc;
}
@ -108,7 +110,7 @@ static int sys_copyfile(const char *src, const char *dst, int flags) {
* @return 0 on success, or -1 w/ errno
*/
int copyfile(const char *src, const char *dst, int flags) {
if (!IsWindows()) {
if (!IsWindows() || startswith(src, "/zip/") || startswith(dst, "/zip/")) {
return sys_copyfile(src, dst, flags);
} else {
return sys_copyfile_nt(src, dst, flags);

View file

@ -35,6 +35,6 @@
* @see open(), touch()
* @asyncsignalsafe
*/
nodiscard int creat(const char *file, uint32_t mode) {
dontdiscard int creat(const char *file, uint32_t mode) {
return openat(AT_FDCWD, file, O_CREAT | O_WRONLY | O_TRUNC, mode);
}

View file

@ -0,0 +1,110 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filesharemode.h"
#include "libc/sysv/consts/o.h"
// code size optimization
// <sync libc/sysv/consts.sh>
#define _O_APPEND 0x00000400 // kNtFileAppendData
#define _O_CREAT 0x00000040 // kNtOpenAlways
#define _O_EXCL 0x00000080 // kNtCreateNew
#define _O_TRUNC 0x00000200 // kNtCreateAlways
#define _O_DIRECTORY 0x00010000 // kNtFileFlagBackupSemantics
#define _O_TMPFILE 0x00410000 // AttributeTemporary|FlagDeleteOnClose
#define _O_DIRECT 0x00004000 // kNtFileFlagNoBuffering
#define _O_NDELAY 0x00000800 // kNtFileFlagWriteThrough
#define _O_RANDOM 0x80000000 // kNtFileFlagRandomAccess
#define _O_SEQUENTIAL 0x40000000 // kNtFileFlagSequentialScan
#define _O_COMPRESSED 0x20000000 // kNtFileAttributeCompressed
#define _O_INDEXED 0x10000000 // !kNtFileAttributeNotContentIndexed
#define _O_NONBLOCK 0x00000800
#define _O_CLOEXEC 0x00080000
// </sync libc/sysv/consts.sh>
textwindows int GetNtOpenFlags(int flags, int mode, uint32_t *out_perm,
uint32_t *out_share, uint32_t *out_disp,
uint32_t *out_attr) {
uint32_t perm, share, disp, attr;
switch (flags & O_ACCMODE) {
case O_RDONLY:
perm = kNtFileGenericRead | kNtGenericExecute;
break;
case O_WRONLY:
perm = kNtFileGenericWrite | kNtGenericExecute;
break;
case O_RDWR:
perm = kNtFileGenericRead | kNtFileGenericWrite | kNtGenericExecute;
break;
default:
return -1;
}
if (flags & _O_APPEND) {
perm = kNtFileAppendData;
}
if (flags & _O_EXCL) {
share = kNtFileShareExclusive;
} else {
share = kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
}
if ((flags & _O_CREAT) && (flags & _O_EXCL)) {
disp = kNtCreateNew;
} else if ((flags & _O_CREAT) && (flags & _O_TRUNC)) {
disp = kNtCreateAlways;
} else if (flags & _O_CREAT) {
disp = kNtOpenAlways;
} else if (flags & _O_TRUNC) {
disp = kNtTruncateExisting;
} else {
disp = kNtOpenExisting;
}
if ((flags & _O_TMPFILE) == _O_TMPFILE) {
attr = kNtFileAttributeTemporary | kNtFileFlagDeleteOnClose;
} else {
attr = kNtFileAttributeNormal;
if (flags & _O_DIRECTORY) {
attr |= kNtFileFlagBackupSemantics;
}
if (~mode & 0200) {
attr |= kNtFileAttributeReadonly;
}
}
if (~flags & _O_INDEXED) attr |= kNtFileAttributeNotContentIndexed;
if (flags & _O_COMPRESSED) attr |= kNtFileAttributeCompressed;
if (flags & _O_SEQUENTIAL) attr |= kNtFileFlagSequentialScan;
if (flags & _O_RANDOM) attr |= kNtFileFlagRandomAccess;
if (flags & _O_DIRECT) attr |= kNtFileFlagNoBuffering;
if (flags & _O_NDELAY) attr |= kNtFileFlagWriteThrough;
if (out_perm) *out_perm = perm;
if (out_share) *out_share = share;
if (out_disp) *out_disp = disp;
if (out_attr) *out_attr = attr;
return 0;
}

View file

@ -16,32 +16,35 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/alg/reverse.internal.h"
#include "libc/calls/calls.h"
#include "libc/intrin/lockxadd.h"
#include "libc/nt/process.h"
static const char kPipeNamePrefix[] = "\\\\?\\pipe\\cosmo\\";
static textwindows size_t UintToChar16Array(char16_t *a, uint64_t i) {
size_t j = 0;
static textwindows char16_t *UintToChar16Array(char16_t p[21], uint64_t x) {
char t;
size_t a, b, i = 0;
do {
a[j++] = i % 10 + '0';
i /= 10;
} while (i > 0);
a[j] = 0;
reverse(a, j);
return j;
p[i++] = x % 10 + '0';
x = x / 10;
} while (x > 0);
if (i) {
for (a = 0, b = i - 1; a < b; ++a, --b) {
t = p[a];
p[a] = p[b];
p[b] = t;
}
}
return p + i;
}
textwindows char16_t *CreatePipeName(char16_t *a) {
static long x;
unsigned i;
for (i = 0; kPipeNamePrefix[i]; ++i) a[i] = kPipeNamePrefix[i];
i += UintToChar16Array(a + i, GetCurrentProcessId());
a[i++] = u'-';
i += UintToChar16Array(a + i, GetCurrentProcessId());
a[i++] = u'-';
i += UintToChar16Array(a + i, x++);
a[i] = u'\0';
char16_t *p = a;
const char *q = "\\\\?\\pipe\\cosmo\\";
while (*q) *p++ = *q++;
p = UintToChar16Array(p, GetCurrentProcessId());
*p++ = '-';
p = UintToChar16Array(p, _lockxadd(&x, 1));
*p = 0;
return a;
}

View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes clock_gettime() clock argument.
*/
char *DescribeClockName(int x) {
int i;
char *s;
_Alignas(char) static char buf[32];
if ((s = GetMagnumStr(kClockNames, x))) {
stpcpy(stpcpy(buf, "CLOCK_"), s);
return buf;
} else {
FormatInt32(buf, x);
return buf;
}
}

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/log/libfatal.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
@ -28,21 +28,19 @@
noasan const char *DescribeFrame(int x) {
/* asan runtime depends on this function */
char *p;
static char buf[128];
static char buf[32];
if (IsShadowFrame(x)) {
p = buf;
p = __stpcpy(p, " shadow of ");
p = __fixcpy(p, UNSHADOW(ADDR(x)), 48);
ksnprintf(buf, sizeof(buf), " /*shadow:%.12p*/", UNSHADOW(ADDR(x)));
return buf;
return " shadow ";
return " /*shadow*/ ";
} else if (IsAutoFrame(x)) {
return " automap";
return " /*automap*/";
} else if (IsFixedFrame(x)) {
return " fixed ";
return " /*fixed*/ ";
} else if (IsArenaFrame(x)) {
return " arena ";
return " /*arena*/ ";
} else if (IsStaticStackFrame(x)) {
return " stack ";
return " /*stack*/ ";
} else {
return "";
}

View file

@ -20,19 +20,32 @@
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) {
/* asan runtime depends on this function */
static noasan char DescribeMapType(int flags) {
switch (flags & MAP_TYPE) {
case MAP_FILE:
return 'f';
case MAP_PRIVATE:
return 'p';
case MAP_SHARED:
return 's';
default:
return '?';
}
}
noasan char *DescribeProt(int prot, char p[hasatleast 4]) {
p[0] = (prot & PROT_READ) ? 'r' : '-';
p[1] = (prot & PROT_WRITE) ? 'w' : '-';
p[2] = (prot & PROT_EXEC) ? 'x' : '-';
if (flags & MAP_PRIVATE) {
p[3] = 'p';
} else if (flags & MAP_SHARED) {
p[3] = 's';
} else {
p[3] = '?';
}
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : 'f';
p[3] = 0;
return p;
}
noasan char *DescribeMapping(int prot, int flags, char p[hasatleast 8]) {
/* asan runtime depends on this function */
DescribeProt(prot, p);
p[3] = DescribeMapType(flags);
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-';
p[5] = (flags & MAP_GROWSDOWN) ? 'S' : '-';
p[6] = (flags & MAP_FIXED) ? 'F' : '-';
p[7] = 0;

View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/mem/alloca.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes clock_gettime() clock argument.
*/
char *DescribeOpenFlags(int x) {
char *s;
int i, n;
struct DescribeFlags *d;
_Alignas(char) static char openflags[128];
// TODO(jart): unify DescribeFlags and MagnumStr data structures
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR;) ++n;
d = alloca(n * sizeof(struct DescribeFlags));
for (i = 0; i < n; ++i) {
d[i].flag = MAGNUM_NUMBER(kOpenFlags, i);
d[i].name = MAGNUM_STRING(kOpenFlags, i);
}
return DescribeFlags(openflags, sizeof(openflags), d, n, "O_", x);
}

102
libc/calls/directmap-nt.c Normal file
View file

@ -0,0 +1,102 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/processmemorycounters.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
int flags, int fd, int64_t off) {
size_t i;
bool iscow;
int64_t handle;
uint32_t oldprot;
struct DirectMap dm;
struct ProtectNt fl;
const struct NtSecurityAttributes *sec;
struct NtProcessMemoryCountersEx memcount;
if (fd != -1) {
handle = g_fds.p[fd].handle;
} else {
handle = kNtInvalidHandleValue;
}
if (flags & MAP_PRIVATE) {
sec = 0; // MAP_PRIVATE isn't inherited across fork()
} else {
sec = &kNtIsInheritable; // MAP_SHARED gives us zero-copy fork()
}
// nt will whine under many circumstances if we change the execute bit
// later using mprotect(). the workaround is to always request execute
// and then virtualprotect() it away until we actually need it. please
// note that open-nt.c always requests an kNtGenericExecute accessmask
iscow = false;
if (handle != -1) {
if (flags & MAP_PRIVATE) {
// windows has cow pages but they can't propagate across fork()
// that means we only get copy-on-write for the root process :(
fl = (struct ProtectNt){kNtPageExecuteWritecopy,
kNtFileMapCopy | kNtFileMapExecute};
iscow = true;
} else {
assert(flags & MAP_SHARED);
if ((g_fds.p[fd].flags & O_ACCMODE) == O_RDONLY) {
fl = (struct ProtectNt){kNtPageExecuteRead,
kNtFileMapRead | kNtFileMapExecute};
} else {
fl = (struct ProtectNt){kNtPageExecuteReadwrite,
kNtFileMapWrite | kNtFileMapExecute};
}
}
} else {
assert(flags & MAP_ANONYMOUS);
fl = (struct ProtectNt){kNtPageExecuteReadwrite,
kNtFileMapWrite | kNtFileMapExecute};
}
if ((dm.maphandle = CreateFileMapping(handle, sec, fl.flags1,
(size + off) >> 32, (size + off), 0))) {
if ((dm.addr = MapViewOfFileEx(dm.maphandle, fl.flags2, off >> 32, off,
size, addr))) {
if (VirtualProtect(addr, size, __prot2nt(prot, iscow), &oldprot)) {
return dm;
} else {
return dm;
UnmapViewOfFile(dm.addr);
}
}
CloseHandle(dm.maphandle);
}
dm.maphandle = kNtInvalidHandleValue;
dm.addr = (void *)(intptr_t)-1;
return dm;
}

View file

@ -17,8 +17,9 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
@ -31,25 +32,24 @@
* support Windows NT and Address Sanitizer. That memory tracking can be
* bypassed by calling this function. However the caller is responsible
* for passing the magic memory handle on Windows NT to CloseHandle().
*
* @asyncsignalsafe
* @threadsafe
*/
noasan struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags,
int fd, int64_t off) {
struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
int64_t off) {
/* asan runtime depends on this function */
char mode[8];
struct DirectMap dm;
struct DirectMap d;
if (!IsWindows() && !IsMetal()) {
dm.addr = __sys_mmap(addr, size, prot, flags, fd, off, off);
SYSDEBUG("sys_mmap(0x%p%s, 0x%x, %s, %d, %d) -> 0x%p %s", addr,
DescribeFrame((intptr_t)addr >> 16), size,
DescribeMapping(prot, flags, mode), (long)fd, off, dm.addr,
dm.addr != MAP_FAILED ? "" : strerror(errno));
dm.maphandle = kNtInvalidHandleValue;
return dm;
d.addr = __sys_mmap(addr, size, prot, flags, fd, off, off);
d.maphandle = kNtInvalidHandleValue;
} else if (IsMetal()) {
return sys_mmap_metal(addr, size, prot, flags, fd, off);
d = sys_mmap_metal(addr, size, prot, flags, fd, off);
} else {
return sys_mmap_nt(addr, size, prot, flags,
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
off);
d = sys_mmap_nt(addr, size, prot, flags, fd, off);
}
KERNTRACE("sys_mmap(%.12p%s, %'zu, %s, %s, %d, %'ld) → {%.12p, %p}% m", addr,
DescribeFrame((intptr_t)addr >> 16), size, DescribeProtFlags(prot),
DescribeMapFlags(flags), fd, off, d.addr, d.maphandle);
return d;
}

View file

@ -17,38 +17,69 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sock/internal.h"
#include "libc/sock/ntstdin.internal.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
/**
* Implements dup(), dup2(), and dup3() for Windows NT.
* Implements dup(), dup2(), dup3(), and F_DUPFD for Windows.
*/
textwindows int sys_dup_nt(int oldfd, int newfd, int flags) {
int64_t proc;
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
int64_t proc, handle;
// validate the api usage
if (oldfd < 0) return einval();
if (flags & ~O_CLOEXEC) return einval();
if (oldfd >= g_fds.n ||
(g_fds.p[oldfd].kind != kFdFile && g_fds.p[oldfd].kind != kFdSocket &&
g_fds.p[oldfd].kind != kFdConsole)) {
return ebadf();
}
// allocate a new file descriptor
if (newfd == -1) {
if ((newfd = __reservefd()) == -1) return -1;
if ((newfd = __reservefd(start)) == -1) {
return -1;
}
} else {
if (__ensurefds(newfd) == -1) return -1;
if (g_fds.p[newfd].kind) close(newfd);
g_fds.p[newfd].kind = kFdReserved;
}
// if this file descriptor is wrapped in a named pipe worker thread
// then we should clone the original authentic handle rather than the
// stdin worker's named pipe. we won't clone the worker, since that
// can always be recreated again on demand.
if (g_fds.p[oldfd].worker) {
handle = g_fds.p[oldfd].worker->reader;
} else {
handle = g_fds.p[oldfd].handle;
}
proc = GetCurrentProcess();
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc, &g_fds.p[newfd].handle,
0, true, kNtDuplicateSameAccess)) {
if (DuplicateHandle(proc, handle, proc, &g_fds.p[newfd].handle, 0, true,
kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
g_fds.p[newfd].extra = g_fds.p[oldfd].extra;
g_fds.p[newfd].flags = flags;
g_fds.p[newfd].mode = g_fds.p[oldfd].mode;
g_fds.p[newfd].flags = g_fds.p[oldfd].flags & ~O_CLOEXEC;
if (flags & O_CLOEXEC) g_fds.p[newfd].flags |= O_CLOEXEC;
if (g_fds.p[oldfd].kind == kFdSocket && weaken(_dupsockfd)) {
g_fds.p[newfd].extra =
(intptr_t)weaken(_dupsockfd)((struct SockFd *)g_fds.p[oldfd].extra);
} else {
g_fds.p[newfd].extra = g_fds.p[oldfd].extra;
}
if (g_fds.p[oldfd].worker) {
g_fds.p[newfd].worker = weaken(RefNtStdinWorker)(g_fds.p[oldfd].worker);
}
return newfd;
} else {
__releasefd(newfd);

View file

@ -18,7 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
@ -34,8 +34,8 @@ int dup(int fd) {
if (!IsWindows()) {
fd2 = sys_dup(fd);
} else {
fd2 = sys_dup_nt(fd, -1, 0);
fd2 = sys_dup_nt(fd, -1, 0, -1);
}
SYSDEBUG("dup(%d) -> %d", fd, fd2);
STRACE("%s(%d) → %d% m", "dup", fd, fd2);
return fd2;
}

View file

@ -18,7 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
@ -32,11 +32,14 @@
* @vforksafe
*/
int dup2(int oldfd, int newfd) {
SYSDEBUG("dup2(%d, %d)", oldfd, newfd);
if (oldfd == newfd) return newfd;
if (!IsWindows()) {
return sys_dup3(oldfd, newfd, 0);
int rc;
if (oldfd == newfd) {
rc = newfd;
} else if (!IsWindows()) {
rc = sys_dup3(oldfd, newfd, 0);
} else {
return sys_dup_nt(oldfd, newfd, 0);
rc = sys_dup_nt(oldfd, newfd, 0, -1);
}
STRACE("dup2(%d, %d) → %d% m", oldfd, newfd, rc);
return rc;
}

View file

@ -17,17 +17,17 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
#define __NR_dup3_linux 0x0124 /*RHEL5:CVE-2010-3301*/
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
static bool once, demodernize;
int olderr, fd;
if (!once) {
olderr = errno;
fd = __sys_dup3(oldfd, newfd, flags);
if ((fd == -1 && errno == ENOSYS) || fd == __NR_dup3_linux) {
if (fd == -1 && errno == ENOSYS) {
STRACE("demodernizing %s() due to %s", "dup3", "RHEL5:CVE-2010-3301");
demodernize = true;
once = true;
errno = olderr;

Some files were not shown because too many files have changed in this diff Show more