diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 07df901..2a2a501 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,11 +23,15 @@ jobs: if: matrix.os == 'windows-latest' - name: Install llvm-nm (Windows) - shell: bash run: | rustup update stable rustup default stable rustup component add llvm-tools-preview + if: matrix.os == 'windows-latest' + + - name: Register llvm-nm in environment (Windows) + shell: bash + run: | echo "WASM_NM=$(rustc --print sysroot|sed 's|C:|/c|'|sed 's|\\|/|g')/lib/rustlib/x86_64-pc-windows-msvc/bin/llvm-nm.exe" >> $GITHUB_ENV if: matrix.os == 'windows-latest' diff --git a/Makefile b/Makefile index 8994695..a93b10a 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ # These variables are specifically meant to be overridable via the make # command-line. WASM_CC ?= clang -WASM_NM ?= $(patsubst %clang,%llvm-nm,$(WASM_CC)) -WASM_AR ?= $(patsubst %clang,%llvm-ar,$(WASM_CC)) +WASM_NM ?= $(patsubst %clang,%llvm-nm,$(filter-out ccache sccache,$(WASM_CC))) +WASM_AR ?= $(patsubst %clang,%llvm-ar,$(filter-out ccache sccache,$(WASM_CC))) WASM_CFLAGS ?= -O2 -DNDEBUG # The directory where we build the sysroot. SYSROOT ?= $(CURDIR)/sysroot @@ -10,17 +10,13 @@ SYSROOT ?= $(CURDIR)/sysroot INSTALL_DIR ?= /usr/local # single or posix THREAD_MODEL ?= single +# dlmalloc or none +MALLOC_IMPL ?= dlmalloc # yes or no -BUILD_DLMALLOC ?= yes BUILD_LIBC_TOP_HALF ?= yes # The directory where we're store intermediate artifacts. OBJDIR ?= $(CURDIR)/build -# Check dependencies. -ifneq ($(BUILD_DLMALLOC),yes) -$(error build currently depends on BUILD_DLMALLOC=yes) -endif - # Variables from this point on are not meant to be overridable via the # make command-line. @@ -54,6 +50,10 @@ LIBC_BOTTOM_HALF_ALL_SOURCES := $(LIBC_BOTTOM_HALF_ALL_SOURCES) $(LIBC_BOTTOM_HA LIBWASI_EMULATED_MMAN_SOURCES = \ $(shell find $(LIBC_BOTTOM_HALF_DIR)/mman -name \*.c) +LIBWASI_EMULATED_PROCESS_CLOCKS_SOURCES = \ + $(shell find $(LIBC_BOTTOM_HALF_DIR)/clocks -name \*.c) +LIBWASI_EMULATED_GETPID_SOURCES = \ + $(shell find $(LIBC_BOTTOM_HALF_DIR)/getpid -name \*.c) LIBWASI_EMULATED_SIGNAL_SOURCES = \ $(shell find $(LIBC_BOTTOM_HALF_DIR)/signal -name \*.c) LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \ @@ -166,8 +166,8 @@ LIBC_TOP_HALF_MUSL_SOURCES = \ %/fminf.c %/fmaxf.c \ %/fmin.c %/fmax.c, \ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/math/*.c)) \ - $(filter-out %/crealf.c %/creal.c \ - %/cimagf.c %/cimag.c, \ + $(filter-out %/crealf.c %/creal.c %creall.c \ + %/cimagf.c %/cimag.c %cimagl.c, \ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/complex/*.c)) \ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/crypt/*.c) MUSL_PRINTSCAN_SOURCES = \ @@ -184,21 +184,33 @@ LIBC_TOP_HALF_ALL_SOURCES = \ $(shell find $(LIBC_TOP_HALF_SOURCES) -name \*.c) # Set the target. -WASM_CFLAGS += --target=$(TARGET_TRIPLE) +CFLAGS = $(WASM_CFLAGS) --target=$(TARGET_TRIPLE) # WebAssembly floating-point match doesn't trap. # TODO: Add -fno-signaling-nans when the compiler supports it. -WASM_CFLAGS += -fno-trapping-math +CFLAGS += -fno-trapping-math +# Add all warnings, but disable a few which occur in third-party code. +CFLAGS += -Wall -Wextra -Werror \ + -Wno-null-pointer-arithmetic \ + -Wno-unused-parameter \ + -Wno-sign-compare \ + -Wno-unused-variable \ + -Wno-unused-function \ + -Wno-ignored-attributes \ + -Wno-missing-braces \ + -Wno-ignored-pragmas \ + -Wno-unused-but-set-variable \ + -Wno-unknown-warning-option # Configure support for threads. ifeq ($(THREAD_MODEL), single) -WASM_CFLAGS += -mthread-model single +CFLAGS += -mthread-model single endif ifeq ($(THREAD_MODEL), posix) -WASM_CFLAGS += -mthread-model posix -pthread +CFLAGS += -mthread-model posix -pthread endif # Set the sysroot. -WASM_CFLAGS += --sysroot="$(SYSROOT)" +CFLAGS += --sysroot="$(SYSROOT)" # These variables describe the locations of various files and directories in # the build tree. @@ -206,8 +218,12 @@ objs = $(patsubst $(CURDIR)/%.c,$(OBJDIR)/%.o,$(1)) DLMALLOC_OBJS = $(call objs,$(DLMALLOC_SOURCES)) LIBC_BOTTOM_HALF_ALL_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_ALL_SOURCES)) LIBC_TOP_HALF_ALL_OBJS = $(call objs,$(LIBC_TOP_HALF_ALL_SOURCES)) -ifeq ($(BUILD_DLMALLOC),yes) +ifeq ($(MALLOC_IMPL),dlmalloc) LIBC_OBJS += $(DLMALLOC_OBJS) +else ifeq ($(MALLOC_IMPL),none) +# No object files to add. +else +$(error unknown malloc implementation $(MALLOC_IMPL)) endif # Add libc-bottom-half's objects. LIBC_OBJS += $(LIBC_BOTTOM_HALF_ALL_OBJS) @@ -219,6 +235,8 @@ MUSL_PRINTSCAN_OBJS = $(call objs,$(MUSL_PRINTSCAN_SOURCES)) MUSL_PRINTSCAN_LONG_DOUBLE_OBJS = $(patsubst %.o,%.long-double.o,$(MUSL_PRINTSCAN_OBJS)) MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS = $(patsubst %.o,%.no-floating-point.o,$(MUSL_PRINTSCAN_OBJS)) LIBWASI_EMULATED_MMAN_OBJS = $(call objs,$(LIBWASI_EMULATED_MMAN_SOURCES)) +LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS = $(call objs,$(LIBWASI_EMULATED_PROCESS_CLOCKS_SOURCES)) +LIBWASI_EMULATED_GETPID_OBJS = $(call objs,$(LIBWASI_EMULATED_GETPID_SOURCES)) LIBWASI_EMULATED_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES)) LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES)) @@ -322,6 +340,10 @@ $(SYSROOT_LIB)/libc-printscan-no-floating-point.a: $(MUSL_PRINTSCAN_NO_FLOATING_ $(SYSROOT_LIB)/libwasi-emulated-mman.a: $(LIBWASI_EMULATED_MMAN_OBJS) +$(SYSROOT_LIB)/libwasi-emulated-process-clocks.a: $(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS) + +$(SYSROOT_LIB)/libwasi-emulated-getpid.a: $(LIBWASI_EMULATED_GETPID_OBJS) + $(SYSROOT_LIB)/libwasi-emulated-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) %.a: @@ -335,40 +357,40 @@ $(SYSROOT_LIB)/libwasi-emulated-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBW # silently dropping the tail. $(WASM_AR) crs $@ $(wordlist 800, 100000, $^) -$(MUSL_PRINTSCAN_OBJS): WASM_CFLAGS += \ +$(MUSL_PRINTSCAN_OBJS): CFLAGS += \ -D__wasilibc_printscan_no_long_double \ -D__wasilibc_printscan_full_support_option="\"add -lc-printscan-long-double to the link command\"" -$(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS): WASM_CFLAGS += \ +$(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS): CFLAGS += \ -D__wasilibc_printscan_no_floating_point \ -D__wasilibc_printscan_floating_point_support_option="\"remove -lc-printscan-no-floating-point from the link command\"" -$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS): WASM_CFLAGS += \ +$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS): CFLAGS += \ -D_WASI_EMULATED_SIGNAL $(OBJDIR)/%.long-double.o: $(CURDIR)/%.c include_dirs @mkdir -p "$(@D)" - "$(WASM_CC)" $(WASM_CFLAGS) -MD -MP -o $@ -c $< + $(WASM_CC) $(CFLAGS) -MD -MP -o $@ -c $< $(OBJDIR)/%.no-floating-point.o: $(CURDIR)/%.c include_dirs @mkdir -p "$(@D)" - "$(WASM_CC)" $(WASM_CFLAGS) -MD -MP -o $@ -c $< + $(WASM_CC) $(CFLAGS) -MD -MP -o $@ -c $< $(OBJDIR)/%.o: $(CURDIR)/%.c include_dirs @mkdir -p "$(@D)" - "$(WASM_CC)" $(WASM_CFLAGS) -MD -MP -o $@ -c $< + $(WASM_CC) $(CFLAGS) -MD -MP -o $@ -c $< -include $(shell find $(OBJDIR) -name \*.d) -$(DLMALLOC_OBJS): WASM_CFLAGS += \ +$(DLMALLOC_OBJS): CFLAGS += \ -I$(DLMALLOC_INC) -startup_files $(LIBC_BOTTOM_HALF_ALL_OBJS): WASM_CFLAGS += \ +startup_files $(LIBC_BOTTOM_HALF_ALL_OBJS): CFLAGS += \ -I$(LIBC_BOTTOM_HALF_HEADERS_PRIVATE) \ -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC) \ -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) -$(LIBC_TOP_HALF_ALL_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS): WASM_CFLAGS += \ +$(LIBC_TOP_HALF_ALL_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS): CFLAGS += \ -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \ -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal \ -I$(LIBC_TOP_HALF_MUSL_DIR)/arch/wasm32 \ @@ -382,6 +404,9 @@ $(LIBC_TOP_HALF_ALL_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_NO -Wno-dangling-else \ -Wno-unknown-pragmas +$(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS): CFLAGS += \ + -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) + include_dirs: $(RM) -r "$(SYSROOT)" @@ -413,7 +438,7 @@ startup_files: include_dirs # @mkdir -p "$(OBJDIR)" cd "$(OBJDIR)" && \ - "$(WASM_CC)" $(WASM_CFLAGS) -c $(LIBC_BOTTOM_HALF_CRT_SOURCES) -MD -MP && \ + $(WASM_CC) $(CFLAGS) -c $(LIBC_BOTTOM_HALF_CRT_SOURCES) -MD -MP && \ mkdir -p "$(SYSROOT_LIB)" && \ mv *.o "$(SYSROOT_LIB)" @@ -422,6 +447,8 @@ libc: include_dirs \ $(SYSROOT_LIB)/libc-printscan-long-double.a \ $(SYSROOT_LIB)/libc-printscan-no-floating-point.a \ $(SYSROOT_LIB)/libwasi-emulated-mman.a \ + $(SYSROOT_LIB)/libwasi-emulated-process-clocks.a \ + $(SYSROOT_LIB)/libwasi-emulated-getpid.a \ $(SYSROOT_LIB)/libwasi-emulated-signal.a finish: startup_files libc @@ -432,6 +459,18 @@ finish: startup_files libc $(WASM_AR) crs "$(SYSROOT_LIB)/lib$${name}.a"; \ done + # + # The build succeeded! The generated sysroot is in $(SYSROOT). + # + +# The check for defined and undefined symbols expects there to be a heap +# alloctor (providing malloc, calloc, free, etc). Skip this step if the build +# is done without a malloc implementation. +ifneq ($(MALLOC_IMPL),none) +finish: check-symbols +endif + +check-symbols: startup_files libc # # Collect metadata on the sysroot and perform sanity checks. # @@ -444,20 +483,20 @@ finish: startup_files libc @# LLVM PR40497, which is fixed in 9.0, but not in 8.0. @# Ignore certain llvm builtin symbols such as those starting with __mul @# since these dependencies can vary between llvm versions. - "$(WASM_NM)" --defined-only "$(SYSROOT_LIB)"/libc.a "$(SYSROOT_LIB)"/*.o \ + "$(WASM_NM)" --defined-only "$(SYSROOT_LIB)"/libc.a "$(SYSROOT_LIB)"/libwasi-emulated-*.a "$(SYSROOT_LIB)"/*.o \ |grep ' [[:upper:]] ' |sed 's/.* [[:upper:]] //' |LC_ALL=C sort > "$(SYSROOT_SHARE)/defined-symbols.txt" for undef_sym in $$("$(WASM_NM)" --undefined-only "$(SYSROOT_LIB)"/libc.a "$(SYSROOT_LIB)"/libc-*.a "$(SYSROOT_LIB)"/*.o \ |grep ' U ' |sed 's/.* U //' |LC_ALL=C sort |uniq); do \ grep -q '\<'$$undef_sym'\>' "$(SYSROOT_SHARE)/defined-symbols.txt" || echo $$undef_sym; \ done | grep -v "^__mul" > "$(SYSROOT_SHARE)/undefined-symbols.txt" - grep '^_*wasi_' "$(SYSROOT_SHARE)/undefined-symbols.txt" \ + grep '^_*imported_wasi_' "$(SYSROOT_SHARE)/undefined-symbols.txt" \ > "$(SYSROOT_LIB)/libc.imports" # # Generate a test file that includes all public header files. # cd "$(SYSROOT)" && \ - for header in $$(find include -type f -not -name mman.h -not -name signal.h |grep -v /bits/); do \ + for header in $$(find include -type f -not -name mman.h -not -name signal.h -not -name times.h -not -name resource.h |grep -v /bits/); do \ echo '#include <'$$header'>' | sed 's/include\///' ; \ done |LC_ALL=C sort >share/$(MULTIARCH_TRIPLE)/include-all.c ; \ cd - >/dev/null @@ -465,7 +504,7 @@ finish: startup_files libc # # Test that it compiles. # - "$(WASM_CC)" $(WASM_CFLAGS) -fsyntax-only "$(SYSROOT_SHARE)/include-all.c" -Wno-\#warnings + $(WASM_CC) $(CFLAGS) -fsyntax-only "$(SYSROOT_SHARE)/include-all.c" -Wno-\#warnings # # Collect all the predefined macros, except for compiler version macros @@ -481,7 +520,7 @@ finish: startup_files libc @# @# TODO: Undefine __FLOAT128__ for now since it's not in clang 8.0. @# TODO: Filter out __FLT16_* for now, as not all versions of clang have these. - "$(WASM_CC)" $(WASM_CFLAGS) "$(SYSROOT_SHARE)/include-all.c" \ + $(WASM_CC) $(CFLAGS) "$(SYSROOT_SHARE)/include-all.c" \ -isystem $(SYSROOT_INC) \ -std=gnu17 \ -E -dM -Wno-\#warnings \ @@ -492,6 +531,8 @@ finish: startup_files libc -U__clang_minor__ \ -U__clang_patchlevel__ \ -U__clang_version__ \ + -U__clang_literal_encoding__ \ + -U__clang_wide_literal_encoding__ \ -U__GNUC__ \ -U__GNUC_MINOR__ \ -U__GNUC_PATCHLEVEL__ \ @@ -505,10 +546,6 @@ finish: startup_files libc # This ignores whitespace because on Windows the output has CRLF line endings. diff -wur "$(CURDIR)/expected/$(MULTIARCH_TRIPLE)" "$(SYSROOT_SHARE)" - # - # The build succeeded! The generated sysroot is in $(SYSROOT). - # - install: finish mkdir -p "$(INSTALL_DIR)" cp -r "$(SYSROOT)/lib" "$(SYSROOT)/share" "$(SYSROOT)/include" "$(INSTALL_DIR)" diff --git a/README.md b/README.md index 367c4d3..0cb697d 100644 --- a/README.md +++ b/README.md @@ -43,4 +43,8 @@ or libc++abi.a, respectively, so they may not be usable without extra setup. This is one of the things [wasi-sdk] simplifies, as it includes cross-compiled builds of compiler-rt, libc++.a, and libc++abi.a. +## Arch Linux AUR package +For Arch Linux users, there's an unofficial AUR package tracking this git repo that can be installed under the name [wasi-libc-git]. + [wasi-sdk]: https://github.com/WebAssembly/wasi-sdk +[wasi-libc-git]: https://aur.archlinux.org/packages/wasi-libc-git/ diff --git a/dlmalloc/src/dlmalloc.c b/dlmalloc/src/dlmalloc.c index dab8df5..331536b 100644 --- a/dlmalloc/src/dlmalloc.c +++ b/dlmalloc/src/dlmalloc.c @@ -91,3 +91,8 @@ void* aligned_alloc(size_t alignment, size_t bytes) { size_t malloc_usable_size(void *ptr) { return dlmalloc_usable_size(ptr); } + +// Define these to satisfy musl references. +void *__libc_malloc(size_t) __attribute__((alias("malloc"))); +void __libc_free(void *) __attribute__((alias("free"))); +void *__libc_calloc(size_t nmemb, size_t size) __attribute__((alias("calloc"))); diff --git a/expected/wasm32-wasi/defined-symbols.txt b/expected/wasm32-wasi/defined-symbols.txt index c3efc08..b8d2ba8 100644 --- a/expected/wasm32-wasi/defined-symbols.txt +++ b/expected/wasm32-wasi/defined-symbols.txt @@ -11,11 +11,14 @@ _IO_putc _IO_putc_unlocked __EINVAL __ENOMEM +__SIG_ERR +__SIG_IGN __asctime_r __assert_fail __c_dot_utf8 __c_dot_utf8_locale __c_locale +__clock __clock_gettime __cos __cosdf @@ -132,6 +135,9 @@ __lgamma_r __lgammaf_r __lgammal_r __libc +__libc_calloc +__libc_free +__libc_malloc __loc_is_allocated __localtime_r __log2_data @@ -145,6 +151,7 @@ __math_divzero __math_divzerof __math_invalid __math_invalidf +__math_invalidl __math_oflow __math_oflowf __math_uflow @@ -181,6 +188,7 @@ __rem_pio2 __rem_pio2_large __rem_pio2f __rem_pio2l +__rsqrt_tab __secs_to_tm __secs_to_zone __seed48 @@ -227,6 +235,7 @@ __strtoull_internal __strtoumax_internal __strxfrm_l __sysinfo +__sysv_signal __tan __tandf __tanl @@ -249,7 +258,54 @@ __uflow __unlist_locked_file __uselocale __utc +__wasi_args_get +__wasi_args_sizes_get +__wasi_clock_res_get +__wasi_clock_time_get +__wasi_environ_get +__wasi_environ_sizes_get +__wasi_fd_advise +__wasi_fd_allocate +__wasi_fd_close +__wasi_fd_datasync +__wasi_fd_fdstat_get +__wasi_fd_fdstat_set_flags +__wasi_fd_fdstat_set_rights +__wasi_fd_filestat_get +__wasi_fd_filestat_set_size +__wasi_fd_filestat_set_times +__wasi_fd_pread +__wasi_fd_prestat_dir_name +__wasi_fd_prestat_get +__wasi_fd_pwrite +__wasi_fd_read +__wasi_fd_readdir +__wasi_fd_renumber +__wasi_fd_seek +__wasi_fd_sync +__wasi_fd_tell +__wasi_fd_write +__wasi_path_create_directory +__wasi_path_filestat_get +__wasi_path_filestat_set_times +__wasi_path_link +__wasi_path_open +__wasi_path_readlink +__wasi_path_remove_directory +__wasi_path_rename +__wasi_path_symlink +__wasi_path_unlink_file +__wasi_poll_oneoff +__wasi_proc_exit +__wasi_proc_raise +__wasi_random_get +__wasi_sched_yield +__wasi_sock_recv +__wasi_sock_send +__wasi_sock_shutdown +__wasilibc_access __wasilibc_cwd +__wasilibc_deinitialize_environ __wasilibc_ensure_environ __wasilibc_environ __wasilibc_environ @@ -257,13 +313,35 @@ __wasilibc_fd_renumber __wasilibc_find_abspath __wasilibc_find_relpath __wasilibc_find_relpath_alloc +__wasilibc_get_environ __wasilibc_initialize_environ +__wasilibc_link +__wasilibc_link_newat +__wasilibc_link_oldat +__wasilibc_maybe_reinitialize_environ_eagerly +__wasilibc_maybe_reinitialize_environ_eagerly +__wasilibc_nocwd___wasilibc_rmdirat +__wasilibc_nocwd___wasilibc_unlinkat +__wasilibc_nocwd_faccessat +__wasilibc_nocwd_fstatat +__wasilibc_nocwd_linkat +__wasilibc_nocwd_mkdirat_nomode +__wasilibc_nocwd_openat_nomode +__wasilibc_nocwd_opendirat +__wasilibc_nocwd_readlinkat +__wasilibc_nocwd_renameat +__wasilibc_nocwd_scandirat +__wasilibc_nocwd_symlinkat +__wasilibc_nocwd_utimensat __wasilibc_open_nomode -__wasilibc_openat_nomode __wasilibc_register_preopened_fd +__wasilibc_rename_newat +__wasilibc_rename_oldat __wasilibc_rmdirat +__wasilibc_stat __wasilibc_tell __wasilibc_unlinkat +__wasilibc_utimens __wasm_call_dtors __wcscoll_l __wcsftime_l @@ -322,6 +400,7 @@ atoll basename bcmp bcopy +bsd_signal bsearch btowc bzero @@ -594,6 +673,7 @@ getline getopt getopt_long getopt_long_only +getpid getrusage getsockopt getsubopt @@ -773,10 +853,12 @@ memset mkdir mkdirat mktime +mmap modf modff modfl mrand48 +munmap nan nanf nanl @@ -828,6 +910,7 @@ printf program_invocation_name program_invocation_short_name pselect +psignal putc putc_unlocked putchar @@ -843,6 +926,7 @@ pwrite pwritev qsort quick_exit +raise rand rand_r random @@ -904,6 +988,7 @@ setlocale setstate setvbuf shutdown +signal signgam significand significandf @@ -965,6 +1050,7 @@ strpbrk strptime strrchr strsep +strsignal strspn strstr strtod diff --git a/expected/wasm32-wasi/include-all.c b/expected/wasm32-wasi/include-all.c index f6ecbce..86297f3 100644 --- a/expected/wasm32-wasi/include-all.c +++ b/expected/wasm32-wasi/include-all.c @@ -137,7 +137,6 @@ #include #include #include -#include #include #include #include @@ -146,7 +145,6 @@ #include #include #include -#include #include #include #include @@ -166,6 +164,7 @@ #include #include #include +#include #include #include #include diff --git a/expected/wasm32-wasi/predefined-macros.txt b/expected/wasm32-wasi/predefined-macros.txt index 1c8283a..c1bb19e 100644 --- a/expected/wasm32-wasi/predefined-macros.txt +++ b/expected/wasm32-wasi/predefined-macros.txt @@ -46,6 +46,7 @@ #define ARG_MAX 131072 #define ARMAG "!\n" #define AT_EACCESS (0x0) +#define AT_FDCWD (-2) #define AT_REMOVEDIR (0x4) #define AT_SYMLINK_FOLLOW (0x2) #define AT_SYMLINK_NOFOLLOW (0x1) @@ -891,6 +892,7 @@ #define IP_PMTUDISC_PROBE 3 #define IP_PMTUDISC_WANT 1 #define IP_RECVERR 11 +#define IP_RECVERR_RFC4884 26 #define IP_RECVFRAGSIZE 25 #define IP_RECVOPTS 6 #define IP_RECVORIGDSTADDR IP_ORIGDSTADDR @@ -1705,6 +1707,7 @@ #define TCP_CONGESTION 13 #define TCP_CORK 3 #define TCP_DEFER_ACCEPT 9 +#define TCP_ENCAP_ESPINTCP 7 #define TCP_ESTABLISHED 1 #define TCP_FASTOPEN 23 #define TCP_FASTOPEN_CONNECT 30 @@ -1723,7 +1726,8 @@ #define TCP_MAXSEG 2 #define TCP_MD5SIG 14 #define TCP_MD5SIG_EXT 32 -#define TCP_MD5SIG_FLAG_PREFIX 1 +#define TCP_MD5SIG_FLAG_IFINDEX 0x2 +#define TCP_MD5SIG_FLAG_PREFIX 0x1 #define TCP_MD5SIG_MAXKEYLEN 80 #define TCP_NODELAY 1 #define TCP_NOTSENT_LOWAT 25 @@ -2305,14 +2309,12 @@ #define _SYS_PARAM_H #define _SYS_RANDOM_H #define _SYS_REG_H -#define _SYS_RESOURCE_H #define _SYS_SELECT_H #define _SYS_SOCKET_H #define _SYS_STAT_H #define _SYS_SYSCALL_H #define _SYS_SYSINFO_H #define _SYS_TIMEB_H -#define _SYS_TIMES_H #define _SYS_TIMEX_H #define _SYS_TIME_H #define _SYS_TTYDEFAULTS_H @@ -2893,15 +2895,15 @@ #define __WASI_ERRNO_TIMEDOUT (UINT16_C(73)) #define __WASI_ERRNO_TXTBSY (UINT16_C(74)) #define __WASI_ERRNO_XDEV (UINT16_C(75)) -#define __WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP (UINT16_C(1)) +#define __WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP ((__wasi_eventrwflags_t)(1 << 0)) #define __WASI_EVENTTYPE_CLOCK (UINT8_C(0)) #define __WASI_EVENTTYPE_FD_READ (UINT8_C(1)) #define __WASI_EVENTTYPE_FD_WRITE (UINT8_C(2)) -#define __WASI_FDFLAGS_APPEND (UINT16_C(1)) -#define __WASI_FDFLAGS_DSYNC (UINT16_C(2)) -#define __WASI_FDFLAGS_NONBLOCK (UINT16_C(4)) -#define __WASI_FDFLAGS_RSYNC (UINT16_C(8)) -#define __WASI_FDFLAGS_SYNC (UINT16_C(16)) +#define __WASI_FDFLAGS_APPEND ((__wasi_fdflags_t)(1 << 0)) +#define __WASI_FDFLAGS_DSYNC ((__wasi_fdflags_t)(1 << 1)) +#define __WASI_FDFLAGS_NONBLOCK ((__wasi_fdflags_t)(1 << 2)) +#define __WASI_FDFLAGS_RSYNC ((__wasi_fdflags_t)(1 << 3)) +#define __WASI_FDFLAGS_SYNC ((__wasi_fdflags_t)(1 << 4)) #define __WASI_FILETYPE_BLOCK_DEVICE (UINT8_C(1)) #define __WASI_FILETYPE_CHARACTER_DEVICE (UINT8_C(2)) #define __WASI_FILETYPE_DIRECTORY (UINT8_C(3)) @@ -2910,50 +2912,50 @@ #define __WASI_FILETYPE_SOCKET_STREAM (UINT8_C(6)) #define __WASI_FILETYPE_SYMBOLIC_LINK (UINT8_C(7)) #define __WASI_FILETYPE_UNKNOWN (UINT8_C(0)) -#define __WASI_FSTFLAGS_ATIM (UINT16_C(1)) -#define __WASI_FSTFLAGS_ATIM_NOW (UINT16_C(2)) -#define __WASI_FSTFLAGS_MTIM (UINT16_C(4)) -#define __WASI_FSTFLAGS_MTIM_NOW (UINT16_C(8)) -#define __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW (UINT32_C(1)) -#define __WASI_OFLAGS_CREAT (UINT16_C(1)) -#define __WASI_OFLAGS_DIRECTORY (UINT16_C(2)) -#define __WASI_OFLAGS_EXCL (UINT16_C(4)) -#define __WASI_OFLAGS_TRUNC (UINT16_C(8)) +#define __WASI_FSTFLAGS_ATIM ((__wasi_fstflags_t)(1 << 0)) +#define __WASI_FSTFLAGS_ATIM_NOW ((__wasi_fstflags_t)(1 << 1)) +#define __WASI_FSTFLAGS_MTIM ((__wasi_fstflags_t)(1 << 2)) +#define __WASI_FSTFLAGS_MTIM_NOW ((__wasi_fstflags_t)(1 << 3)) +#define __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW ((__wasi_lookupflags_t)(1 << 0)) +#define __WASI_OFLAGS_CREAT ((__wasi_oflags_t)(1 << 0)) +#define __WASI_OFLAGS_DIRECTORY ((__wasi_oflags_t)(1 << 1)) +#define __WASI_OFLAGS_EXCL ((__wasi_oflags_t)(1 << 2)) +#define __WASI_OFLAGS_TRUNC ((__wasi_oflags_t)(1 << 3)) #define __WASI_PREOPENTYPE_DIR (UINT8_C(0)) -#define __WASI_RIFLAGS_RECV_PEEK (UINT16_C(1)) -#define __WASI_RIFLAGS_RECV_WAITALL (UINT16_C(2)) -#define __WASI_RIGHTS_FD_ADVISE (UINT64_C(128)) -#define __WASI_RIGHTS_FD_ALLOCATE (UINT64_C(256)) -#define __WASI_RIGHTS_FD_DATASYNC (UINT64_C(1)) -#define __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS (UINT64_C(8)) -#define __WASI_RIGHTS_FD_FILESTAT_GET (UINT64_C(2097152)) -#define __WASI_RIGHTS_FD_FILESTAT_SET_SIZE (UINT64_C(4194304)) -#define __WASI_RIGHTS_FD_FILESTAT_SET_TIMES (UINT64_C(8388608)) -#define __WASI_RIGHTS_FD_READ (UINT64_C(2)) -#define __WASI_RIGHTS_FD_READDIR (UINT64_C(16384)) -#define __WASI_RIGHTS_FD_SEEK (UINT64_C(4)) -#define __WASI_RIGHTS_FD_SYNC (UINT64_C(16)) -#define __WASI_RIGHTS_FD_TELL (UINT64_C(32)) -#define __WASI_RIGHTS_FD_WRITE (UINT64_C(64)) -#define __WASI_RIGHTS_PATH_CREATE_DIRECTORY (UINT64_C(512)) -#define __WASI_RIGHTS_PATH_CREATE_FILE (UINT64_C(1024)) -#define __WASI_RIGHTS_PATH_FILESTAT_GET (UINT64_C(262144)) -#define __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE (UINT64_C(524288)) -#define __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES (UINT64_C(1048576)) -#define __WASI_RIGHTS_PATH_LINK_SOURCE (UINT64_C(2048)) -#define __WASI_RIGHTS_PATH_LINK_TARGET (UINT64_C(4096)) -#define __WASI_RIGHTS_PATH_OPEN (UINT64_C(8192)) -#define __WASI_RIGHTS_PATH_READLINK (UINT64_C(32768)) -#define __WASI_RIGHTS_PATH_REMOVE_DIRECTORY (UINT64_C(33554432)) -#define __WASI_RIGHTS_PATH_RENAME_SOURCE (UINT64_C(65536)) -#define __WASI_RIGHTS_PATH_RENAME_TARGET (UINT64_C(131072)) -#define __WASI_RIGHTS_PATH_SYMLINK (UINT64_C(16777216)) -#define __WASI_RIGHTS_PATH_UNLINK_FILE (UINT64_C(67108864)) -#define __WASI_RIGHTS_POLL_FD_READWRITE (UINT64_C(134217728)) -#define __WASI_RIGHTS_SOCK_SHUTDOWN (UINT64_C(268435456)) -#define __WASI_ROFLAGS_RECV_DATA_TRUNCATED (UINT16_C(1)) -#define __WASI_SDFLAGS_RD (UINT8_C(1)) -#define __WASI_SDFLAGS_WR (UINT8_C(2)) +#define __WASI_RIFLAGS_RECV_PEEK ((__wasi_riflags_t)(1 << 0)) +#define __WASI_RIFLAGS_RECV_WAITALL ((__wasi_riflags_t)(1 << 1)) +#define __WASI_RIGHTS_FD_ADVISE ((__wasi_rights_t)(1 << 7)) +#define __WASI_RIGHTS_FD_ALLOCATE ((__wasi_rights_t)(1 << 8)) +#define __WASI_RIGHTS_FD_DATASYNC ((__wasi_rights_t)(1 << 0)) +#define __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(1 << 3)) +#define __WASI_RIGHTS_FD_FILESTAT_GET ((__wasi_rights_t)(1 << 21)) +#define __WASI_RIGHTS_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(1 << 22)) +#define __WASI_RIGHTS_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(1 << 23)) +#define __WASI_RIGHTS_FD_READ ((__wasi_rights_t)(1 << 1)) +#define __WASI_RIGHTS_FD_READDIR ((__wasi_rights_t)(1 << 14)) +#define __WASI_RIGHTS_FD_SEEK ((__wasi_rights_t)(1 << 2)) +#define __WASI_RIGHTS_FD_SYNC ((__wasi_rights_t)(1 << 4)) +#define __WASI_RIGHTS_FD_TELL ((__wasi_rights_t)(1 << 5)) +#define __WASI_RIGHTS_FD_WRITE ((__wasi_rights_t)(1 << 6)) +#define __WASI_RIGHTS_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(1 << 9)) +#define __WASI_RIGHTS_PATH_CREATE_FILE ((__wasi_rights_t)(1 << 10)) +#define __WASI_RIGHTS_PATH_FILESTAT_GET ((__wasi_rights_t)(1 << 18)) +#define __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(1 << 19)) +#define __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(1 << 20)) +#define __WASI_RIGHTS_PATH_LINK_SOURCE ((__wasi_rights_t)(1 << 11)) +#define __WASI_RIGHTS_PATH_LINK_TARGET ((__wasi_rights_t)(1 << 12)) +#define __WASI_RIGHTS_PATH_OPEN ((__wasi_rights_t)(1 << 13)) +#define __WASI_RIGHTS_PATH_READLINK ((__wasi_rights_t)(1 << 15)) +#define __WASI_RIGHTS_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(1 << 25)) +#define __WASI_RIGHTS_PATH_RENAME_SOURCE ((__wasi_rights_t)(1 << 16)) +#define __WASI_RIGHTS_PATH_RENAME_TARGET ((__wasi_rights_t)(1 << 17)) +#define __WASI_RIGHTS_PATH_SYMLINK ((__wasi_rights_t)(1 << 24)) +#define __WASI_RIGHTS_PATH_UNLINK_FILE ((__wasi_rights_t)(1 << 26)) +#define __WASI_RIGHTS_POLL_FD_READWRITE ((__wasi_rights_t)(1 << 27)) +#define __WASI_RIGHTS_SOCK_SHUTDOWN ((__wasi_rights_t)(1 << 28)) +#define __WASI_ROFLAGS_RECV_DATA_TRUNCATED ((__wasi_roflags_t)(1 << 0)) +#define __WASI_SDFLAGS_RD ((__wasi_sdflags_t)(1 << 0)) +#define __WASI_SDFLAGS_WR ((__wasi_sdflags_t)(1 << 1)) #define __WASI_SIGNAL_ABRT (UINT8_C(6)) #define __WASI_SIGNAL_ALRM (UINT8_C(14)) #define __WASI_SIGNAL_BUS (UINT8_C(7)) @@ -2985,7 +2987,7 @@ #define __WASI_SIGNAL_WINCH (UINT8_C(27)) #define __WASI_SIGNAL_XCPU (UINT8_C(23)) #define __WASI_SIGNAL_XFSZ (UINT8_C(24)) -#define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME (UINT16_C(1)) +#define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME ((__wasi_subclockflags_t)(1 << 0)) #define __WASI_WHENCE_CUR (UINT8_C(1)) #define __WASI_WHENCE_END (UINT8_C(2)) #define __WASI_WHENCE_SET (UINT8_C(0)) @@ -3021,6 +3023,7 @@ #define __wasi_libc_environ_h #define __wasi_libc_find_relpath_h #define __wasi_libc_h +#define __wasi_libc_nocwd_h #define __wasilibc___errno_h #define __wasilibc___errno_values_h #define __wasilibc___fd_set_h @@ -3120,6 +3123,8 @@ #define cbrt(x) __tg_real(cbrt, (x)) #define ceil(x) __tg_real(ceil, (x)) #define cimag(x) __tg_complex_retreal(cimag, (x)) +#define cimagf(x) (__builtin_cimagf(x)) +#define cimagl(x) (__builtin_cimagl(x)) #define clrbit(x,i) __bitop(x,i,&=~) #define compl ~ #define complex _Complex @@ -3129,6 +3134,8 @@ #define cosh(x) __tg_real_complex(cosh, (x)) #define cproj(x) __tg_complex(cproj, (x)) #define creal(x) __tg_complex_retreal(creal, (x)) +#define crealf(x) (__builtin_crealf(x)) +#define creall(x) (__builtin_creall(x)) #define creat64 creat #define d_fileno d_ino #define direct dirent diff --git a/expected/wasm32-wasi/undefined-symbols.txt b/expected/wasm32-wasi/undefined-symbols.txt index 47e3106..dd981ec 100644 --- a/expected/wasm32-wasi/undefined-symbols.txt +++ b/expected/wasm32-wasi/undefined-symbols.txt @@ -11,6 +11,51 @@ __floatunsitf __getf2 __gttf2 __heap_base +__imported_wasi_snapshot_preview1_args_get +__imported_wasi_snapshot_preview1_args_sizes_get +__imported_wasi_snapshot_preview1_clock_res_get +__imported_wasi_snapshot_preview1_clock_time_get +__imported_wasi_snapshot_preview1_environ_get +__imported_wasi_snapshot_preview1_environ_sizes_get +__imported_wasi_snapshot_preview1_fd_advise +__imported_wasi_snapshot_preview1_fd_allocate +__imported_wasi_snapshot_preview1_fd_close +__imported_wasi_snapshot_preview1_fd_datasync +__imported_wasi_snapshot_preview1_fd_fdstat_get +__imported_wasi_snapshot_preview1_fd_fdstat_set_flags +__imported_wasi_snapshot_preview1_fd_fdstat_set_rights +__imported_wasi_snapshot_preview1_fd_filestat_get +__imported_wasi_snapshot_preview1_fd_filestat_set_size +__imported_wasi_snapshot_preview1_fd_filestat_set_times +__imported_wasi_snapshot_preview1_fd_pread +__imported_wasi_snapshot_preview1_fd_prestat_dir_name +__imported_wasi_snapshot_preview1_fd_prestat_get +__imported_wasi_snapshot_preview1_fd_pwrite +__imported_wasi_snapshot_preview1_fd_read +__imported_wasi_snapshot_preview1_fd_readdir +__imported_wasi_snapshot_preview1_fd_renumber +__imported_wasi_snapshot_preview1_fd_seek +__imported_wasi_snapshot_preview1_fd_sync +__imported_wasi_snapshot_preview1_fd_tell +__imported_wasi_snapshot_preview1_fd_write +__imported_wasi_snapshot_preview1_path_create_directory +__imported_wasi_snapshot_preview1_path_filestat_get +__imported_wasi_snapshot_preview1_path_filestat_set_times +__imported_wasi_snapshot_preview1_path_link +__imported_wasi_snapshot_preview1_path_open +__imported_wasi_snapshot_preview1_path_readlink +__imported_wasi_snapshot_preview1_path_remove_directory +__imported_wasi_snapshot_preview1_path_rename +__imported_wasi_snapshot_preview1_path_symlink +__imported_wasi_snapshot_preview1_path_unlink_file +__imported_wasi_snapshot_preview1_poll_oneoff +__imported_wasi_snapshot_preview1_proc_exit +__imported_wasi_snapshot_preview1_proc_raise +__imported_wasi_snapshot_preview1_random_get +__imported_wasi_snapshot_preview1_sched_yield +__imported_wasi_snapshot_preview1_sock_recv +__imported_wasi_snapshot_preview1_sock_send +__imported_wasi_snapshot_preview1_sock_shutdown __letf2 __lttf2 __netf2 @@ -19,48 +64,5 @@ __subtf3 __trunctfdf2 __trunctfsf2 __unordtf2 -__wasi_args_get -__wasi_args_sizes_get -__wasi_clock_res_get -__wasi_clock_time_get -__wasi_environ_get -__wasi_environ_sizes_get -__wasi_fd_advise -__wasi_fd_allocate -__wasi_fd_close -__wasi_fd_datasync -__wasi_fd_fdstat_get -__wasi_fd_fdstat_set_flags -__wasi_fd_filestat_get -__wasi_fd_filestat_set_size -__wasi_fd_filestat_set_times -__wasi_fd_pread -__wasi_fd_prestat_dir_name -__wasi_fd_prestat_get -__wasi_fd_pwrite -__wasi_fd_read -__wasi_fd_readdir -__wasi_fd_renumber -__wasi_fd_seek -__wasi_fd_sync -__wasi_fd_tell -__wasi_fd_write -__wasi_path_create_directory -__wasi_path_filestat_get -__wasi_path_filestat_set_times -__wasi_path_link -__wasi_path_open -__wasi_path_readlink -__wasi_path_remove_directory -__wasi_path_rename -__wasi_path_symlink -__wasi_path_unlink_file -__wasi_poll_oneoff -__wasi_proc_exit -__wasi_random_get -__wasi_sched_yield -__wasi_sock_recv -__wasi_sock_send -__wasi_sock_shutdown __wasm_call_ctors main diff --git a/libc-bottom-half/clocks/clock.c b/libc-bottom-half/clocks/clock.c new file mode 100644 index 0000000..6767d73 --- /dev/null +++ b/libc-bottom-half/clocks/clock.c @@ -0,0 +1,35 @@ +#define _WASI_EMULATED_PROCESS_CLOCKS +#include +#include +#include + +_Static_assert( + CLOCKS_PER_SEC == NSEC_PER_SEC, + "This implementation assumes that `clock` is in nanoseconds" +); + +// Snapshot of the monotonic clock at the start of the program. +static __wasi_timestamp_t start; + +// Use a priority of 10 to run fairly early in the implementation-reserved +// constructor priority range. +__attribute__((constructor(10))) +static void init(void) { + (void)__wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC, 0, &start); +} + +// Define the libc symbol as `__clock` so that we can reliably call it +// from elsewhere in libc. +clock_t __clock(void) { + // Use `MONOTONIC` instead of `PROCESS_CPUTIME_ID` since WASI doesn't have + // an inherent concept of a process. Note that this means we'll incorrectly + // include time from other processes, so this function is only declared by + // the headers if `_WASI_EMULATED_PROCESS_CLOCKS` is defined. + __wasi_timestamp_t now = 0; + (void)__wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC, 0, &now); + return now - start; +} + +// Define a user-visible alias as a weak symbol. +__attribute__((__weak__, __alias__("__clock"))) +clock_t clock(void); diff --git a/libc-bottom-half/clocks/getrusage.c b/libc-bottom-half/clocks/getrusage.c new file mode 100644 index 0000000..d0113c5 --- /dev/null +++ b/libc-bottom-half/clocks/getrusage.c @@ -0,0 +1,28 @@ +#define _WASI_EMULATED_PROCESS_CLOCKS +#include +#include +#include +#include +#include + +// `clock` is a weak symbol so that application code can override it. +// We want to use the function in libc, so use the libc-internal name. +clock_t __clock(void); + +int getrusage(int who, struct rusage *r_usage) { + switch (who) { + case RUSAGE_SELF: { + __wasi_timestamp_t usertime = __clock(); + *r_usage = (struct rusage) { + .ru_utime = timestamp_to_timeval(usertime) + }; + return 0; + } + case RUSAGE_CHILDREN: + *r_usage = (struct rusage) {}; + return 0; + default: + errno = EINVAL; + return -1; + } +} diff --git a/libc-bottom-half/clocks/times.c b/libc-bottom-half/clocks/times.c new file mode 100644 index 0000000..e245569 --- /dev/null +++ b/libc-bottom-half/clocks/times.c @@ -0,0 +1,26 @@ +#define _WASI_EMULATED_PROCESS_CLOCKS +#include +#include +#include +#include + +_Static_assert( + CLOCKS_PER_SEC == NSEC_PER_SEC, + "This implementation assumes that `clock` is in nanoseconds" +); + +// `clock` is a weak symbol so that application code can override it. +// We want to use the function in libc, so use the libc-internal name. +clock_t __clock(void); + +clock_t times(struct tms *buffer) { + __wasi_timestamp_t user = __clock(); + *buffer = (struct tms){ + .tms_utime = user, + .tms_cutime = user + }; + + __wasi_timestamp_t realtime = 0; + (void)__wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC, 0, &realtime); + return realtime; +} diff --git a/libc-bottom-half/cloudlibc/src/common/errno.h b/libc-bottom-half/cloudlibc/src/common/errno.h index ebc1734..7d178fb 100644 --- a/libc-bottom-half/cloudlibc/src/common/errno.h +++ b/libc-bottom-half/cloudlibc/src/common/errno.h @@ -7,78 +7,16 @@ #include -#ifdef __wasilibc_unmodified_upstream -// Translates ENOTCAPABLE to ENOTDIR if not a directory. -static inline __wasi_errno_t errno_fixup_directory(__wasi_fd_t fd, - __wasi_errno_t error) { - if (error == __WASI_ENOTCAPABLE) { - __wasi_fdstat_t fds; - if (__wasi_fd_stat_get(fd, &fds) == 0 && - fds.fs_filetype != __WASI_FILETYPE_DIRECTORY) - return __WASI_ENOTDIR; - } - return error; -} -#else // WASI syscalls should just return ENOTDIR if that's what the problem is. static inline __wasi_errno_t errno_fixup_directory(__wasi_fd_t fd, __wasi_errno_t error) { return error; } -#endif -#ifdef __wasilibc_unmodified_upstream // posix_spawn etc. -// Translates ENOTCAPABLE to EBADF if a regular file or EACCES otherwise. -static inline __wasi_errno_t errno_fixup_executable(__wasi_fd_t fd, - __wasi_errno_t error) { - if (error == __WASI_ENOTCAPABLE) { - __wasi_fdstat_t fds; - if (__wasi_fd_stat_get(fd, &fds) == 0) - return fds.fs_filetype == __WASI_FILETYPE_REGULAR_FILE - ? __WASI_EBADF - : __WASI_EACCES; - } - return error; -} -#endif - -#ifdef __wasilibc_unmodified_upstream // process file descriptors -// Translates ENOTCAPABLE to EINVAL if not a process. -static inline __wasi_errno_t errno_fixup_process(__wasi_fd_t fd, - __wasi_errno_t error) { - if (error == __WASI_ENOTCAPABLE) { - __wasi_fdstat_t fds; - if (__wasi_fd_stat_get(fd, &fds) == 0 && - fds.fs_filetype != __WASI_FILETYPE_PROCESS) - return __WASI_EINVAL; - } - return error; -} -#endif - -#ifdef __wasilibc_unmodified_upstream -// Translates ENOTCAPABLE to ENOTSOCK if not a socket. -static inline __wasi_errno_t errno_fixup_socket(__wasi_fd_t fd, - __wasi_errno_t error) { - if (error == __WASI_ENOTCAPABLE) { - __wasi_fdstat_t fds; - if (__wasi_fd_stat_get(fd, &fds) == 0 && -#ifdef __wasilibc_unmodified_upstream // don't hard-code magic numbers - (fds.fs_filetype & 0xf0) != 0x80) -#else - (fds.fs_filetype != __WASI_FILETYPE_SOCKET_STREAM && - fds.fs_filetype != __WASI_FILETYPE_SOCKET_DGRAM)) -#endif - return __WASI_ENOTSOCK; - } - return error; -} -#else // WASI syscalls should just return ENOTSOCK if that's what the problem is. static inline __wasi_errno_t errno_fixup_socket(__wasi_fd_t fd, __wasi_errno_t error) { return error; } -#endif #endif diff --git a/libc-bottom-half/cloudlibc/src/include/stdlib.h b/libc-bottom-half/cloudlibc/src/include/stdlib.h index e30b8de..ff48afb 100644 --- a/libc-bottom-half/cloudlibc/src/include/stdlib.h +++ b/libc-bottom-half/cloudlibc/src/include/stdlib.h @@ -69,223 +69,18 @@ #include <_/limits.h> #include <_/types.h> -#ifdef __wasilibc_unmodified_upstream -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -#define RAND_MAX _INT_MAX - -#define NULL _NULL - -typedef struct { - int quot; - int rem; -} div_t; - -typedef struct { - long quot; - long rem; -} ldiv_t; - -typedef struct { - long long quot; - long long rem; -} lldiv_t; - -#ifndef _SIZE_T_DECLARED -typedef __size_t size_t; -#define _SIZE_T_DECLARED -#endif -#ifndef _WCHAR_T_DECLARED -typedef __wchar_t wchar_t; -#define _WCHAR_T_DECLARED -#endif - -#ifdef __wasilibc_unmodified_upstream -// Process wide locale always uses ASCII. -#define MB_CUR_MAX ((size_t)1) -#endif - -// Keep existing code happy that assumes that MB_CUR_MAX_L is a macro. -#define MB_CUR_MAX_L MB_CUR_MAX_L - -#define alloca(size) __builtin_alloca(size) -#endif - __BEGIN_DECLS _Noreturn void _Exit(int); -#ifdef __wasilibc_unmodified_upstream -size_t MB_CUR_MAX_L(__locale_t); -long a64l(const char *); -#endif _Noreturn void abort(void); -#ifdef __wasilibc_unmodified_upstream -int abs(int) __pure2; -int at_quick_exit(void (*)(void)); -int atexit(void (*)(void)); -void *aligned_alloc(size_t, size_t); -__uint32_t arc4random(void); -void arc4random_buf(void *, size_t); -__uint32_t arc4random_uniform(__uint32_t); -double atof(const char *); -int atoi(const char *); -long atol(const char *); -long long atoll(const char *); -void *bsearch(const void *, const void *, size_t, size_t, - int (*)(const void *, const void *)); -#endif void *calloc(size_t, size_t); -#ifdef __wasilibc_unmodified_upstream -div_t div(int, int) __pure2; -double drand48(void); -double erand48(__uint16_t *); -#endif _Noreturn void exit(int); void free(void *); -#ifdef __wasilibc_unmodified_upstream -char *getenv(const char *); -int getsubopt(char **, char *const *, char **); -long jrand48(__uint16_t *); -int l64a_r(long, char *, int); -long labs(long) __pure2; -ldiv_t ldiv(long, long) __pure2; -long long llabs(long long) __pure2; -lldiv_t lldiv(long long, long long) __pure2; -long lrand48(void); -#endif void *malloc(size_t); -#ifdef __wasilibc_unmodified_upstream -int mblen(const char *, size_t); -int mblen_l(const char *, size_t, __locale_t); -size_t mbstowcs(wchar_t *__restrict, const char *__restrict, size_t); -size_t mbstowcs_l(wchar_t *__restrict, const char *__restrict, size_t, - __locale_t); -int mbtowc(wchar_t *__restrict, const char *__restrict, size_t); -int mbtowc_l(wchar_t *__restrict, const char *__restrict, size_t, __locale_t); -long mrand48(void); -long nrand48(__uint16_t *); -int posix_memalign(void **, size_t, size_t); -#endif void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); -#ifdef __wasilibc_unmodified_upstream -void qsort_r(void *, size_t, size_t, - int (*)(const void *, const void *, void *), void *); -_Noreturn void quick_exit(int); -int rand(void); -long random(void); -#endif void *realloc(void *, size_t); -#ifdef __wasilibc_unmodified_upstream -void *reallocarray(void *, size_t, size_t); -double strtod(const char *__restrict, char **__restrict); -double strtod_l(const char *__restrict, char **__restrict, __locale_t); -float strtof(const char *__restrict, char **__restrict); -float strtof_l(const char *__restrict, char **__restrict, __locale_t); -long strtol(const char *__restrict, char **__restrict, int); -long strtol_l(const char *__restrict, char **__restrict, int, __locale_t); -long double strtold(const char *__restrict, char **__restrict); -long double strtold_l(const char *__restrict, char **__restrict, __locale_t); -long long strtoll(const char *__restrict, char **__restrict, int); -long long strtoll_l(const char *__restrict, char **__restrict, int, __locale_t); -unsigned long strtoul(const char *__restrict, char **__restrict, int); -unsigned long strtoul_l(const char *__restrict, char **__restrict, int, - __locale_t); -unsigned long long strtoull(const char *__restrict, char **__restrict, int); -unsigned long long strtoull_l(const char *__restrict, char **__restrict, int, - __locale_t); -size_t wcstombs(char *__restrict, const wchar_t *__restrict, size_t); -size_t wcstombs_l(char *__restrict, const wchar_t *__restrict, size_t, - __locale_t); -int wctomb(char *, wchar_t); -int wctomb_l(char *, wchar_t, __locale_t); -#endif __END_DECLS #if _CLOUDLIBC_INLINE_FUNCTIONS -#ifdef __wasilibc_unmodified_upstream -static __inline double __atof(const char *__str) { - return strtod(__str, NULL); -} -#define atof(str) __atof(str) - -static __inline int __atoi(const char *__str) { - return (int)strtol(__str, NULL, 10); -} -#define atoi(str) __atoi(str) - -static __inline long __atol(const char *__str) { - return strtol(__str, NULL, 10); -} -#define atol(str) __atol(str) - -static __inline long long __atoll(const char *__str) { - return strtoll(__str, NULL, 10); -} -#define atoll(str) __atoll(str) - -static __inline int __abs(int __i) { - return __i < 0 ? -__i : __i; -} -#define abs(i) __abs(i) - -static __inline long __labs(long __i) { - return __i < 0 ? -__i : __i; -} -#define labs(i) __labs(i) - -static __inline long long __llabs(long long __i) { - return __i < 0 ? -__i : __i; -} -#define llabs(i) __llabs(i) - -static __inline div_t __div(int __numer, int __denom) { - div_t __res = {__numer / __denom, __numer % __denom}; - return __res; -} -#define div(numer, denom) __div(numer, denom) - -static __inline ldiv_t __ldiv(long __numer, long __denom) { - ldiv_t __res = {__numer / __denom, __numer % __denom}; - return __res; -} -#define ldiv(numer, denom) __ldiv(numer, denom) - -static __inline lldiv_t __lldiv(long long __numer, long long __denom) { - lldiv_t __res = {__numer / __denom, __numer % __denom}; - return __res; -} -#define lldiv(numer, denom) __lldiv(numer, denom) - -static __inline void *__bsearch(const void *__key, const void *__base, - size_t __nel, size_t __width, - int (*__compar)(const void *, const void *)) { - const char *__basep, *__obj; - size_t __mid, __skip; - int __cmp; - - __basep = (const char *)__base; - while (__nel > 0) { - // Pick pivot. - __mid = __nel / 2; - __obj = __basep + __mid * __width; - __cmp = __compar(__key, (const void *)__obj); - if (__cmp < 0) { - // key < obj. Restrict search to top of the list. - __nel = __mid; - } else if (__cmp > 0) { - // key > obj. Restrict search to bottom of the list. - __skip = __mid + 1; - __basep += __skip * __width; - __nel -= __skip; - } else { - return (void *)__obj; - } - } - return NULL; -} -#define bsearch(key, base, nel, width, compar) \ - __preserve_const(void, __bsearch, base, key, base, nel, width, compar) -#endif // qsort_r() implementation from Bentley and McIlroy's // "Engineering a Sort Function". diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c index 325093f..59fc027 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c @@ -25,12 +25,8 @@ DIR *fdopendir(int fd) { // Ensure that this is really a directory by already loading the first // chunk of data. __wasi_errno_t error = -#ifdef __wasilibc_unmodified_upstream - __wasi_file_readdir(fd, dirp->buffer, DIRENT_DEFAULT_BUFFER_SIZE, -#else // TODO: Remove the cast on `dirp->buffer` once the witx is updated with char8 support. __wasi_fd_readdir(fd, (uint8_t *)dirp->buffer, DIRENT_DEFAULT_BUFFER_SIZE, -#endif __WASI_DIRCOOKIE_START, &dirp->buffer_used); if (error != 0) { free(dirp->buffer); diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/opendirat.c b/libc-bottom-half/cloudlibc/src/libc/dirent/opendirat.c index c940d5f..e6d1c2a 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/opendirat.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/opendirat.c @@ -3,18 +3,15 @@ // SPDX-License-Identifier: BSD-2-Clause #include +#include #include #include #include #include -DIR *opendirat(int dir, const char *dirname) { +DIR *__wasilibc_nocwd_opendirat(int dir, const char *dirname) { // Open directory. -#ifdef __wasilibc_unmodified_upstream // avoid making a varargs call - int fd = openat(dir, dirname, O_RDONLY | O_NONBLOCK | O_DIRECTORY); -#else - int fd = __wasilibc_openat_nomode(dir, dirname, O_RDONLY | O_NONBLOCK | O_DIRECTORY); -#endif + int fd = __wasilibc_nocwd_openat_nomode(dir, dirname, O_RDONLY | O_NONBLOCK | O_DIRECTORY); if (fd == -1) return NULL; diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c index c4a2013..b5650d6 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c @@ -91,12 +91,8 @@ struct dirent *readdir(DIR *dirp) { // Load more directory entries and continue. __wasi_errno_t error = -#ifdef __wasilibc_unmodified_upstream - __wasi_file_readdir(dirp->fd, dirp->buffer, dirp->buffer_size, -#else // TODO: Remove the cast on `dirp->buffer` once the witx is updated with char8 support. __wasi_fd_readdir(dirp->fd, (uint8_t *)dirp->buffer, dirp->buffer_size, -#endif dirp->cookie, &dirp->buffer_used); if (error != 0) { errno = error; diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c b/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c index 83cdeb9..06feae9 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -17,19 +18,15 @@ static int sel_true(const struct dirent *de) { return 1; } -int scandirat(int dirfd, const char *dir, struct dirent ***namelist, - int (*sel)(const struct dirent *), - int (*compar)(const struct dirent **, const struct dirent **)) { +int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***namelist, + int (*sel)(const struct dirent *), + int (*compar)(const struct dirent **, const struct dirent **)) { // Match all files if no select function is provided. if (sel == NULL) sel = sel_true; // Open the directory. -#ifdef __wasilibc_unmodified_upstream // avoid making a varargs call - int fd = openat(dirfd, dir, O_RDONLY | O_NONBLOCK | O_DIRECTORY); -#else - int fd = __wasilibc_openat_nomode(dirfd, dir, O_RDONLY | O_NONBLOCK | O_DIRECTORY); -#endif + int fd = __wasilibc_nocwd_openat_nomode(dirfd, dir, O_RDONLY | O_NONBLOCK | O_DIRECTORY); if (fd == -1) return -1; @@ -119,12 +116,8 @@ int scandirat(int dirfd, const char *dir, struct dirent ***namelist, read_entries:; // Load more directory entries and continue. -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_file_readdir(fd, buffer, buffer_size, -#else // TODO: Remove the cast on `buffer` once the witx is updated with char8 support. __wasi_errno_t error = __wasi_fd_readdir(fd, (uint8_t *)buffer, buffer_size, -#endif cookie, &buffer_used); if (error != 0) { errno = error; diff --git a/libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c b/libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c index d4e5597..5d4055d 100644 --- a/libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c +++ b/libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c @@ -18,11 +18,7 @@ int fcntl(int fildes, int cmd, ...) { case F_GETFL: { // Obtain the flags and the rights of the descriptor. __wasi_fdstat_t fds; -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_fd_stat_get(fildes, &fds); -#else __wasi_errno_t error = __wasi_fd_fdstat_get(fildes, &fds); -#endif if (error != 0) { errno = error; return -1; @@ -31,26 +27,13 @@ int fcntl(int fildes, int cmd, ...) { // Roughly approximate the access mode by converting the rights. int oflags = fds.fs_flags; if ((fds.fs_rights_base & -#ifdef __wasilibc_unmodified_upstream - (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FILE_READDIR)) != 0) { - if ((fds.fs_rights_base & __WASI_RIGHT_FD_WRITE) != 0) -#else (__WASI_RIGHTS_FD_READ | __WASI_RIGHTS_FD_READDIR)) != 0) { if ((fds.fs_rights_base & __WASI_RIGHTS_FD_WRITE) != 0) -#endif oflags |= O_RDWR; else oflags |= O_RDONLY; -#ifdef __wasilibc_unmodified_upstream - } else if ((fds.fs_rights_base & __WASI_RIGHT_FD_WRITE) != 0) { -#else } else if ((fds.fs_rights_base & __WASI_RIGHTS_FD_WRITE) != 0) { -#endif oflags |= O_WRONLY; -#ifdef __wasilibc_unmodified_upstream - } else if ((fds.fs_rights_base & __WASI_RIGHT_PROC_EXEC) != 0) { - oflags |= O_EXEC; -#endif } else { oflags |= O_SEARCH; } @@ -63,15 +46,9 @@ int fcntl(int fildes, int cmd, ...) { int flags = va_arg(ap, int); va_end(ap); -#ifdef __wasilibc_unmodified_upstream // fstat - __wasi_fdstat_t fds = {.fs_flags = flags & 0xfff}; - __wasi_errno_t error = - __wasi_fd_stat_put(fildes, &fds, __WASI_FDSTAT_FLAGS); -#else __wasi_fdflags_t fs_flags = flags & 0xfff; __wasi_errno_t error = __wasi_fd_fdstat_set_flags(fildes, fs_flags); -#endif if (error != 0) { errno = error; return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c b/libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c index 12d62b7..46919fe 100644 --- a/libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c +++ b/libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c @@ -11,98 +11,39 @@ #include #include -#ifdef __wasilibc_unmodified_upstream // fstat -static_assert(O_APPEND == __WASI_FDFLAG_APPEND, "Value mismatch"); -static_assert(O_DSYNC == __WASI_FDFLAG_DSYNC, "Value mismatch"); -static_assert(O_NONBLOCK == __WASI_FDFLAG_NONBLOCK, "Value mismatch"); -static_assert(O_RSYNC == __WASI_FDFLAG_RSYNC, "Value mismatch"); -static_assert(O_SYNC == __WASI_FDFLAG_SYNC, "Value mismatch"); -#else static_assert(O_APPEND == __WASI_FDFLAGS_APPEND, "Value mismatch"); static_assert(O_DSYNC == __WASI_FDFLAGS_DSYNC, "Value mismatch"); static_assert(O_NONBLOCK == __WASI_FDFLAGS_NONBLOCK, "Value mismatch"); static_assert(O_RSYNC == __WASI_FDFLAGS_RSYNC, "Value mismatch"); static_assert(O_SYNC == __WASI_FDFLAGS_SYNC, "Value mismatch"); -#endif -#ifdef __wasilibc_unmodified_upstream // fstat -static_assert(O_CREAT >> 12 == __WASI_O_CREAT, "Value mismatch"); -static_assert(O_DIRECTORY >> 12 == __WASI_O_DIRECTORY, "Value mismatch"); -static_assert(O_EXCL >> 12 == __WASI_O_EXCL, "Value mismatch"); -static_assert(O_TRUNC >> 12 == __WASI_O_TRUNC, "Value mismatch"); -#else static_assert(O_CREAT >> 12 == __WASI_OFLAGS_CREAT, "Value mismatch"); static_assert(O_DIRECTORY >> 12 == __WASI_OFLAGS_DIRECTORY, "Value mismatch"); static_assert(O_EXCL >> 12 == __WASI_OFLAGS_EXCL, "Value mismatch"); static_assert(O_TRUNC >> 12 == __WASI_OFLAGS_TRUNC, "Value mismatch"); -#endif -int openat(int fd, const char *path, int oflag, ...) { -#ifdef __wasilibc_unmodified_upstream // fstat -#else - return __wasilibc_openat_nomode(fd, path, oflag); -} - -int __wasilibc_openat_nomode(int fd, const char *path, int oflag) { -#endif +int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) { // Compute rights corresponding with the access modes provided. // Attempt to obtain all rights, except the ones that contradict the // access mode provided to openat(). -#ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead. - __wasi_rights_t min = 0; -#endif __wasi_rights_t max = -#ifdef __wasilibc_unmodified_upstream // fstat - ~(__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | - __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FILE_ALLOCATE | - __WASI_RIGHT_FILE_READDIR | __WASI_RIGHT_FILE_STAT_FPUT_SIZE | -#else ~(__WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_READ | __WASI_RIGHTS_FD_WRITE | __WASI_RIGHTS_FD_ALLOCATE | - __WASI_RIGHTS_FD_READDIR | __WASI_RIGHTS_FD_FILESTAT_SET_SIZE | -#endif -#ifdef __wasilibc_unmodified_upstream // RIGHT_MEM_MAP_EXEC - __WASI_RIGHT_MEM_MAP_EXEC); -#else - 0); -#endif + __WASI_RIGHTS_FD_READDIR | __WASI_RIGHTS_FD_FILESTAT_SET_SIZE); switch (oflag & O_ACCMODE) { case O_RDONLY: case O_RDWR: case O_WRONLY: if ((oflag & O_RDONLY) != 0) { -#ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead. - min |= (oflag & O_DIRECTORY) == 0 ? __WASI_RIGHT_FD_READ - : __WASI_RIGHT_FILE_READDIR; -#endif -#ifdef __wasilibc_unmodified_upstream // RIGHT_MEM_MAP_EXEC - max |= __WASI_RIGHT_FD_READ | __WASI_RIGHT_FILE_READDIR | - __WASI_RIGHT_MEM_MAP_EXEC; -#else max |= __WASI_RIGHTS_FD_READ | __WASI_RIGHTS_FD_READDIR; -#endif } if ((oflag & O_WRONLY) != 0) { -#ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead. - min |= __WASI_RIGHT_FD_WRITE; - if ((oflag & O_APPEND) == 0) - min |= __WASI_RIGHT_FD_SEEK; -#endif -#ifdef __wasilibc_unmodified_upstream // fstat - max |= __WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_WRITE | - __WASI_RIGHT_FILE_ALLOCATE | - __WASI_RIGHT_FILE_STAT_FPUT_SIZE; -#else max |= __WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_WRITE | __WASI_RIGHTS_FD_ALLOCATE | __WASI_RIGHTS_FD_FILESTAT_SET_SIZE; -#endif } break; case O_EXEC: -#ifdef __wasilibc_unmodified_upstream // RIGHT_PROC_EXEC - min |= __WASI_RIGHT_PROC_EXEC; -#endif break; case O_SEARCH: break; @@ -110,72 +51,31 @@ int __wasilibc_openat_nomode(int fd, const char *path, int oflag) { errno = EINVAL; return -1; } -#ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead. - assert((min & max) == min && - "Minimal rights should be a subset of the maximum"); -#endif // Ensure that we can actually obtain the minimal rights needed. __wasi_fdstat_t fsb_cur; -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_fd_stat_get(fd, &fsb_cur); -#else __wasi_errno_t error = __wasi_fd_fdstat_get(fd, &fsb_cur); -#endif if (error != 0) { errno = error; return -1; } -#ifdef __wasilibc_unmodified_upstream // Let the WASI implementation check this instead. - if (fsb_cur.fs_filetype != __WASI_FILETYPE_DIRECTORY) { - errno = ENOTDIR; - return -1; - } - if ((min & fsb_cur.fs_rights_inheriting) != min) { - errno = ENOTCAPABLE; - return -1; - } -#endif // Path lookup properties. -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - __wasi_lookup_t lookup = {.fd = fd, .flags = 0}; -#else __wasi_lookupflags_t lookup_flags = 0; -#endif if ((oflag & O_NOFOLLOW) == 0) -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - lookup.flags |= __WASI_LOOKUP_SYMLINK_FOLLOW; -#else lookup_flags |= __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW; -#endif // Open file with appropriate rights. -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t and __wasi_fdstat_t - __wasi_fdstat_t fsb_new = { - .fs_flags = oflag & 0xfff, - .fs_rights_base = max & fsb_cur.fs_rights_inheriting, - .fs_rights_inheriting = fsb_cur.fs_rights_inheriting, - }; - __wasi_fd_t newfd; - error = __wasi_file_open(lookup, path, strlen(path), - (oflag >> 12) & 0xfff, &fsb_new, &newfd); -#else __wasi_fdflags_t fs_flags = oflag & 0xfff; __wasi_rights_t fs_rights_base = max & fsb_cur.fs_rights_inheriting; __wasi_rights_t fs_rights_inheriting = fsb_cur.fs_rights_inheriting; __wasi_fd_t newfd; - error = __wasi_path_open(fd, lookup_flags, path, strlen(path), + error = __wasi_path_open(fd, lookup_flags, path, (oflag >> 12) & 0xfff, fs_rights_base, fs_rights_inheriting, fs_flags, &newfd); -#endif if (error != 0) { -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - errno = errno_fixup_directory(lookup.fd, error); -#else errno = errno_fixup_directory(fd, error); -#endif return -1; } return newfd; diff --git a/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fadvise.c b/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fadvise.c index af8d7e1..d683d39 100644 --- a/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fadvise.c +++ b/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fadvise.c @@ -20,9 +20,5 @@ static_assert(POSIX_FADV_WILLNEED == __WASI_ADVICE_WILLNEED, int posix_fadvise(int fd, off_t offset, off_t len, int advice) { if (offset < 0 || len < 0) return EINVAL; -#ifdef __wasilibc_unmodified_upstream - return __wasi_file_advise(fd, offset, len, advice); -#else return __wasi_fd_advise(fd, offset, len, advice); -#endif } diff --git a/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fallocate.c b/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fallocate.c index 44e1842..4b41c4b 100644 --- a/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fallocate.c +++ b/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fallocate.c @@ -9,9 +9,5 @@ int posix_fallocate(int fd, off_t offset, off_t len) { if (offset < 0 || len < 0) return EINVAL; -#ifdef __wasilibc_unmodified_upstream - return __wasi_file_allocate(fd, offset, len); -#else return __wasi_fd_allocate(fd, offset, len); -#endif } diff --git a/libc-bottom-half/cloudlibc/src/libc/sched/sched_yield.c b/libc-bottom-half/cloudlibc/src/libc/sched/sched_yield.c index e48e3c7..6100ea5 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sched/sched_yield.c +++ b/libc-bottom-half/cloudlibc/src/libc/sched/sched_yield.c @@ -7,11 +7,7 @@ #include int sched_yield(void) { -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_thread_yield(); -#else __wasi_errno_t error = __wasi_sched_yield(); -#endif if (error != 0) { errno = error; return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c b/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c index f5e4d96..e43cef2 100644 --- a/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c +++ b/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c @@ -9,13 +9,8 @@ #include #include -int renameat(int oldfd, const char *old, int newfd, const char *new) { -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_file_rename(oldfd, old, strlen(old), -#else - __wasi_errno_t error = __wasi_path_rename(oldfd, old, strlen(old), -#endif - newfd, new, strlen(new)); +int __wasilibc_nocwd_renameat(int oldfd, const char *old, int newfd, const char *new) { + __wasi_errno_t error = __wasi_path_rename(oldfd, old, newfd, new); if (error != 0) { errno = errno_fixup_directory(oldfd, errno_fixup_directory(newfd, error)); return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c b/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c index e464d88..7d03cc6 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c @@ -24,11 +24,7 @@ int ioctl(int fildes, int request, ...) { }; __wasi_event_t events[__arraycount(subscriptions)]; size_t nevents; -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_poll( -#else __wasi_errno_t error = __wasi_poll_oneoff( -#endif subscriptions, events, __arraycount(subscriptions), &nevents); if (error != 0) { errno = error; @@ -61,11 +57,7 @@ int ioctl(int fildes, int request, ...) { case FIONBIO: { // Obtain the current file descriptor flags. __wasi_fdstat_t fds; -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_fd_stat_get(fildes, &fds); -#else __wasi_errno_t error = __wasi_fd_fdstat_get(fildes, &fds); -#endif if (error != 0) { errno = error; return -1; @@ -75,25 +67,13 @@ int ioctl(int fildes, int request, ...) { va_list ap; va_start(ap, request); if (*va_arg(ap, const int *) != 0) -#ifdef __wasilibc_unmodified_upstream // generated constant names - fds.fs_flags |= __WASI_FDFLAG_NONBLOCK; -#else fds.fs_flags |= __WASI_FDFLAGS_NONBLOCK; -#endif else -#ifdef __wasilibc_unmodified_upstream // generated constant names - fds.fs_flags &= ~__WASI_FDFLAG_NONBLOCK; -#else fds.fs_flags &= ~__WASI_FDFLAGS_NONBLOCK; -#endif va_end(ap); // Update the file descriptor flags. -#ifdef __wasilibc_unmodified_upstream // fstat - error = __wasi_fd_stat_put(fildes, &fds, __WASI_FDSTAT_FLAGS); -#else error = __wasi_fd_fdstat_set_flags(fildes, fds.fs_flags); -#endif if (error != 0) { errno = error; return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/resource/getrusage.c b/libc-bottom-half/cloudlibc/src/libc/sys/resource/getrusage.c deleted file mode 100644 index be1a078..0000000 --- a/libc-bottom-half/cloudlibc/src/libc/sys/resource/getrusage.c +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2016 Nuxi, https://nuxi.nl/ -// -// SPDX-License-Identifier: BSD-2-Clause - -#include - -#include - -#include -#include - -int getrusage(int who, struct rusage *r_usage) { - switch (who) { - case RUSAGE_SELF: { - __wasi_timestamp_t usertime = 0; -#ifdef __wasilibc_unmodified_upstream // generated constant names - (void)__wasi_clock_time_get(__WASI_CLOCK_PROCESS_CPUTIME_ID, 1000, -#else - (void)__wasi_clock_time_get(__WASI_CLOCKID_PROCESS_CPUTIME_ID, 1000, -#endif - &usertime); - *r_usage = (struct rusage){ - .ru_utime = timestamp_to_timeval(usertime), - }; - return 0; - } - case RUSAGE_CHILDREN: - *r_usage = (struct rusage){}; - return 0; - default: - errno = EINVAL; - return -1; - } -} diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/select/select.c b/libc-bottom-half/cloudlibc/src/libc/sys/select/select.c index 5d4bc93..ebe5e8c 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/select/select.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/select/select.c @@ -17,17 +17,9 @@ int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, } struct timespec ts = {.tv_sec = timeout->tv_sec, .tv_nsec = (long)timeout->tv_usec * 1000}; -#ifdef __wasilibc_unmodified_upstream - return pselect(nfds, readfds, writefds, errorfds, &ts); -#else return pselect(nfds, readfds, writefds, errorfds, &ts, NULL); -#endif } else { // No timeout specified. -#ifdef __wasilibc_unmodified_upstream - return pselect(nfds, readfds, writefds, errorfds, NULL); -#else return pselect(nfds, readfds, writefds, errorfds, NULL, NULL); -#endif } } diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c index 61af183..1fe41c4 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c @@ -9,11 +9,7 @@ #include int getsockopt(int socket, int level, int option_name, -#ifdef __wasilibc_unmodified_upstream - void *restrict option_value, size_t *restrict option_len) { -#else void *restrict option_value, socklen_t *restrict option_len) { -#endif // Only support SOL_SOCKET options for now. if (level != SOL_SOCKET) { errno = ENOPROTOOPT; @@ -26,11 +22,7 @@ int getsockopt(int socket, int level, int option_name, // Return the type of the socket. This information can simply be // obtained by looking at the file descriptor type. __wasi_fdstat_t fsb; -#ifdef __wasilibc_unmodified_upstream - if (__wasi_fd_stat_get(socket, &fsb) != 0) { -#else if (__wasi_fd_fdstat_get(socket, &fsb) != 0) { -#endif errno = EBADF; return -1; } diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c index 57e0370..49c09d0 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c @@ -11,13 +11,8 @@ #include #include -#ifdef __wasilibc_unmodified_upstream -static_assert(MSG_PEEK == __WASI_SOCK_RECV_PEEK, "Value mismatch"); -static_assert(MSG_WAITALL == __WASI_SOCK_RECV_WAITALL, "Value mismatch"); -#else static_assert(MSG_PEEK == __WASI_RIFLAGS_RECV_PEEK, "Value mismatch"); static_assert(MSG_WAITALL == __WASI_RIFLAGS_RECV_WAITALL, "Value mismatch"); -#endif ssize_t recv(int socket, void *restrict buffer, size_t length, int flags) { // Validate flags. @@ -28,37 +23,20 @@ ssize_t recv(int socket, void *restrict buffer, size_t length, int flags) { // Prepare input parameters. __wasi_iovec_t iov = {.buf = buffer, .buf_len = length}; -#ifdef __wasilibc_unmodified_upstream // send/recv - __wasi_recv_in_t ri = { - .ri_data = &iov, - .ri_data_len = 1, - .ri_flags = flags, - }; -#else __wasi_iovec_t *ri_data = &iov; size_t ri_data_len = 1; __wasi_riflags_t ri_flags = flags; -#endif // Perform system call. -#ifdef __wasilibc_unmodified_upstream // send/recv - __wasi_recv_out_t ro; - __wasi_errno_t error = __wasi_sock_recv(socket, &ri, &ro); -#else size_t ro_datalen; __wasi_roflags_t ro_flags; __wasi_errno_t error = __wasi_sock_recv(socket, ri_data, ri_data_len, ri_flags, &ro_datalen, &ro_flags); -#endif if (error != 0) { errno = errno_fixup_socket(socket, error); return -1; } -#ifdef __wasilibc_unmodified_upstream // send/recv - return ro.ro_datalen; -#else return ro_datalen; -#endif } diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c index 626110c..0759abf 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c @@ -19,32 +19,16 @@ ssize_t send(int socket, const void *buffer, size_t length, int flags) { // Prepare input parameters. __wasi_ciovec_t iov = {.buf = buffer, .buf_len = length}; -#ifdef __wasilibc_unmodified_upstream // send/recv - __wasi_send_in_t si = { - .si_data = &iov, - .si_data_len = 1, - }; -#else __wasi_ciovec_t *si_data = &iov; size_t si_data_len = 1; __wasi_siflags_t si_flags = 0; -#endif // Perform system call. -#ifdef __wasilibc_unmodified_upstream // send/recv - __wasi_send_out_t so; - __wasi_errno_t error = __wasi_sock_send(socket, &si, &so); -#else size_t so_datalen; __wasi_errno_t error = __wasi_sock_send(socket, si_data, si_data_len, si_flags, &so_datalen); -#endif if (error != 0) { errno = errno_fixup_socket(socket, error); return -1; } -#ifdef __wasilibc_unmodified_upstream // send/recv - return so.so_datalen; -#else return so_datalen; -#endif } diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c index 560f53c..883b551 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c @@ -10,13 +10,8 @@ #include #include -#ifdef __wasilibc_unmodified_upstream // generated constant names -static_assert(SHUT_RD == __WASI_SHUT_RD, "Value mismatch"); -static_assert(SHUT_WR == __WASI_SHUT_WR, "Value mismatch"); -#else static_assert(SHUT_RD == __WASI_SDFLAGS_RD, "Value mismatch"); static_assert(SHUT_WR == __WASI_SDFLAGS_WR, "Value mismatch"); -#endif int shutdown(int socket, int how) { // Validate shutdown flags. diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c index ff590d1..b8ffdb5 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c @@ -11,11 +11,7 @@ int fstat(int fildes, struct stat *buf) { __wasi_filestat_t internal_stat; -#ifdef __wasilibc_unmodified_upstream // fstat - __wasi_errno_t error = __wasi_file_stat_fget(fildes, &internal_stat); -#else __wasi_errno_t error = __wasi_fd_filestat_get(fildes, &internal_stat); -#endif if (error != 0) { errno = error; return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c index 375d59d..f037d99 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c @@ -13,29 +13,17 @@ #include "stat_impl.h" -int fstatat(int fd, const char *restrict path, struct stat *restrict buf, - int flag) { +int __wasilibc_nocwd_fstatat(int fd, const char *restrict path, struct stat *restrict buf, + int flag) { // Create lookup properties. -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - __wasi_lookup_t lookup = {.fd = fd, .flags = 0}; -#else __wasi_lookupflags_t lookup_flags = 0; -#endif if ((flag & AT_SYMLINK_NOFOLLOW) == 0) -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - lookup.flags |= __WASI_LOOKUP_SYMLINK_FOLLOW; -#else lookup_flags |= __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW; -#endif // Perform system call. __wasi_filestat_t internal_stat; __wasi_errno_t error = -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - __wasi_file_stat_get(lookup, path, strlen(path), &internal_stat); -#else - __wasi_path_filestat_get(fd, lookup_flags, path, strlen(path), &internal_stat); -#endif + __wasi_path_filestat_get(fd, lookup_flags, path, &internal_stat); if (error != 0) { errno = errno_fixup_directory(fd, error); return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c index 1ae43dd..13357fc 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c @@ -11,26 +11,16 @@ int futimens(int fd, const struct timespec *times) { // Convert timestamps and extract NOW/OMIT flags. -#ifdef __wasilibc_unmodified_upstream // fstat - __wasi_filestat_t fs; - __wasi_fsflags_t flags; - if (!utimens_get_timestamps(times, &fs, &flags)) { -#else __wasi_timestamp_t st_atim; __wasi_timestamp_t st_mtim; __wasi_fstflags_t flags; if (!utimens_get_timestamps(times, &st_atim, &st_mtim, &flags)) { -#endif errno = EINVAL; return -1; } // Perform system call. -#ifdef __wasilibc_unmodified_upstream // fstat - __wasi_errno_t error = __wasi_file_stat_fput(fd, &fs, flags); -#else __wasi_errno_t error = __wasi_fd_filestat_set_times(fd, st_atim, st_mtim, flags); -#endif if (error != 0) { errno = error; return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c index 75f47a4..c89ce3d 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c @@ -10,18 +10,8 @@ #include #include -#ifdef __wasilibc_unmodified_upstream -int mkdirat(int fd, const char *path, ...) { -#else -int mkdirat(int fd, const char *path, mode_t mode) { -#endif -#ifdef __wasilibc_unmodified_upstream // __wasi_path_create_directory - __wasi_errno_t error = __wasi_file_create( - fd, path, strlen(path), __WASI_FILETYPE_DIRECTORY); -#else - __wasi_errno_t error = __wasi_path_create_directory( - fd, path, strlen(path)); -#endif +int __wasilibc_nocwd_mkdirat_nomode(int fd, const char *path) { + __wasi_errno_t error = __wasi_path_create_directory(fd, path); if (error != 0) { errno = errno_fixup_directory(fd, error); return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/stat_impl.h b/libc-bottom-half/cloudlibc/src/libc/sys/stat/stat_impl.h index d1a26fd..c649d3b 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/stat_impl.h +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/stat_impl.h @@ -24,43 +24,17 @@ static_assert(S_ISSOCK(S_IFSOCK), "Value mismatch"); static inline void to_public_stat(const __wasi_filestat_t *in, struct stat *out) { // Ensure that we don't truncate any values. -#ifdef __wasilibc_unmodified_upstream - static_assert(sizeof(in->st_dev) == sizeof(out->st_dev), "Size mismatch"); - static_assert(sizeof(in->st_ino) == sizeof(out->st_ino), "Size mismatch"); - static_assert(sizeof(in->st_filetype) == sizeof(out->__st_filetype), - "Size mismatch"); -#else static_assert(sizeof(in->dev) == sizeof(out->st_dev), "Size mismatch"); static_assert(sizeof(in->ino) == sizeof(out->st_ino), "Size mismatch"); /* * The non-standard __st_filetype field appears to only be used for shared * memory, which we don't currently support. */ -#endif -#ifdef __wasilibc_unmodified_upstream - static_assert(sizeof(in->st_nlink) == sizeof(out->st_nlink), "Size mismatch"); - static_assert(sizeof(in->st_size) == sizeof(out->st_size), "Size mismatch"); -#else /* nlink_t is 64-bit on wasm32, following the x32 ABI. */ static_assert(sizeof(in->nlink) <= sizeof(out->st_nlink), "Size shortfall"); static_assert(sizeof(in->size) == sizeof(out->st_size), "Size mismatch"); -#endif *out = (struct stat){ -#ifdef __wasilibc_unmodified_upstream -#define COPY_FIELD(field) .field = in->field - COPY_FIELD(st_dev), - COPY_FIELD(st_ino), - .__st_filetype = in->st_filetype, - COPY_FIELD(st_nlink), - COPY_FIELD(st_size), -#undef COPY_FIELD -#define COPY_TIMESPEC(field) .field = timestamp_to_timespec(in->field) - COPY_TIMESPEC(st_atim), - COPY_TIMESPEC(st_mtim), - COPY_TIMESPEC(st_ctim), -#undef COPY_TIMESPEC -#else .st_dev = in->dev, .st_ino = in->ino, .st_nlink = in->nlink, @@ -68,15 +42,10 @@ static inline void to_public_stat(const __wasi_filestat_t *in, .st_atim = timestamp_to_timespec(in->atim), .st_mtim = timestamp_to_timespec(in->mtim), .st_ctim = timestamp_to_timespec(in->ctim), -#endif }; // Convert file type to legacy types encoded in st_mode. -#ifdef __wasilibc_unmodified_upstream - switch (in->st_filetype) { -#else switch (in->filetype) { -#endif case __WASI_FILETYPE_BLOCK_DEVICE: out->st_mode |= S_IFBLK; break; @@ -100,64 +69,37 @@ static inline void to_public_stat(const __wasi_filestat_t *in, } static inline bool utimens_get_timestamps(const struct timespec *times, -#ifdef __wasilibc_unmodified_upstream // fstat - __wasi_filestat_t *fs, - __wasi_fsflags_t *flags) { -#else __wasi_timestamp_t *st_atim, __wasi_timestamp_t *st_mtim, __wasi_fstflags_t *flags) { -#endif if (times == NULL) { // Update both timestamps. -#ifdef __wasilibc_unmodified_upstream // fstat - *flags = __WASI_FILESTAT_ATIM_NOW | __WASI_FILESTAT_MTIM_NOW; -#else *flags = __WASI_FSTFLAGS_ATIM_NOW | __WASI_FSTFLAGS_MTIM_NOW; -#endif } else { // Set individual timestamps. *flags = 0; switch (times[0].tv_nsec) { case UTIME_NOW: -#ifdef __wasilibc_unmodified_upstream // fstat - *flags |= __WASI_FILESTAT_ATIM_NOW; -#else *flags |= __WASI_FSTFLAGS_ATIM_NOW; -#endif break; case UTIME_OMIT: break; default: -#ifdef __wasilibc_unmodified_upstream // fstat - *flags |= __WASI_FILESTAT_ATIM; - if (!timespec_to_timestamp_exact(×[0], &fs->st_atim)) -#else *flags |= __WASI_FSTFLAGS_ATIM; if (!timespec_to_timestamp_exact(×[0], st_atim)) -#endif return false; break; } switch (times[1].tv_nsec) { case UTIME_NOW: -#ifdef __wasilibc_unmodified_upstream // fstat - *flags |= __WASI_FILESTAT_MTIM_NOW; -#else *flags |= __WASI_FSTFLAGS_MTIM_NOW; -#endif break; case UTIME_OMIT: break; default: -#ifdef __wasilibc_unmodified_upstream // fstat - *flags |= __WASI_FILESTAT_MTIM; - if (!timespec_to_timestamp_exact(×[1], &fs->st_mtim)) -#else *flags |= __WASI_FSTFLAGS_MTIM; if (!timespec_to_timestamp_exact(×[1], st_mtim)) -#endif return false; break; } diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c index f27b67d..a572716 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c @@ -13,43 +13,25 @@ #include "stat_impl.h" -int utimensat(int fd, const char *path, const struct timespec times[2], - int flag) { +int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec times[2], + int flag) { // Convert timestamps and extract NOW/OMIT flags. -#ifdef __wasilibc_unmodified_upstream // fstat - __wasi_filestat_t fs; - __wasi_fsflags_t flags; - if (!utimens_get_timestamps(times, &fs, &flags)) { -#else __wasi_timestamp_t st_atim; __wasi_timestamp_t st_mtim; __wasi_fstflags_t flags; if (!utimens_get_timestamps(times, &st_atim, &st_mtim, &flags)) { -#endif errno = EINVAL; return -1; } // Create lookup properties. -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - __wasi_lookup_t lookup = {.fd = fd, .flags = 0}; -#else __wasi_lookupflags_t lookup_flags = 0; -#endif if ((flag & AT_SYMLINK_NOFOLLOW) == 0) -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - lookup.flags |= __WASI_LOOKUP_SYMLINK_FOLLOW; -#else lookup_flags |= __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW; -#endif // Perform system call. __wasi_errno_t error = -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t, fstat - __wasi_file_stat_put(lookup, path, strlen(path), &fs, flags); -#else - __wasi_path_filestat_set_times(fd, lookup_flags, path, strlen(path), st_atim, st_mtim, flags); -#endif + __wasi_path_filestat_set_times(fd, lookup_flags, path, st_atim, st_mtim, flags); if (error != 0) { errno = errno_fixup_directory(fd, error); return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/time/gettimeofday.c b/libc-bottom-half/cloudlibc/src/libc/sys/time/gettimeofday.c index 9d33386..d58cbb9 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/time/gettimeofday.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/time/gettimeofday.c @@ -8,17 +8,9 @@ #include -#ifdef __wasilibc_unmodified_upstream -int gettimeofday(struct timeval *restrict tp, ...) { -#else int gettimeofday(struct timeval *restrict tp, void *tz) { -#endif __wasi_timestamp_t ts = 0; -#ifdef __wasilibc_unmodified_upstream // generated constant names - (void)__wasi_clock_time_get(__WASI_CLOCK_REALTIME, 1000, &ts); -#else (void)__wasi_clock_time_get(__WASI_CLOCKID_REALTIME, 1000, &ts); -#endif *tp = timestamp_to_timeval(ts); return 0; } diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/times/times.c b/libc-bottom-half/cloudlibc/src/libc/sys/times/times.c deleted file mode 100644 index 19dc42a..0000000 --- a/libc-bottom-half/cloudlibc/src/libc/sys/times/times.c +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ -// -// SPDX-License-Identifier: BSD-2-Clause - -#include - -#include - -#include -#include - -static_assert(CLOCKS_PER_SEC == NSEC_PER_SEC, - "Timestamp should need no conversion"); - -clock_t times(struct tms *buffer) { - // Obtain user time. - __wasi_timestamp_t usertime = 0; -#ifdef __wasilibc_unmodified_upstream // generated constant names - (void)__wasi_clock_time_get(__WASI_CLOCK_PROCESS_CPUTIME_ID, 0, &usertime); -#else - (void)__wasi_clock_time_get(__WASI_CLOCKID_PROCESS_CPUTIME_ID, 0, &usertime); -#endif - *buffer = (struct tms){.tms_utime = usertime}; - - // Obtain real time. - __wasi_timestamp_t realtime = 0; -#ifdef __wasilibc_unmodified_upstream // generated constant names - (void)__wasi_clock_time_get(__WASI_CLOCK_MONOTONIC, 0, &realtime); -#else - (void)__wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC, 0, &realtime); -#endif - return realtime; -} diff --git a/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_MONOTONIC.c b/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_MONOTONIC.c index bf87ea9..a4c4a62 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_MONOTONIC.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_MONOTONIC.c @@ -8,9 +8,5 @@ #include const struct __clockid _CLOCK_MONOTONIC = { -#ifdef __wasilibc_unmodified_upstream // generated constant names - .id = __WASI_CLOCK_MONOTONIC, -#else .id = __WASI_CLOCKID_MONOTONIC, -#endif }; diff --git a/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_PROCESS_CPUTIME_ID.c b/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_PROCESS_CPUTIME_ID.c index ce87214..901fd73 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_PROCESS_CPUTIME_ID.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_PROCESS_CPUTIME_ID.c @@ -8,9 +8,5 @@ #include const struct __clockid _CLOCK_PROCESS_CPUTIME_ID = { -#ifdef __wasilibc_unmodified_upstream - .id = __WASI_CLOCK_PROCESS_CPUTIME_ID, -#else .id = __WASI_CLOCKID_PROCESS_CPUTIME_ID, -#endif }; diff --git a/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_REALTIME.c b/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_REALTIME.c index 9bbcc6e..9523754 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_REALTIME.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_REALTIME.c @@ -8,9 +8,5 @@ #include const struct __clockid _CLOCK_REALTIME = { -#ifdef __wasilibc_unmodified_upstream // generated constant names - .id = __WASI_CLOCK_REALTIME, -#else .id = __WASI_CLOCKID_REALTIME, -#endif }; diff --git a/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_THREAD_CPUTIME_ID.c b/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_THREAD_CPUTIME_ID.c index 4cfd3ee..de58c51 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_THREAD_CPUTIME_ID.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_THREAD_CPUTIME_ID.c @@ -8,9 +8,5 @@ #include const struct __clockid _CLOCK_THREAD_CPUTIME_ID = { -#ifdef __wasilibc_unmodified_upstream // generated constant names - .id = __WASI_CLOCK_THREAD_CPUTIME_ID, -#else .id = __WASI_CLOCKID_THREAD_CPUTIME_ID, -#endif }; diff --git a/libc-bottom-half/cloudlibc/src/libc/time/clock.c b/libc-bottom-half/cloudlibc/src/libc/time/clock.c deleted file mode 100644 index d0748f3..0000000 --- a/libc-bottom-half/cloudlibc/src/libc/time/clock.c +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ -// -// SPDX-License-Identifier: BSD-2-Clause - -#include - -#include -#include -#include - -static_assert(CLOCKS_PER_SEC == NSEC_PER_SEC, - "Timestamp should need no conversion"); - -clock_t clock(void) { - __wasi_timestamp_t ts = 0; -#ifdef __wasilibc_unmodified_upstream // generated constant names - (void)__wasi_clock_time_get(__WASI_CLOCK_PROCESS_CPUTIME_ID, 0, &ts); -#else - (void)__wasi_clock_time_get(__WASI_CLOCKID_PROCESS_CPUTIME_ID, 0, &ts); -#endif - return ts; -} diff --git a/libc-bottom-half/cloudlibc/src/libc/time/clock_gettime.c b/libc-bottom-half/cloudlibc/src/libc/time/clock_gettime.c index 412b613..dbb36a7 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/clock_gettime.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/clock_gettime.c @@ -9,11 +9,7 @@ #include #include -#ifdef __wasilibc_unmodified_upstream -int clock_gettime(clockid_t clock_id, struct timespec *tp) { -#else int __clock_gettime(clockid_t clock_id, struct timespec *tp) { -#endif __wasi_timestamp_t ts; __wasi_errno_t error = __wasi_clock_time_get(clock_id->id, 1, &ts); if (error != 0) { @@ -23,7 +19,4 @@ int __clock_gettime(clockid_t clock_id, struct timespec *tp) { *tp = timestamp_to_timespec(ts); return 0; } -#ifdef __wasilibc_unmodified_upstream -#else extern __typeof(__clock_gettime) clock_gettime __attribute__((weak, alias("__clock_gettime"))); -#endif diff --git a/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c b/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c index cd8ecfc..52b577a 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c @@ -10,20 +10,11 @@ #include #include -#ifdef __wasilibc_unmodified_upstream // generated constant names -static_assert(TIMER_ABSTIME == __WASI_SUBSCRIPTION_CLOCK_ABSTIME, -#else static_assert(TIMER_ABSTIME == __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME, -#endif "Value mismatch"); -#ifdef __wasilibc_unmodified_upstream -int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, - ...) { -#else int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp) { -#endif if ((flags & ~TIMER_ABSTIME) != 0) return EINVAL; @@ -39,10 +30,6 @@ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, // Block until polling event is triggered. size_t nevents; __wasi_event_t ev; -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_poll(&sub, &ev, 1, &nevents); -#else __wasi_errno_t error = __wasi_poll_oneoff(&sub, &ev, 1, &nevents); -#endif return error == 0 && ev.error == 0 ? 0 : ENOTSUP; } diff --git a/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c b/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c index 0cba5ac..9ffa1be 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c @@ -6,16 +6,8 @@ #include #include -#ifdef __wasilibc_unmodified_upstream -int nanosleep(const struct timespec *rqtp, ...) { -#else int nanosleep(const struct timespec *rqtp, struct timespec *rem) { -#endif -#ifdef __wasilibc_unmodified_upstream - int error = clock_nanosleep(CLOCK_REALTIME, 0, rqtp); -#else int error = clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rem); -#endif if (error != 0) { errno = error; return -1; @@ -23,7 +15,6 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rem) { return 0; } -#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +#if defined(_REENTRANT) __strong_reference(nanosleep, thrd_sleep); -#else #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/time/time.c b/libc-bottom-half/cloudlibc/src/libc/time/time.c index 2c0ba9a..52bc0e4 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/time.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/time.c @@ -9,11 +9,7 @@ time_t time(time_t *tloc) { __wasi_timestamp_t ts = 0; -#ifdef __wasilibc_unmodified_upstream - (void)__wasi_clock_time_get(__WASI_CLOCK_REALTIME, NSEC_PER_SEC, &ts); -#else (void)__wasi_clock_time_get(__WASI_CLOCKID_REALTIME, NSEC_PER_SEC, &ts); -#endif if (tloc != NULL) *tloc = ts / NSEC_PER_SEC; return ts / NSEC_PER_SEC; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c index 2c8ee84..077250c 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c @@ -10,7 +10,7 @@ #include #include -int faccessat(int fd, const char *path, int amode, int flag) { +int __wasilibc_nocwd_faccessat(int fd, const char *path, int amode, int flag) { // Validate function parameters. if ((amode & ~(F_OK | R_OK | W_OK | X_OK)) != 0 || (flag & ~AT_EACCESS) != 0) { @@ -19,21 +19,10 @@ int faccessat(int fd, const char *path, int amode, int flag) { } // Check for target file existence and obtain the file type. -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - __wasi_lookup_t lookup = { - .fd = fd, - .flags = __WASI_LOOKUP_SYMLINK_FOLLOW, - }; -#else __wasi_lookupflags_t lookup_flags = __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW; -#endif __wasi_filestat_t file; __wasi_errno_t error = -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - __wasi_file_stat_get(lookup, path, strlen(path), &file); -#else - __wasi_path_filestat_get(fd, lookup_flags, path, strlen(path), &file); -#endif + __wasi_path_filestat_get(fd, lookup_flags, path, &file); if (error != 0) { errno = errno_fixup_directory(fd, error); return -1; @@ -43,11 +32,7 @@ int faccessat(int fd, const char *path, int amode, int flag) { // directory file descriptor. if (amode != 0) { __wasi_fdstat_t directory; -#ifdef __wasilibc_unmodified_upstream - error = __wasi_fd_stat_get(fd, &directory); -#else error = __wasi_fd_fdstat_get(fd, &directory); -#endif if (error != 0) { errno = error; return -1; @@ -55,25 +40,11 @@ int faccessat(int fd, const char *path, int amode, int flag) { __wasi_rights_t min = 0; if ((amode & R_OK) != 0) -#ifdef __wasilibc_unmodified_upstream - min |= file.st_filetype == __WASI_FILETYPE_DIRECTORY - ? __WASI_RIGHT_FILE_READDIR - : __WASI_RIGHT_FD_READ; -#else min |= file.filetype == __WASI_FILETYPE_DIRECTORY ? __WASI_RIGHTS_FD_READDIR : __WASI_RIGHTS_FD_READ; -#endif if ((amode & W_OK) != 0) -#ifdef __wasilibc_unmodified_upstream // generated constant names - min |= __WASI_RIGHT_FD_WRITE; -#else min |= __WASI_RIGHTS_FD_WRITE; -#endif -#ifdef __wasilibc_unmodified_upstream // RIGHT_PROC_EXEC - if ((amode & X_OK) != 0 && file.st_filetype != __WASI_FILETYPE_DIRECTORY) - min |= __WASI_RIGHT_PROC_EXEC; -#endif if ((min & directory.fs_rights_inheriting) != min) { errno = EACCES; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/ftruncate.c b/libc-bottom-half/cloudlibc/src/libc/unistd/ftruncate.c index c00ccdd..7792597 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/ftruncate.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/ftruncate.c @@ -11,19 +11,9 @@ int ftruncate(int fildes, off_t length) { errno = EINVAL; return -1; } -#ifdef __wasilibc_unmodified_upstream // fstat - __wasi_filestat_t fs = { - .st_size = length, - }; -#else __wasi_filesize_t st_size = length; -#endif __wasi_errno_t error = -#ifdef __wasilibc_unmodified_upstream // fstat - __wasi_file_stat_fput(fildes, &fs, __WASI_FILESTAT_SIZE); -#else __wasi_fd_filestat_set_size(fildes, st_size); -#endif if (error != 0) { errno = error; return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c index f0ec72b..683dd4c 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c @@ -10,27 +10,14 @@ #include #include -int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag) { +int __wasilibc_nocwd_linkat(int fd1, const char *path1, int fd2, const char *path2, int flag) { // Create lookup properties. -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - __wasi_lookup_t lookup1 = {.fd = fd1, .flags = 0}; -#else __wasi_lookupflags_t lookup1_flags = 0; -#endif if ((flag & AT_SYMLINK_FOLLOW) != 0) -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - lookup1.flags |= __WASI_LOOKUP_SYMLINK_FOLLOW; -#else lookup1_flags |= __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW; -#endif // Perform system call. -#ifdef __wasilibc_unmodified_upstream // split out __wasi_lookup_t - __wasi_errno_t error = __wasi_file_link(lookup1, path1, strlen(path1), -#else - __wasi_errno_t error = __wasi_path_link(fd1, lookup1_flags, path1, strlen(path1), -#endif - fd2, path2, strlen(path2)); + __wasi_errno_t error = __wasi_path_link(fd1, lookup1_flags, path1, fd2, path2); if (error != 0) { errno = errno_fixup_directory(fd1, errno_fixup_directory(fd2, error)); return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c b/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c index cb5d995..0dfc49e 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c @@ -11,11 +11,7 @@ static_assert(SEEK_CUR == __WASI_WHENCE_CUR, "Value mismatch"); static_assert(SEEK_END == __WASI_WHENCE_END, "Value mismatch"); static_assert(SEEK_SET == __WASI_WHENCE_SET, "Value mismatch"); -#ifdef __wasilibc_unmodified_upstream // Provide an __lseek entry point -off_t lseek(int fildes, off_t offset, int whence) { -#else off_t __lseek(int fildes, off_t offset, int whence) { -#endif __wasi_filesize_t new_offset; __wasi_errno_t error = __wasi_fd_seek(fildes, offset, whence, &new_offset); @@ -26,7 +22,4 @@ off_t __lseek(int fildes, off_t offset, int whence) { return new_offset; } -#ifdef __wasilibc_unmodified_upstream // Provide an __lseek entry point -#else extern __typeof(__lseek) lseek __attribute__((weak, alias("__lseek"))); -#endif diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/pread.c b/libc-bottom-half/cloudlibc/src/libc/unistd/pread.c index 9520867..c9944bc 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/pread.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/pread.c @@ -17,17 +17,9 @@ ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset) { __wasi_fd_pread(fildes, &iov, 1, offset, &bytes_read); if (error != 0) { __wasi_fdstat_t fds; -#ifdef __wasilibc_unmodified_upstream - if (error == ENOTCAPABLE && __wasi_fd_stat_get(fildes, &fds) == 0) { -#else if (error == ENOTCAPABLE && __wasi_fd_fdstat_get(fildes, &fds) == 0) { -#endif // Determine why we got ENOTCAPABLE. -#ifdef __wasilibc_unmodified_upstream // generated constant names - if ((fds.fs_rights_base & __WASI_RIGHT_FD_READ) == 0) -#else if ((fds.fs_rights_base & __WASI_RIGHTS_FD_READ) == 0) -#endif error = EBADF; else error = ESPIPE; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/pwrite.c b/libc-bottom-half/cloudlibc/src/libc/unistd/pwrite.c index 56672e5..f80bc40 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/pwrite.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/pwrite.c @@ -17,17 +17,9 @@ ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) { __wasi_fd_pwrite(fildes, &iov, 1, offset, &bytes_written); if (error != 0) { __wasi_fdstat_t fds; -#ifdef __wasilibc_unmodified_upstream - if (error == ENOTCAPABLE && __wasi_fd_stat_get(fildes, &fds) == 0) { -#else if (error == ENOTCAPABLE && __wasi_fd_fdstat_get(fildes, &fds) == 0) { -#endif // Determine why we got ENOTCAPABLE. -#ifdef __wasilibc_unmodified_upstream // generated constant names - if ((fds.fs_rights_base & __WASI_RIGHT_FD_WRITE) == 0) -#else if ((fds.fs_rights_base & __WASI_RIGHTS_FD_WRITE) == 0) -#endif error = EBADF; else error = ESPIPE; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c index 1ebffc6..e08afb9 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c @@ -9,17 +9,12 @@ #include #include -ssize_t readlinkat(int fd, const char *restrict path, char *restrict buf, - size_t bufsize) { +ssize_t __wasilibc_nocwd_readlinkat(int fd, const char *restrict path, char *restrict buf, + size_t bufsize) { size_t bufused; -#ifdef __wasilibc_unmodified_upstream - __wasi_errno_t error = __wasi_file_readlink(fd, path, strlen(path), - buf, bufsize, &bufused); -#else // TODO: Remove the cast on `buf` once the witx is updated with char8 support. - __wasi_errno_t error = __wasi_path_readlink(fd, path, strlen(path), + __wasi_errno_t error = __wasi_path_readlink(fd, path, (uint8_t*)buf, bufsize, &bufused); -#endif if (error != 0) { errno = errno_fixup_directory(fd, error); return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/sleep.c b/libc-bottom-half/cloudlibc/src/libc/unistd/sleep.c index f6a1d89..970287b 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/sleep.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/sleep.c @@ -7,11 +7,7 @@ unsigned int sleep(unsigned int seconds) { struct timespec ts = {.tv_sec = seconds, .tv_nsec = 0}; -#ifdef __wasilibc_unmodified_upstream - if (clock_nanosleep(CLOCK_REALTIME, 0, &ts) != 0) -#else if (clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL) != 0) -#endif return seconds; return 0; } diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c index 9ad06b7..1705afc 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c @@ -9,13 +9,8 @@ #include #include -int symlinkat(const char *path1, int fd, const char *path2) { - __wasi_errno_t error = -#ifdef __wasilibc_unmodified_upstream - __wasi_file_symlink(path1, strlen(path1), fd, path2, strlen(path2)); -#else - __wasi_path_symlink(path1, strlen(path1), fd, path2, strlen(path2)); -#endif +int __wasilibc_nocwd_symlinkat(const char *path1, int fd, const char *path2) { + __wasi_errno_t error = __wasi_path_symlink(path1, fd, path2); if (error != 0) { errno = errno_fixup_directory(fd, error); return -1; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/unlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/unlinkat.c index d970ad1..ea795c2 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/unlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/unlinkat.c @@ -5,31 +5,15 @@ #include #include -#ifdef __wasilibc_unmodified_upstream // unlink -#else #include -#endif #include #include #include #include int unlinkat(int fd, const char *path, int flag) { -#ifdef __wasilibc_unmodified_upstream // unlink - __wasi_ulflags_t ulflags = 0; - if ((flag & AT_REMOVEDIR) != 0) - ulflags |= __WASI_UNLINK_REMOVEDIR; - __wasi_errno_t error = - __wasi_file_unlink(fd, path, strlen(path), ulflags); - if (error != 0) { - errno = errno_fixup_directory(fd, error); - return -1; - } - return 0; -#else if ((flag & AT_REMOVEDIR) != 0) { return __wasilibc_rmdirat(fd, path); } return __wasilibc_unlinkat(fd, path); -#endif } diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/usleep.c b/libc-bottom-half/cloudlibc/src/libc/unistd/usleep.c index 51ee5cb..8005f17 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/usleep.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/usleep.c @@ -9,11 +9,7 @@ int usleep(useconds_t useconds) { struct timespec ts = {.tv_sec = useconds / 1000000, .tv_nsec = useconds % 1000000 * 1000}; -#ifdef __wasilibc_unmodified_upstream - int error = clock_nanosleep(CLOCK_REALTIME, 0, &ts); -#else int error = clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL); -#endif if (error != 0) { errno = error; return -1; diff --git a/libc-bottom-half/getpid/getpid.c b/libc-bottom-half/getpid/getpid.c new file mode 100644 index 0000000..d2920ac --- /dev/null +++ b/libc-bottom-half/getpid/getpid.c @@ -0,0 +1,6 @@ +#include + +pid_t getpid(void) { + // Return an arbitrary value, greater than 1 which is special. + return 42; +} diff --git a/libc-bottom-half/headers/private/stdio.h b/libc-bottom-half/headers/private/stdio.h index dfbefa1..b135b6a 100644 --- a/libc-bottom-half/headers/private/stdio.h +++ b/libc-bottom-half/headers/private/stdio.h @@ -1,2 +1,3 @@ #include <_/cdefs.h> int snprintf(char *str, size_t size, const char *format, ...); +int rename(const char *oldpath, const char *newpath); diff --git a/libc-bottom-half/headers/private/stdlib.h b/libc-bottom-half/headers/private/stdlib.h index f1e8d6f..8c2b395 100644 --- a/libc-bottom-half/headers/private/stdlib.h +++ b/libc-bottom-half/headers/private/stdlib.h @@ -4,3 +4,5 @@ #include #include_next + +int clearenv(void); diff --git a/libc-bottom-half/headers/public/__header_fcntl.h b/libc-bottom-half/headers/public/__header_fcntl.h index 9826439..04252ac 100644 --- a/libc-bottom-half/headers/public/__header_fcntl.h +++ b/libc-bottom-half/headers/public/__header_fcntl.h @@ -56,4 +56,6 @@ #define AT_SYMLINK_FOLLOW (0x2) #define AT_REMOVEDIR (0x4) +#define AT_FDCWD (-2) + #endif diff --git a/libc-bottom-half/headers/public/wasi/api.h b/libc-bottom-half/headers/public/wasi/api.h index 734d212..7a208be 100644 --- a/libc-bottom-half/headers/public/wasi/api.h +++ b/libc-bottom-half/headers/public/wasi/api.h @@ -1,6 +1,13 @@ /** * THIS FILE IS AUTO-GENERATED from the following files: - * typenames.witx, wasi_snapshot_preview1.witx + * wasi_snapshot_preview1.witx + * + * To regenerate this file execute: + * + * cargo run --manifest-path tools/wasi-headers/Cargo.toml generate-libc + * + * Modifications to this file will cause CI to fail, the code generator tool + * must be modified to change this file. * * @file * This file describes the [WASI] interface, consisting of functions, types, @@ -502,160 +509,157 @@ typedef uint64_t __wasi_rights_t; * If `path_open` is set, includes the right to invoke * `path_open` with `fdflags::dsync`. */ -#define __WASI_RIGHTS_FD_DATASYNC (UINT64_C(1)) +#define __WASI_RIGHTS_FD_DATASYNC ((__wasi_rights_t)(1 << 0)) /** * The right to invoke `fd_read` and `sock_recv`. * If `rights::fd_seek` is set, includes the right to invoke `fd_pread`. */ -#define __WASI_RIGHTS_FD_READ (UINT64_C(2)) +#define __WASI_RIGHTS_FD_READ ((__wasi_rights_t)(1 << 1)) /** * The right to invoke `fd_seek`. This flag implies `rights::fd_tell`. */ -#define __WASI_RIGHTS_FD_SEEK (UINT64_C(4)) +#define __WASI_RIGHTS_FD_SEEK ((__wasi_rights_t)(1 << 2)) /** * The right to invoke `fd_fdstat_set_flags`. */ -#define __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS (UINT64_C(8)) +#define __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(1 << 3)) /** * The right to invoke `fd_sync`. * If `path_open` is set, includes the right to invoke * `path_open` with `fdflags::rsync` and `fdflags::dsync`. */ -#define __WASI_RIGHTS_FD_SYNC (UINT64_C(16)) +#define __WASI_RIGHTS_FD_SYNC ((__wasi_rights_t)(1 << 4)) /** * The right to invoke `fd_seek` in such a way that the file offset * remains unaltered (i.e., `whence::cur` with offset zero), or to * invoke `fd_tell`. */ -#define __WASI_RIGHTS_FD_TELL (UINT64_C(32)) +#define __WASI_RIGHTS_FD_TELL ((__wasi_rights_t)(1 << 5)) /** * The right to invoke `fd_write` and `sock_send`. * If `rights::fd_seek` is set, includes the right to invoke `fd_pwrite`. */ -#define __WASI_RIGHTS_FD_WRITE (UINT64_C(64)) +#define __WASI_RIGHTS_FD_WRITE ((__wasi_rights_t)(1 << 6)) /** * The right to invoke `fd_advise`. */ -#define __WASI_RIGHTS_FD_ADVISE (UINT64_C(128)) +#define __WASI_RIGHTS_FD_ADVISE ((__wasi_rights_t)(1 << 7)) /** * The right to invoke `fd_allocate`. */ -#define __WASI_RIGHTS_FD_ALLOCATE (UINT64_C(256)) +#define __WASI_RIGHTS_FD_ALLOCATE ((__wasi_rights_t)(1 << 8)) /** * The right to invoke `path_create_directory`. */ -#define __WASI_RIGHTS_PATH_CREATE_DIRECTORY (UINT64_C(512)) +#define __WASI_RIGHTS_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(1 << 9)) /** * If `path_open` is set, the right to invoke `path_open` with `oflags::creat`. */ -#define __WASI_RIGHTS_PATH_CREATE_FILE (UINT64_C(1024)) +#define __WASI_RIGHTS_PATH_CREATE_FILE ((__wasi_rights_t)(1 << 10)) /** * The right to invoke `path_link` with the file descriptor as the * source directory. */ -#define __WASI_RIGHTS_PATH_LINK_SOURCE (UINT64_C(2048)) +#define __WASI_RIGHTS_PATH_LINK_SOURCE ((__wasi_rights_t)(1 << 11)) /** * The right to invoke `path_link` with the file descriptor as the * target directory. */ -#define __WASI_RIGHTS_PATH_LINK_TARGET (UINT64_C(4096)) +#define __WASI_RIGHTS_PATH_LINK_TARGET ((__wasi_rights_t)(1 << 12)) /** * The right to invoke `path_open`. */ -#define __WASI_RIGHTS_PATH_OPEN (UINT64_C(8192)) +#define __WASI_RIGHTS_PATH_OPEN ((__wasi_rights_t)(1 << 13)) /** * The right to invoke `fd_readdir`. */ -#define __WASI_RIGHTS_FD_READDIR (UINT64_C(16384)) +#define __WASI_RIGHTS_FD_READDIR ((__wasi_rights_t)(1 << 14)) /** * The right to invoke `path_readlink`. */ -#define __WASI_RIGHTS_PATH_READLINK (UINT64_C(32768)) +#define __WASI_RIGHTS_PATH_READLINK ((__wasi_rights_t)(1 << 15)) /** * The right to invoke `path_rename` with the file descriptor as the source directory. */ -#define __WASI_RIGHTS_PATH_RENAME_SOURCE (UINT64_C(65536)) +#define __WASI_RIGHTS_PATH_RENAME_SOURCE ((__wasi_rights_t)(1 << 16)) /** * The right to invoke `path_rename` with the file descriptor as the target directory. */ -#define __WASI_RIGHTS_PATH_RENAME_TARGET (UINT64_C(131072)) +#define __WASI_RIGHTS_PATH_RENAME_TARGET ((__wasi_rights_t)(1 << 17)) /** * The right to invoke `path_filestat_get`. */ -#define __WASI_RIGHTS_PATH_FILESTAT_GET (UINT64_C(262144)) +#define __WASI_RIGHTS_PATH_FILESTAT_GET ((__wasi_rights_t)(1 << 18)) /** * The right to change a file's size (there is no `path_filestat_set_size`). * If `path_open` is set, includes the right to invoke `path_open` with `oflags::trunc`. */ -#define __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE (UINT64_C(524288)) +#define __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(1 << 19)) /** * The right to invoke `path_filestat_set_times`. */ -#define __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES (UINT64_C(1048576)) +#define __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(1 << 20)) /** * The right to invoke `fd_filestat_get`. */ -#define __WASI_RIGHTS_FD_FILESTAT_GET (UINT64_C(2097152)) +#define __WASI_RIGHTS_FD_FILESTAT_GET ((__wasi_rights_t)(1 << 21)) /** * The right to invoke `fd_filestat_set_size`. */ -#define __WASI_RIGHTS_FD_FILESTAT_SET_SIZE (UINT64_C(4194304)) +#define __WASI_RIGHTS_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(1 << 22)) /** * The right to invoke `fd_filestat_set_times`. */ -#define __WASI_RIGHTS_FD_FILESTAT_SET_TIMES (UINT64_C(8388608)) +#define __WASI_RIGHTS_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(1 << 23)) /** * The right to invoke `path_symlink`. */ -#define __WASI_RIGHTS_PATH_SYMLINK (UINT64_C(16777216)) +#define __WASI_RIGHTS_PATH_SYMLINK ((__wasi_rights_t)(1 << 24)) /** * The right to invoke `path_remove_directory`. */ -#define __WASI_RIGHTS_PATH_REMOVE_DIRECTORY (UINT64_C(33554432)) +#define __WASI_RIGHTS_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(1 << 25)) /** * The right to invoke `path_unlink_file`. */ -#define __WASI_RIGHTS_PATH_UNLINK_FILE (UINT64_C(67108864)) +#define __WASI_RIGHTS_PATH_UNLINK_FILE ((__wasi_rights_t)(1 << 26)) /** * If `rights::fd_read` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_read`. * If `rights::fd_write` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_write`. */ -#define __WASI_RIGHTS_POLL_FD_READWRITE (UINT64_C(134217728)) +#define __WASI_RIGHTS_POLL_FD_READWRITE ((__wasi_rights_t)(1 << 27)) /** * The right to invoke `sock_shutdown`. */ -#define __WASI_RIGHTS_SOCK_SHUTDOWN (UINT64_C(268435456)) - -_Static_assert(sizeof(__wasi_rights_t) == 8, "witx calculated size"); -_Static_assert(_Alignof(__wasi_rights_t) == 8, "witx calculated align"); +#define __WASI_RIGHTS_SOCK_SHUTDOWN ((__wasi_rights_t)(1 << 28)) /** * A file descriptor handle. @@ -749,7 +753,7 @@ _Static_assert(sizeof(__wasi_dircookie_t) == 8, "witx calculated size"); _Static_assert(_Alignof(__wasi_dircookie_t) == 8, "witx calculated align"); /** - * The type for the $d_namlen field of $dirent. + * The type for the `dirent::d_namlen` field of `dirent` struct. */ typedef uint32_t __wasi_dirnamlen_t; @@ -891,32 +895,29 @@ typedef uint16_t __wasi_fdflags_t; /** * Append mode: Data written to the file is always appended to the file's end. */ -#define __WASI_FDFLAGS_APPEND (UINT16_C(1)) +#define __WASI_FDFLAGS_APPEND ((__wasi_fdflags_t)(1 << 0)) /** * Write according to synchronized I/O data integrity completion. Only the data stored in the file is synchronized. */ -#define __WASI_FDFLAGS_DSYNC (UINT16_C(2)) +#define __WASI_FDFLAGS_DSYNC ((__wasi_fdflags_t)(1 << 1)) /** * Non-blocking mode. */ -#define __WASI_FDFLAGS_NONBLOCK (UINT16_C(4)) +#define __WASI_FDFLAGS_NONBLOCK ((__wasi_fdflags_t)(1 << 2)) /** * Synchronized read I/O operations. */ -#define __WASI_FDFLAGS_RSYNC (UINT16_C(8)) +#define __WASI_FDFLAGS_RSYNC ((__wasi_fdflags_t)(1 << 3)) /** * Write according to synchronized I/O file integrity completion. In * addition to synchronizing the data stored in the file, the implementation * may also synchronously update the file's metadata. */ -#define __WASI_FDFLAGS_SYNC (UINT16_C(16)) - -_Static_assert(sizeof(__wasi_fdflags_t) == 2, "witx calculated size"); -_Static_assert(_Alignof(__wasi_fdflags_t) == 2, "witx calculated align"); +#define __WASI_FDFLAGS_SYNC ((__wasi_fdflags_t)(1 << 4)) /** * File descriptor attributes. @@ -969,25 +970,22 @@ typedef uint16_t __wasi_fstflags_t; /** * Adjust the last data access timestamp to the value stored in `filestat::atim`. */ -#define __WASI_FSTFLAGS_ATIM (UINT16_C(1)) +#define __WASI_FSTFLAGS_ATIM ((__wasi_fstflags_t)(1 << 0)) /** * Adjust the last data access timestamp to the time of clock `clockid::realtime`. */ -#define __WASI_FSTFLAGS_ATIM_NOW (UINT16_C(2)) +#define __WASI_FSTFLAGS_ATIM_NOW ((__wasi_fstflags_t)(1 << 1)) /** * Adjust the last data modification timestamp to the value stored in `filestat::mtim`. */ -#define __WASI_FSTFLAGS_MTIM (UINT16_C(4)) +#define __WASI_FSTFLAGS_MTIM ((__wasi_fstflags_t)(1 << 2)) /** * Adjust the last data modification timestamp to the time of clock `clockid::realtime`. */ -#define __WASI_FSTFLAGS_MTIM_NOW (UINT16_C(8)) - -_Static_assert(sizeof(__wasi_fstflags_t) == 2, "witx calculated size"); -_Static_assert(_Alignof(__wasi_fstflags_t) == 2, "witx calculated align"); +#define __WASI_FSTFLAGS_MTIM_NOW ((__wasi_fstflags_t)(1 << 3)) /** * Flags determining the method of how paths are resolved. @@ -997,10 +995,7 @@ typedef uint32_t __wasi_lookupflags_t; /** * As long as the resolved path corresponds to a symbolic link, it is expanded. */ -#define __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW (UINT32_C(1)) - -_Static_assert(sizeof(__wasi_lookupflags_t) == 4, "witx calculated size"); -_Static_assert(_Alignof(__wasi_lookupflags_t) == 4, "witx calculated align"); +#define __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW ((__wasi_lookupflags_t)(1 << 0)) /** * Open flags used by `path_open`. @@ -1010,25 +1005,22 @@ typedef uint16_t __wasi_oflags_t; /** * Create file if it does not exist. */ -#define __WASI_OFLAGS_CREAT (UINT16_C(1)) +#define __WASI_OFLAGS_CREAT ((__wasi_oflags_t)(1 << 0)) /** * Fail if not a directory. */ -#define __WASI_OFLAGS_DIRECTORY (UINT16_C(2)) +#define __WASI_OFLAGS_DIRECTORY ((__wasi_oflags_t)(1 << 1)) /** * Fail if file already exists. */ -#define __WASI_OFLAGS_EXCL (UINT16_C(4)) +#define __WASI_OFLAGS_EXCL ((__wasi_oflags_t)(1 << 2)) /** * Truncate file to size 0. */ -#define __WASI_OFLAGS_TRUNC (UINT16_C(8)) - -_Static_assert(sizeof(__wasi_oflags_t) == 2, "witx calculated size"); -_Static_assert(_Alignof(__wasi_oflags_t) == 2, "witx calculated align"); +#define __WASI_OFLAGS_TRUNC ((__wasi_oflags_t)(1 << 3)) /** * Number of hard links to an inode. @@ -1139,13 +1131,10 @@ typedef uint16_t __wasi_eventrwflags_t; /** * The peer of this socket has closed or disconnected. */ -#define __WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP (UINT16_C(1)) - -_Static_assert(sizeof(__wasi_eventrwflags_t) == 2, "witx calculated size"); -_Static_assert(_Alignof(__wasi_eventrwflags_t) == 2, "witx calculated align"); +#define __WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP ((__wasi_eventrwflags_t)(1 << 0)) /** - * The contents of an $event when type is `eventtype::fd_read` or + * The contents of an `event` when type is `eventtype::fd_read` or * `eventtype::fd_write`. */ typedef struct __wasi_event_fd_readwrite_t { @@ -1213,10 +1202,7 @@ typedef uint16_t __wasi_subclockflags_t; * provided in `subscription_clock::timeout` relative to the * current time value of clock `subscription_clock::id`. */ -#define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME (UINT16_C(1)) - -_Static_assert(sizeof(__wasi_subclockflags_t) == 2, "witx calculated size"); -_Static_assert(_Alignof(__wasi_subclockflags_t) == 2, "witx calculated align"); +#define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME ((__wasi_subclockflags_t)(1 << 0)) /** * The contents of a `subscription` when type is `eventtype::clock`. @@ -1277,15 +1263,12 @@ typedef union __wasi_subscription_u_u_t { __wasi_subscription_fd_readwrite_t fd_write; } __wasi_subscription_u_u_t; typedef struct __wasi_subscription_u_t { - __wasi_eventtype_t tag; + uint8_t tag; __wasi_subscription_u_u_t u; } __wasi_subscription_u_t; _Static_assert(sizeof(__wasi_subscription_u_t) == 40, "witx calculated size"); _Static_assert(_Alignof(__wasi_subscription_u_t) == 8, "witx calculated align"); -_Static_assert(offsetof(__wasi_subscription_u_t, u) == 8, "witx calculated union offset"); -_Static_assert(sizeof(__wasi_subscription_u_u_t) == 32, "witx calculated union size"); -_Static_assert(_Alignof(__wasi_subscription_u_u_t) == 8, "witx calculated union align"); /** * Subscription to an event. @@ -1519,15 +1502,12 @@ typedef uint16_t __wasi_riflags_t; /** * Returns the message without removing it from the socket's receive queue. */ -#define __WASI_RIFLAGS_RECV_PEEK (UINT16_C(1)) +#define __WASI_RIFLAGS_RECV_PEEK ((__wasi_riflags_t)(1 << 0)) /** * On byte-stream sockets, block until the full amount of data can be returned. */ -#define __WASI_RIFLAGS_RECV_WAITALL (UINT16_C(2)) - -_Static_assert(sizeof(__wasi_riflags_t) == 2, "witx calculated size"); -_Static_assert(_Alignof(__wasi_riflags_t) == 2, "witx calculated align"); +#define __WASI_RIFLAGS_RECV_WAITALL ((__wasi_riflags_t)(1 << 1)) /** * Flags returned by `sock_recv`. @@ -1537,10 +1517,7 @@ typedef uint16_t __wasi_roflags_t; /** * Returned by `sock_recv`: Message data has been truncated. */ -#define __WASI_ROFLAGS_RECV_DATA_TRUNCATED (UINT16_C(1)) - -_Static_assert(sizeof(__wasi_roflags_t) == 2, "witx calculated size"); -_Static_assert(_Alignof(__wasi_roflags_t) == 2, "witx calculated align"); +#define __WASI_ROFLAGS_RECV_DATA_TRUNCATED ((__wasi_roflags_t)(1 << 0)) /** * Flags provided to `sock_send`. As there are currently no flags @@ -1559,15 +1536,12 @@ typedef uint8_t __wasi_sdflags_t; /** * Disables further receive operations. */ -#define __WASI_SDFLAGS_RD (UINT8_C(1)) +#define __WASI_SDFLAGS_RD ((__wasi_sdflags_t)(1 << 0)) /** * Disables further send operations. */ -#define __WASI_SDFLAGS_WR (UINT8_C(2)) - -_Static_assert(sizeof(__wasi_sdflags_t) == 1, "witx calculated size"); -_Static_assert(_Alignof(__wasi_sdflags_t) == 1, "witx calculated align"); +#define __WASI_SDFLAGS_WR ((__wasi_sdflags_t)(1 << 1)) /** * Identifiers for preopened capabilities. @@ -1604,15 +1578,12 @@ typedef union __wasi_prestat_u_t { __wasi_prestat_dir_t dir; } __wasi_prestat_u_t; typedef struct __wasi_prestat_t { - __wasi_preopentype_t tag; + uint8_t tag; __wasi_prestat_u_t u; } __wasi_prestat_t; _Static_assert(sizeof(__wasi_prestat_t) == 8, "witx calculated size"); _Static_assert(_Alignof(__wasi_prestat_t) == 4, "witx calculated align"); -_Static_assert(offsetof(__wasi_prestat_t, u) == 4, "witx calculated union offset"); -_Static_assert(sizeof(__wasi_prestat_u_t) == 4, "witx calculated union size"); -_Static_assert(_Alignof(__wasi_prestat_u_t) == 4, "witx calculated union align"); /** * @defgroup wasi_snapshot_preview1 @@ -1625,458 +1596,296 @@ _Static_assert(_Alignof(__wasi_prestat_u_t) == 4, "witx calculated union align") */ __wasi_errno_t __wasi_args_get( uint8_t * * argv, - uint8_t * argv_buf -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("args_get"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Return command-line argument data sizes. + * @return + * Returns the number of arguments and the size of the argument string + * data, or an error. */ __wasi_errno_t __wasi_args_sizes_get( - /** - * The number of arguments. - */ - __wasi_size_t *argc, - /** - * The size of the argument string data. - */ - __wasi_size_t *argv_buf_size -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("args_sizes_get"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0, + __wasi_size_t *retptr1 +) __attribute__((__warn_unused_result__)); /** * Read environment variable data. * The sizes of the buffers should match that returned by `environ_sizes_get`. */ __wasi_errno_t __wasi_environ_get( uint8_t * * environ, - uint8_t * environ_buf -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("environ_get"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Return environment variable data sizes. + * @return + * Returns the number of environment variable arguments and the size of the + * environment variable data. */ __wasi_errno_t __wasi_environ_sizes_get( - /** - * The number of environment variable arguments. - */ - __wasi_size_t *environc, - /** - * The size of the environment variable data. - */ - __wasi_size_t *environ_buf_size -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("environ_sizes_get"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0, + __wasi_size_t *retptr1 +) __attribute__((__warn_unused_result__)); /** * Return the resolution of a clock. * Implementations are required to provide a non-zero value for supported clocks. For unsupported clocks, * return `errno::inval`. * Note: This is similar to `clock_getres` in POSIX. + * @return + * The resolution of the clock, or an error if one happened. */ __wasi_errno_t __wasi_clock_res_get( /** * The clock for which to return the resolution. */ __wasi_clockid_t id, - - /** - * The resolution of the clock. - */ - __wasi_timestamp_t *resolution -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("clock_res_get"), - __warn_unused_result__ -)); - + __wasi_timestamp_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Return the time value of a clock. * Note: This is similar to `clock_gettime` in POSIX. + * @return + * The time value of the clock. */ __wasi_errno_t __wasi_clock_time_get( /** * The clock for which to return the time. */ __wasi_clockid_t id, - /** * The maximum lag (exclusive) that the returned time value may have, compared to its actual value. */ __wasi_timestamp_t precision, - - /** - * The time value of the clock. - */ - __wasi_timestamp_t *time -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("clock_time_get"), - __warn_unused_result__ -)); - + __wasi_timestamp_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Provide file advisory information on a file descriptor. * Note: This is similar to `posix_fadvise` in POSIX. */ __wasi_errno_t __wasi_fd_advise( __wasi_fd_t fd, - /** * The offset within the file to which the advisory applies. */ __wasi_filesize_t offset, - /** * The length of the region to which the advisory applies. */ __wasi_filesize_t len, - /** * The advice. */ __wasi_advice_t advice -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_advise"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Force the allocation of space in a file. * Note: This is similar to `posix_fallocate` in POSIX. */ __wasi_errno_t __wasi_fd_allocate( __wasi_fd_t fd, - /** * The offset at which to start the allocation. */ __wasi_filesize_t offset, - /** * The length of the area that is allocated. */ __wasi_filesize_t len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_allocate"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Close a file descriptor. * Note: This is similar to `close` in POSIX. */ __wasi_errno_t __wasi_fd_close( __wasi_fd_t fd -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_close"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Synchronize the data of a file to disk. * Note: This is similar to `fdatasync` in POSIX. */ __wasi_errno_t __wasi_fd_datasync( __wasi_fd_t fd -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_datasync"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Get the attributes of a file descriptor. * Note: This returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields. + * @return + * The buffer where the file descriptor's attributes are stored. */ __wasi_errno_t __wasi_fd_fdstat_get( __wasi_fd_t fd, - - /** - * The buffer where the file descriptor's attributes are stored. - */ - __wasi_fdstat_t *stat -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_fdstat_get"), - __warn_unused_result__ -)); - + __wasi_fdstat_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Adjust the flags associated with a file descriptor. * Note: This is similar to `fcntl(fd, F_SETFL, flags)` in POSIX. */ __wasi_errno_t __wasi_fd_fdstat_set_flags( __wasi_fd_t fd, - /** * The desired values of the file descriptor flags. */ __wasi_fdflags_t flags -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_fdstat_set_flags"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Adjust the rights associated with a file descriptor. * This can only be used to remove rights, and returns `errno::notcapable` if called in a way that would attempt to add rights */ __wasi_errno_t __wasi_fd_fdstat_set_rights( __wasi_fd_t fd, - /** * The desired rights of the file descriptor. */ __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_fdstat_set_rights"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Return the attributes of an open file. + * @return + * The buffer where the file's attributes are stored. */ __wasi_errno_t __wasi_fd_filestat_get( __wasi_fd_t fd, - - /** - * The buffer where the file's attributes are stored. - */ - __wasi_filestat_t *buf -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_filestat_get"), - __warn_unused_result__ -)); - + __wasi_filestat_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Adjust the size of an open file. If this increases the file's size, the extra bytes are filled with zeros. * Note: This is similar to `ftruncate` in POSIX. */ __wasi_errno_t __wasi_fd_filestat_set_size( __wasi_fd_t fd, - /** * The desired file size. */ __wasi_filesize_t size -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_filestat_set_size"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Adjust the timestamps of an open file or directory. * Note: This is similar to `futimens` in POSIX. */ __wasi_errno_t __wasi_fd_filestat_set_times( __wasi_fd_t fd, - /** * The desired values of the data access timestamp. */ __wasi_timestamp_t atim, - /** * The desired values of the data modification timestamp. */ __wasi_timestamp_t mtim, - /** * A bitmask indicating which timestamps to adjust. */ __wasi_fstflags_t fst_flags -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_filestat_set_times"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Read from a file descriptor, without using and updating the file descriptor's offset. * Note: This is similar to `preadv` in POSIX. + * @return + * The number of bytes read. */ __wasi_errno_t __wasi_fd_pread( __wasi_fd_t fd, - /** * List of scatter/gather vectors in which to store data. */ const __wasi_iovec_t *iovs, - /** * The length of the array pointed to by `iovs`. */ size_t iovs_len, - /** * The offset within the file at which to read. */ __wasi_filesize_t offset, - - /** - * The number of bytes read. - */ - __wasi_size_t *nread -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_pread"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Return a description of the given preopened file descriptor. + * @return + * The buffer where the description is stored. */ __wasi_errno_t __wasi_fd_prestat_get( __wasi_fd_t fd, - - /** - * The buffer where the description is stored. - */ - __wasi_prestat_t *buf -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_prestat_get"), - __warn_unused_result__ -)); - + __wasi_prestat_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Return a description of the given preopened file descriptor. */ __wasi_errno_t __wasi_fd_prestat_dir_name( __wasi_fd_t fd, - /** * A buffer into which to write the preopened directory name. */ uint8_t * path, - __wasi_size_t path_len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_prestat_dir_name"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Write to a file descriptor, without using and updating the file descriptor's offset. * Note: This is similar to `pwritev` in POSIX. + * @return + * The number of bytes written. */ __wasi_errno_t __wasi_fd_pwrite( __wasi_fd_t fd, - /** * List of scatter/gather vectors from which to retrieve data. */ const __wasi_ciovec_t *iovs, - /** * The length of the array pointed to by `iovs`. */ size_t iovs_len, - /** * The offset within the file at which to write. */ __wasi_filesize_t offset, - - /** - * The number of bytes written. - */ - __wasi_size_t *nwritten -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_pwrite"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Read from a file descriptor. * Note: This is similar to `readv` in POSIX. + * @return + * The number of bytes read. */ __wasi_errno_t __wasi_fd_read( __wasi_fd_t fd, - /** * List of scatter/gather vectors to which to store data. */ const __wasi_iovec_t *iovs, - /** * The length of the array pointed to by `iovs`. */ size_t iovs_len, - - /** - * The number of bytes read. - */ - __wasi_size_t *nread -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_read"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Read directory entries from a directory. * When successful, the contents of the output buffer consist of a sequence of - * directory entries. Each directory entry consists of a dirent_t object, - * followed by dirent_t::d_namlen bytes holding the name of the directory + * directory entries. Each directory entry consists of a `dirent` object, + * followed by `dirent::d_namlen` bytes holding the name of the directory * entry. * This function fills the output buffer as much as possible, potentially * truncating the last directory entry. This allows the caller to grow its * read buffer size in case it's too small to fit a single large directory * entry, or skip the oversized directory entry. + * @return + * The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached. */ __wasi_errno_t __wasi_fd_readdir( __wasi_fd_t fd, - /** * The buffer where directory entries are stored */ uint8_t * buf, - __wasi_size_t buf_len, - /** * The location within the directory to start reading */ __wasi_dircookie_t cookie, - - /** - * The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached. - */ - __wasi_size_t *bufused -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_readdir"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Atomically replace a file descriptor by renumbering another file descriptor. * Due to the strong focus on thread safety, this environment does not provide @@ -2089,238 +1898,141 @@ __wasi_errno_t __wasi_fd_readdir( */ __wasi_errno_t __wasi_fd_renumber( __wasi_fd_t fd, - /** * The file descriptor to overwrite. */ __wasi_fd_t to -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_renumber"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Move the offset of a file descriptor. * Note: This is similar to `lseek` in POSIX. + * @return + * The new offset of the file descriptor, relative to the start of the file. */ __wasi_errno_t __wasi_fd_seek( __wasi_fd_t fd, - /** * The number of bytes to move. */ __wasi_filedelta_t offset, - /** * The base from which the offset is relative. */ __wasi_whence_t whence, - - /** - * The new offset of the file descriptor, relative to the start of the file. - */ - __wasi_filesize_t *newoffset -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_seek"), - __warn_unused_result__ -)); - + __wasi_filesize_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Synchronize the data and metadata of a file to disk. * Note: This is similar to `fsync` in POSIX. */ __wasi_errno_t __wasi_fd_sync( __wasi_fd_t fd -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_sync"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Return the current offset of a file descriptor. * Note: This is similar to `lseek(fd, 0, SEEK_CUR)` in POSIX. + * @return + * The current offset of the file descriptor, relative to the start of the file. */ __wasi_errno_t __wasi_fd_tell( __wasi_fd_t fd, - - /** - * The current offset of the file descriptor, relative to the start of the file. - */ - __wasi_filesize_t *offset -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_tell"), - __warn_unused_result__ -)); - + __wasi_filesize_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Write to a file descriptor. * Note: This is similar to `writev` in POSIX. */ __wasi_errno_t __wasi_fd_write( __wasi_fd_t fd, - /** * List of scatter/gather vectors from which to retrieve data. */ const __wasi_ciovec_t *iovs, - /** * The length of the array pointed to by `iovs`. */ size_t iovs_len, - - /** - * The number of bytes written. - */ - __wasi_size_t *nwritten -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("fd_write"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Create a directory. * Note: This is similar to `mkdirat` in POSIX. */ __wasi_errno_t __wasi_path_create_directory( __wasi_fd_t fd, - /** * The path at which to create the directory. */ - const char *path, - - /** - * The length of the buffer pointed to by `path`. - */ - size_t path_len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_create_directory"), - __warn_unused_result__ -)); - + const char *path +) __attribute__((__warn_unused_result__)); /** * Return the attributes of a file or directory. * Note: This is similar to `stat` in POSIX. + * @return + * The buffer where the file's attributes are stored. */ __wasi_errno_t __wasi_path_filestat_get( __wasi_fd_t fd, - /** * Flags determining the method of how the path is resolved. */ __wasi_lookupflags_t flags, - /** * The path of the file or directory to inspect. */ const char *path, - - /** - * The length of the buffer pointed to by `path`. - */ - size_t path_len, - - /** - * The buffer where the file's attributes are stored. - */ - __wasi_filestat_t *buf -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_filestat_get"), - __warn_unused_result__ -)); - + __wasi_filestat_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Adjust the timestamps of a file or directory. * Note: This is similar to `utimensat` in POSIX. */ __wasi_errno_t __wasi_path_filestat_set_times( __wasi_fd_t fd, - /** * Flags determining the method of how the path is resolved. */ __wasi_lookupflags_t flags, - /** * The path of the file or directory to operate on. */ const char *path, - - /** - * The length of the buffer pointed to by `path`. - */ - size_t path_len, - /** * The desired values of the data access timestamp. */ __wasi_timestamp_t atim, - /** * The desired values of the data modification timestamp. */ __wasi_timestamp_t mtim, - /** * A bitmask indicating which timestamps to adjust. */ __wasi_fstflags_t fst_flags -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_filestat_set_times"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Create a hard link. * Note: This is similar to `linkat` in POSIX. */ __wasi_errno_t __wasi_path_link( __wasi_fd_t old_fd, - /** * Flags determining the method of how the path is resolved. */ __wasi_lookupflags_t old_flags, - /** * The source path from which to link. */ const char *old_path, - - /** - * The length of the buffer pointed to by `old_path`. - */ - size_t old_path_len, - /** * The working directory at which the resolution of the new path starts. */ __wasi_fd_t new_fd, - /** * The destination path at which to create the hard link. */ - const char *new_path, - - /** - * The length of the buffer pointed to by `new_path`. - */ - size_t new_path_len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_link"), - __warn_unused_result__ -)); - + const char *new_path +) __attribute__((__warn_unused_result__)); /** * Open a file or directory. * The returned file descriptor is not guaranteed to be the lowest-numbered @@ -2329,31 +2041,24 @@ __wasi_errno_t __wasi_path_link( * is error-prone in multi-threaded contexts. The returned file descriptor is * guaranteed to be less than 2**31. * Note: This is similar to `openat` in POSIX. + * @return + * The file descriptor of the file that has been opened. */ __wasi_errno_t __wasi_path_open( __wasi_fd_t fd, - /** * Flags determining the method of how the path is resolved. */ __wasi_lookupflags_t dirflags, - /** * The relative path of the file or directory to open, relative to the * `path_open::fd` directory. */ const char *path, - - /** - * The length of the buffer pointed to by `path`. - */ - size_t path_len, - /** * The method by which to open the file. */ __wasi_oflags_t oflags, - /** * The initial rights of the newly created file descriptor. The * implementation is allowed to return a file descriptor with fewer rights @@ -2364,55 +2069,29 @@ __wasi_errno_t __wasi_path_open( * file descriptors derived from it. */ __wasi_rights_t fs_rights_base, - - __wasi_rights_t fs_rights_inherting, - + __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fdflags, - - /** - * The file descriptor of the file that has been opened. - */ - __wasi_fd_t *opened_fd -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_open"), - __warn_unused_result__ -)); - + __wasi_fd_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Read the contents of a symbolic link. * Note: This is similar to `readlinkat` in POSIX. + * @return + * The number of bytes placed in the buffer. */ __wasi_errno_t __wasi_path_readlink( __wasi_fd_t fd, - /** * The path of the symbolic link from which to read. */ const char *path, - - /** - * The length of the buffer pointed to by `path`. - */ - size_t path_len, - /** * The buffer to which to write the contents of the symbolic link. */ uint8_t * buf, - __wasi_size_t buf_len, - - /** - * The number of bytes placed in the buffer. - */ - __wasi_size_t *bufused -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_readlink"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Remove a directory. * Return `errno::notempty` if the directory is not empty. @@ -2420,59 +2099,30 @@ __wasi_errno_t __wasi_path_readlink( */ __wasi_errno_t __wasi_path_remove_directory( __wasi_fd_t fd, - /** * The path to a directory to remove. */ - const char *path, - - /** - * The length of the buffer pointed to by `path`. - */ - size_t path_len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_remove_directory"), - __warn_unused_result__ -)); - + const char *path +) __attribute__((__warn_unused_result__)); /** * Rename a file or directory. * Note: This is similar to `renameat` in POSIX. */ __wasi_errno_t __wasi_path_rename( __wasi_fd_t fd, - /** * The source path of the file or directory to rename. */ const char *old_path, - - /** - * The length of the buffer pointed to by `old_path`. - */ - size_t old_path_len, - /** * The working directory at which the resolution of the new path starts. */ __wasi_fd_t new_fd, - /** * The destination path to which to rename the file or directory. */ - const char *new_path, - - /** - * The length of the buffer pointed to by `new_path`. - */ - size_t new_path_len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_rename"), - __warn_unused_result__ -)); - + const char *new_path +) __attribute__((__warn_unused_result__)); /** * Create a symbolic link. * Note: This is similar to `symlinkat` in POSIX. @@ -2482,29 +2132,12 @@ __wasi_errno_t __wasi_path_symlink( * The contents of the symbolic link. */ const char *old_path, - - /** - * The length of the buffer pointed to by `old_path`. - */ - size_t old_path_len, - __wasi_fd_t fd, - /** * The destination path at which to create the symbolic link. */ - const char *new_path, - - /** - * The length of the buffer pointed to by `new_path`. - */ - size_t new_path_len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_symlink"), - __warn_unused_result__ -)); - + const char *new_path +) __attribute__((__warn_unused_result__)); /** * Unlink a file. * Return `errno::isdir` if the path refers to a directory. @@ -2512,51 +2145,31 @@ __wasi_errno_t __wasi_path_symlink( */ __wasi_errno_t __wasi_path_unlink_file( __wasi_fd_t fd, - /** * The path to a file to unlink. */ - const char *path, - - /** - * The length of the buffer pointed to by `path`. - */ - size_t path_len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("path_unlink_file"), - __warn_unused_result__ -)); - + const char *path +) __attribute__((__warn_unused_result__)); /** * Concurrently poll for the occurrence of a set of events. + * @return + * The number of events stored. */ __wasi_errno_t __wasi_poll_oneoff( /** * The events to which to subscribe. */ const __wasi_subscription_t * in, - /** * The events that have occurred. */ __wasi_event_t * out, - /** * Both the number of subscriptions and events. */ __wasi_size_t nsubscriptions, - - /** - * The number of events stored. - */ - __wasi_size_t *nevents -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("poll_oneoff"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Terminate the process normally. An exit code of 0 indicates successful * termination of the program. The meanings of other values is dependent on @@ -2567,10 +2180,7 @@ _Noreturn void __wasi_proc_exit( * The exit code returned by the process. */ __wasi_exitcode_t rval -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("proc_exit"))); - +); /** * Send a signal to the process of the calling thread. * Note: This is similar to `raise` in POSIX. @@ -2580,24 +2190,14 @@ __wasi_errno_t __wasi_proc_raise( * The signal condition to trigger. */ __wasi_signal_t sig -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("proc_raise"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Temporarily yield execution of the calling thread. * Note: This is similar to `sched_yield` in POSIX. */ __wasi_errno_t __wasi_sched_yield( void -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("sched_yield"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Write high-quality random data into a buffer. * This function blocks when the implementation is unable to immediately @@ -2611,101 +2211,66 @@ __wasi_errno_t __wasi_random_get( * The buffer to fill with random data. */ uint8_t * buf, - __wasi_size_t buf_len -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("random_get"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** * Receive a message from a socket. * Note: This is similar to `recv` in POSIX, though it also supports reading * the data into multiple buffers in the manner of `readv`. + * @return + * Number of bytes stored in ri_data and message flags. */ __wasi_errno_t __wasi_sock_recv( __wasi_fd_t fd, - /** * List of scatter/gather vectors to which to store data. */ const __wasi_iovec_t *ri_data, - /** * The length of the array pointed to by `ri_data`. */ size_t ri_data_len, - /** * Message flags. */ __wasi_riflags_t ri_flags, - - /** - * Number of bytes stored in ri_data. - */ - __wasi_size_t *ro_datalen, - /** - * Message flags. - */ - __wasi_roflags_t *ro_flags -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("sock_recv"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0, + __wasi_roflags_t *retptr1 +) __attribute__((__warn_unused_result__)); /** * Send a message on a socket. * Note: This is similar to `send` in POSIX, though it also supports writing * the data from multiple buffers in the manner of `writev`. + * @return + * Number of bytes transmitted. */ __wasi_errno_t __wasi_sock_send( __wasi_fd_t fd, - /** * List of scatter/gather vectors to which to retrieve data */ const __wasi_ciovec_t *si_data, - /** * The length of the array pointed to by `si_data`. */ size_t si_data_len, - /** * Message flags. */ __wasi_siflags_t si_flags, - - /** - * Number of bytes transmitted. - */ - __wasi_size_t *so_datalen -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("sock_send"), - __warn_unused_result__ -)); - + __wasi_size_t *retptr0 +) __attribute__((__warn_unused_result__)); /** * Shut down socket send and receive channels. * Note: This is similar to `shutdown` in POSIX. */ __wasi_errno_t __wasi_sock_shutdown( __wasi_fd_t fd, - /** * Which channels on the socket to shut down. */ __wasi_sdflags_t how -) __attribute__(( - __import_module__("wasi_snapshot_preview1"), - __import_name__("sock_shutdown"), - __warn_unused_result__ -)); - +) __attribute__((__warn_unused_result__)); /** @} */ #ifdef __cplusplus diff --git a/libc-bottom-half/headers/public/wasi/libc-environ.h b/libc-bottom-half/headers/public/wasi/libc-environ.h index b404add..f84ba8e 100644 --- a/libc-bottom-half/headers/public/wasi/libc-environ.h +++ b/libc-bottom-half/headers/public/wasi/libc-environ.h @@ -1,6 +1,10 @@ #ifndef __wasi_libc_environ_h #define __wasi_libc_environ_h +/// This header file is a WASI-libc-specific interface, and is not needed by +/// most programs. Most programs should just use the standard `getenv` and +/// related APIs, which take care of all of the details automatically. + #ifdef __cplusplus extern "C" { #endif @@ -12,6 +16,19 @@ void __wasilibc_initialize_environ(void); /// If `__wasilibc_initialize_environ` has not yet been called, call it. void __wasilibc_ensure_environ(void); +/// De-initialize the global environment variable state, so that subsequent +/// calls to `__wasilibc_ensure_environ` call `__wasilibc_initialize_environ`. +void __wasilibc_deinitialize_environ(void); + +/// Call `__wasilibc_initialize_environ` only if `environ` and `_environ` are +/// referenced in the program. +void __wasilibc_maybe_reinitialize_environ_eagerly(void); + +/// Return the value of the `environ` variable. Using `environ` directly +/// requires eager initialization of the environment variables. Using this +/// function instead of `environ` allows initialization to happen lazily. +char **__wasilibc_get_environ(void); + #ifdef __cplusplus } #endif diff --git a/libc-bottom-half/headers/public/wasi/libc-nocwd.h b/libc-bottom-half/headers/public/wasi/libc-nocwd.h new file mode 100644 index 0000000..a988503 --- /dev/null +++ b/libc-bottom-half/headers/public/wasi/libc-nocwd.h @@ -0,0 +1,58 @@ +#ifndef __wasi_libc_nocwd_h +#define __wasi_libc_nocwd_h + +/* + * In order to support AT_FDCWD, we need to wrap the *at functions to handle + * it by calling back into the non-at versions which perform libpreopen + * queries. These __wasilibc_nocwd_* forms are the underlying calls which + * assume AT_FDCWD has already been resolved. + */ + +#define __need_size_t +#include +#include <__typedef_ssize_t.h> +#include <__typedef_mode_t.h> +#include <__typedef_DIR.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct timespec; +struct stat; +struct dirent; + +int __wasilibc_nocwd___wasilibc_unlinkat(int, const char *) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd___wasilibc_rmdirat(int, const char *) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_linkat(int, const char *, int, const char *, int) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_symlinkat(const char *, int, const char *) + __attribute__((__warn_unused_result__)); +ssize_t __wasilibc_nocwd_readlinkat(int, const char *__restrict, char *__restrict, size_t) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_faccessat(int, const char *, int, int) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_renameat(int, const char *, int, const char *) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_openat_nomode(int, const char *, int) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_fstatat(int, const char *__restrict, struct stat *__restrict, int) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_mkdirat_nomode(int, const char *) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_utimensat(int, const char *, const struct timespec [2], int) + __attribute__((__warn_unused_result__)); +DIR *__wasilibc_nocwd_opendirat(int, const char *) + __attribute__((__warn_unused_result__)); +int __wasilibc_nocwd_scandirat(int, const char *, struct dirent ***, + int (*)(const struct dirent *), + int (*)(const struct dirent **, const struct dirent **)) + __attribute__((__warn_unused_result__)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc-bottom-half/headers/public/wasi/libc.h b/libc-bottom-half/headers/public/wasi/libc.h index 5997c47..b50518b 100644 --- a/libc-bottom-half/headers/public/wasi/libc.h +++ b/libc-bottom-half/headers/public/wasi/libc.h @@ -2,11 +2,15 @@ #define __wasi_libc_h #include <__typedef_off_t.h> +#include <__struct_timespec.h> #ifdef __cplusplus extern "C" { #endif +struct stat; +struct timespec; + /// Register the given pre-opened file descriptor under the given path. /// /// This function does not take ownership of `prefix` (it makes its own copy). @@ -14,13 +18,16 @@ int __wasilibc_register_preopened_fd(int fd, const char *prefix); /// Renumber `fd` to `newfd`; similar to `dup2` but does a move rather than a /// copy. -int __wasilibc_fd_renumber(int fd, int newfd); +int __wasilibc_fd_renumber(int fd, int newfd) + __attribute__((__warn_unused_result__)); /// Like `unlinkat`, but without depending on `__wasi_path_remove_directory`. -int __wasilibc_unlinkat(int fd, const char *path); +int __wasilibc_unlinkat(int fd, const char *path) + __attribute__((__warn_unused_result__)); /// An `*at` version of rmdir. -int __wasilibc_rmdirat(int fd, const char *path); +int __wasilibc_rmdirat(int fd, const char *path) + __attribute__((__warn_unused_result__)); /// Like `open`, but without the varargs in the signature. int __wasilibc_open_nomode(const char *path, int oflag); @@ -30,7 +37,26 @@ int __wasilibc_openat_nomode(int fd, const char *path, int oflag); /// Return the current file offset. Like `lseek(fd, 0, SEEK_CUR)`, but without /// depending on `lseek`. -off_t __wasilibc_tell(int fd); +off_t __wasilibc_tell(int fd) + __attribute__((__warn_unused_result__)); + +/* Non-`at` forms of various `*at` functions. */ +int __wasilibc_access(const char *pathname, int mode, int flags) + __attribute__((__warn_unused_result__)); +int __wasilibc_stat(const char *__restrict pathname, struct stat *__restrict statbuf, int flags) + __attribute__((__warn_unused_result__)); +int __wasilibc_utimens(const char *pathname, const struct timespec times[2], int flags) + __attribute__((__warn_unused_result__)); +int __wasilibc_link(const char *oldpath, const char *newpath, int flags) + __attribute__((__warn_unused_result__)); +int __wasilibc_link_oldat(int olddirfd, const char *oldpath, const char *newpath, int flags) + __attribute__((__warn_unused_result__)); +int __wasilibc_link_newat(const char *oldpath, int newdirfd, const char *newpath, int flags) + __attribute__((__warn_unused_result__)); +int __wasilibc_rename_oldat(int olddirfd, const char *oldpath, const char *newpath) + __attribute__((__warn_unused_result__)); +int __wasilibc_rename_newat(const char *oldpath, int newdirfd, const char *newpath) + __attribute__((__warn_unused_result__)); #ifdef __cplusplus } diff --git a/libc-bottom-half/sources/__wasilibc_environ.c b/libc-bottom-half/sources/__wasilibc_environ.c new file mode 100644 index 0000000..53d0a55 --- /dev/null +++ b/libc-bottom-half/sources/__wasilibc_environ.c @@ -0,0 +1,14 @@ +#include + +extern char **__wasilibc_environ; + +// See the comments in libc-environ.h. +char **__wasilibc_get_environ(void) { + // Perform lazy initialization if needed. + __wasilibc_ensure_environ(); + + // Return `environ`. Use the `__wasilibc_`-prefixed name so that we don't + // pull in the `environ` symbol directly, which would lead to eager + // initialization being done instead. + return __wasilibc_environ; +} diff --git a/libc-bottom-half/sources/__wasilibc_initialize_environ.c b/libc-bottom-half/sources/__wasilibc_initialize_environ.c index fe6001a..4ec4d30 100644 --- a/libc-bottom-half/sources/__wasilibc_initialize_environ.c +++ b/libc-bottom-half/sources/__wasilibc_initialize_environ.c @@ -75,3 +75,20 @@ oserr: software: _Exit(EX_SOFTWARE); } + +// See the comments in libc-environ.h. +void __wasilibc_deinitialize_environ(void) { + if (__wasilibc_environ != (char **)-1) { + // Let libc-top-half clear the old environment-variable strings. + clearenv(); + // Set the pointer to the special init value. + __wasilibc_environ = (char **)-1; + } +} + +// See the comments in libc-environ.h. +__attribute__((weak)) +void __wasilibc_maybe_reinitialize_environ_eagerly(void) { + // This version does nothing. It may be overridden by a version which does + // something if `environ` is used. +} diff --git a/libc-bottom-half/sources/__wasilibc_real.c b/libc-bottom-half/sources/__wasilibc_real.c new file mode 100644 index 0000000..e6481f7 --- /dev/null +++ b/libc-bottom-half/sources/__wasilibc_real.c @@ -0,0 +1,659 @@ +/** + * THIS FILE IS AUTO-GENERATED from the following files: + * wasi_snapshot_preview1.witx + * + * To regenerate this file execute: + * + * cargo run --manifest-path tools/wasi-headers/Cargo.toml generate-libc + * + * Modifications to this file will cause CI to fail, the code generator tool + * must be modified to change this file. + */ + +#include +#include + +int32_t __imported_wasi_snapshot_preview1_args_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("args_get") +)); + +__wasi_errno_t __wasi_args_get( + uint8_t * * argv, + uint8_t * argv_buf +){ + int32_t ret = __imported_wasi_snapshot_preview1_args_get((int32_t) argv, (int32_t) argv_buf); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_args_sizes_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("args_sizes_get") +)); + +__wasi_errno_t __wasi_args_sizes_get( + __wasi_size_t *retptr0, + __wasi_size_t *retptr1 +){ + int32_t ret = __imported_wasi_snapshot_preview1_args_sizes_get((int32_t) retptr0, (int32_t) retptr1); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_environ_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("environ_get") +)); + +__wasi_errno_t __wasi_environ_get( + uint8_t * * environ, + uint8_t * environ_buf +){ + int32_t ret = __imported_wasi_snapshot_preview1_environ_get((int32_t) environ, (int32_t) environ_buf); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_environ_sizes_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("environ_sizes_get") +)); + +__wasi_errno_t __wasi_environ_sizes_get( + __wasi_size_t *retptr0, + __wasi_size_t *retptr1 +){ + int32_t ret = __imported_wasi_snapshot_preview1_environ_sizes_get((int32_t) retptr0, (int32_t) retptr1); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_clock_res_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("clock_res_get") +)); + +__wasi_errno_t __wasi_clock_res_get( + __wasi_clockid_t id, + __wasi_timestamp_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_clock_res_get((int32_t) id, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_clock_time_get(int32_t arg0, int64_t arg1, int32_t arg2) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("clock_time_get") +)); + +__wasi_errno_t __wasi_clock_time_get( + __wasi_clockid_t id, + __wasi_timestamp_t precision, + __wasi_timestamp_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_clock_time_get((int32_t) id, (int64_t) precision, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_advise(int32_t arg0, int64_t arg1, int64_t arg2, int32_t arg3) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_advise") +)); + +__wasi_errno_t __wasi_fd_advise( + __wasi_fd_t fd, + __wasi_filesize_t offset, + __wasi_filesize_t len, + __wasi_advice_t advice +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_advise((int32_t) fd, (int64_t) offset, (int64_t) len, (int32_t) advice); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_allocate(int32_t arg0, int64_t arg1, int64_t arg2) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_allocate") +)); + +__wasi_errno_t __wasi_fd_allocate( + __wasi_fd_t fd, + __wasi_filesize_t offset, + __wasi_filesize_t len +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_allocate((int32_t) fd, (int64_t) offset, (int64_t) len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_close(int32_t arg0) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_close") +)); + +__wasi_errno_t __wasi_fd_close( + __wasi_fd_t fd +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_close((int32_t) fd); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_datasync(int32_t arg0) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_datasync") +)); + +__wasi_errno_t __wasi_fd_datasync( + __wasi_fd_t fd +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_datasync((int32_t) fd); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_fdstat_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_fdstat_get") +)); + +__wasi_errno_t __wasi_fd_fdstat_get( + __wasi_fd_t fd, + __wasi_fdstat_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_fdstat_get((int32_t) fd, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_fdstat_set_flags(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_fdstat_set_flags") +)); + +__wasi_errno_t __wasi_fd_fdstat_set_flags( + __wasi_fd_t fd, + __wasi_fdflags_t flags +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_fdstat_set_flags((int32_t) fd, flags); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_fdstat_set_rights(int32_t arg0, int64_t arg1, int64_t arg2) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_fdstat_set_rights") +)); + +__wasi_errno_t __wasi_fd_fdstat_set_rights( + __wasi_fd_t fd, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_fdstat_set_rights((int32_t) fd, fs_rights_base, fs_rights_inheriting); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_filestat_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_filestat_get") +)); + +__wasi_errno_t __wasi_fd_filestat_get( + __wasi_fd_t fd, + __wasi_filestat_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_filestat_get((int32_t) fd, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_filestat_set_size(int32_t arg0, int64_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_filestat_set_size") +)); + +__wasi_errno_t __wasi_fd_filestat_set_size( + __wasi_fd_t fd, + __wasi_filesize_t size +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_filestat_set_size((int32_t) fd, (int64_t) size); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_filestat_set_times(int32_t arg0, int64_t arg1, int64_t arg2, int32_t arg3) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_filestat_set_times") +)); + +__wasi_errno_t __wasi_fd_filestat_set_times( + __wasi_fd_t fd, + __wasi_timestamp_t atim, + __wasi_timestamp_t mtim, + __wasi_fstflags_t fst_flags +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_filestat_set_times((int32_t) fd, (int64_t) atim, (int64_t) mtim, fst_flags); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_pread(int32_t arg0, int32_t arg1, int32_t arg2, int64_t arg3, int32_t arg4) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_pread") +)); + +__wasi_errno_t __wasi_fd_pread( + __wasi_fd_t fd, + const __wasi_iovec_t *iovs, + size_t iovs_len, + __wasi_filesize_t offset, + __wasi_size_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_pread((int32_t) fd, (int32_t) iovs, (int32_t) iovs_len, (int64_t) offset, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_prestat_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_prestat_get") +)); + +__wasi_errno_t __wasi_fd_prestat_get( + __wasi_fd_t fd, + __wasi_prestat_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_prestat_get((int32_t) fd, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_prestat_dir_name(int32_t arg0, int32_t arg1, int32_t arg2) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_prestat_dir_name") +)); + +__wasi_errno_t __wasi_fd_prestat_dir_name( + __wasi_fd_t fd, + uint8_t * path, + __wasi_size_t path_len +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_prestat_dir_name((int32_t) fd, (int32_t) path, (int32_t) path_len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_pwrite(int32_t arg0, int32_t arg1, int32_t arg2, int64_t arg3, int32_t arg4) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_pwrite") +)); + +__wasi_errno_t __wasi_fd_pwrite( + __wasi_fd_t fd, + const __wasi_ciovec_t *iovs, + size_t iovs_len, + __wasi_filesize_t offset, + __wasi_size_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_pwrite((int32_t) fd, (int32_t) iovs, (int32_t) iovs_len, (int64_t) offset, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_read(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_read") +)); + +__wasi_errno_t __wasi_fd_read( + __wasi_fd_t fd, + const __wasi_iovec_t *iovs, + size_t iovs_len, + __wasi_size_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_read((int32_t) fd, (int32_t) iovs, (int32_t) iovs_len, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_readdir(int32_t arg0, int32_t arg1, int32_t arg2, int64_t arg3, int32_t arg4) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_readdir") +)); + +__wasi_errno_t __wasi_fd_readdir( + __wasi_fd_t fd, + uint8_t * buf, + __wasi_size_t buf_len, + __wasi_dircookie_t cookie, + __wasi_size_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_readdir((int32_t) fd, (int32_t) buf, (int32_t) buf_len, (int64_t) cookie, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_renumber(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_renumber") +)); + +__wasi_errno_t __wasi_fd_renumber( + __wasi_fd_t fd, + __wasi_fd_t to +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_renumber((int32_t) fd, (int32_t) to); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_seek(int32_t arg0, int64_t arg1, int32_t arg2, int32_t arg3) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_seek") +)); + +__wasi_errno_t __wasi_fd_seek( + __wasi_fd_t fd, + __wasi_filedelta_t offset, + __wasi_whence_t whence, + __wasi_filesize_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_seek((int32_t) fd, offset, (int32_t) whence, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_sync(int32_t arg0) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_sync") +)); + +__wasi_errno_t __wasi_fd_sync( + __wasi_fd_t fd +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_sync((int32_t) fd); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_tell(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_tell") +)); + +__wasi_errno_t __wasi_fd_tell( + __wasi_fd_t fd, + __wasi_filesize_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_tell((int32_t) fd, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_fd_write(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("fd_write") +)); + +__wasi_errno_t __wasi_fd_write( + __wasi_fd_t fd, + const __wasi_ciovec_t *iovs, + size_t iovs_len, + __wasi_size_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_fd_write((int32_t) fd, (int32_t) iovs, (int32_t) iovs_len, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_create_directory(int32_t arg0, int32_t arg1, int32_t arg2) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_create_directory") +)); + +__wasi_errno_t __wasi_path_create_directory( + __wasi_fd_t fd, + const char *path +){ + size_t path_len = strlen(path); + int32_t ret = __imported_wasi_snapshot_preview1_path_create_directory((int32_t) fd, (int32_t) path, (int32_t) path_len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_filestat_get(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_filestat_get") +)); + +__wasi_errno_t __wasi_path_filestat_get( + __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, + __wasi_filestat_t *retptr0 +){ + size_t path_len = strlen(path); + int32_t ret = __imported_wasi_snapshot_preview1_path_filestat_get((int32_t) fd, flags, (int32_t) path, (int32_t) path_len, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_filestat_set_times(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int64_t arg4, int64_t arg5, int32_t arg6) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_filestat_set_times") +)); + +__wasi_errno_t __wasi_path_filestat_set_times( + __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, + __wasi_timestamp_t atim, + __wasi_timestamp_t mtim, + __wasi_fstflags_t fst_flags +){ + size_t path_len = strlen(path); + int32_t ret = __imported_wasi_snapshot_preview1_path_filestat_set_times((int32_t) fd, flags, (int32_t) path, (int32_t) path_len, (int64_t) atim, (int64_t) mtim, fst_flags); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_link(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_link") +)); + +__wasi_errno_t __wasi_path_link( + __wasi_fd_t old_fd, + __wasi_lookupflags_t old_flags, + const char *old_path, + __wasi_fd_t new_fd, + const char *new_path +){ + size_t old_path_len = strlen(old_path); + size_t new_path_len = strlen(new_path); + int32_t ret = __imported_wasi_snapshot_preview1_path_link((int32_t) old_fd, old_flags, (int32_t) old_path, (int32_t) old_path_len, (int32_t) new_fd, (int32_t) new_path, (int32_t) new_path_len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_open(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int64_t arg5, int64_t arg6, int32_t arg7, int32_t arg8) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_open") +)); + +__wasi_errno_t __wasi_path_open( + __wasi_fd_t fd, + __wasi_lookupflags_t dirflags, + const char *path, + __wasi_oflags_t oflags, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting, + __wasi_fdflags_t fdflags, + __wasi_fd_t *retptr0 +){ + size_t path_len = strlen(path); + int32_t ret = __imported_wasi_snapshot_preview1_path_open((int32_t) fd, dirflags, (int32_t) path, (int32_t) path_len, oflags, fs_rights_base, fs_rights_inheriting, fdflags, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_readlink(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_readlink") +)); + +__wasi_errno_t __wasi_path_readlink( + __wasi_fd_t fd, + const char *path, + uint8_t * buf, + __wasi_size_t buf_len, + __wasi_size_t *retptr0 +){ + size_t path_len = strlen(path); + int32_t ret = __imported_wasi_snapshot_preview1_path_readlink((int32_t) fd, (int32_t) path, (int32_t) path_len, (int32_t) buf, (int32_t) buf_len, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_remove_directory(int32_t arg0, int32_t arg1, int32_t arg2) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_remove_directory") +)); + +__wasi_errno_t __wasi_path_remove_directory( + __wasi_fd_t fd, + const char *path +){ + size_t path_len = strlen(path); + int32_t ret = __imported_wasi_snapshot_preview1_path_remove_directory((int32_t) fd, (int32_t) path, (int32_t) path_len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_rename(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_rename") +)); + +__wasi_errno_t __wasi_path_rename( + __wasi_fd_t fd, + const char *old_path, + __wasi_fd_t new_fd, + const char *new_path +){ + size_t old_path_len = strlen(old_path); + size_t new_path_len = strlen(new_path); + int32_t ret = __imported_wasi_snapshot_preview1_path_rename((int32_t) fd, (int32_t) old_path, (int32_t) old_path_len, (int32_t) new_fd, (int32_t) new_path, (int32_t) new_path_len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_symlink(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_symlink") +)); + +__wasi_errno_t __wasi_path_symlink( + const char *old_path, + __wasi_fd_t fd, + const char *new_path +){ + size_t old_path_len = strlen(old_path); + size_t new_path_len = strlen(new_path); + int32_t ret = __imported_wasi_snapshot_preview1_path_symlink((int32_t) old_path, (int32_t) old_path_len, (int32_t) fd, (int32_t) new_path, (int32_t) new_path_len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_path_unlink_file(int32_t arg0, int32_t arg1, int32_t arg2) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("path_unlink_file") +)); + +__wasi_errno_t __wasi_path_unlink_file( + __wasi_fd_t fd, + const char *path +){ + size_t path_len = strlen(path); + int32_t ret = __imported_wasi_snapshot_preview1_path_unlink_file((int32_t) fd, (int32_t) path, (int32_t) path_len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_poll_oneoff(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("poll_oneoff") +)); + +__wasi_errno_t __wasi_poll_oneoff( + const __wasi_subscription_t * in, + __wasi_event_t * out, + __wasi_size_t nsubscriptions, + __wasi_size_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_poll_oneoff((int32_t) in, (int32_t) out, (int32_t) nsubscriptions, (int32_t) retptr0); + return (uint16_t) ret; +} + +_Noreturn void __imported_wasi_snapshot_preview1_proc_exit(int32_t arg0) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("proc_exit") +)); + +_Noreturn void __wasi_proc_exit( + __wasi_exitcode_t rval +){ + __imported_wasi_snapshot_preview1_proc_exit((int32_t) rval); +} + +int32_t __imported_wasi_snapshot_preview1_proc_raise(int32_t arg0) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("proc_raise") +)); + +__wasi_errno_t __wasi_proc_raise( + __wasi_signal_t sig +){ + int32_t ret = __imported_wasi_snapshot_preview1_proc_raise((int32_t) sig); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_sched_yield() __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("sched_yield") +)); + +__wasi_errno_t __wasi_sched_yield( + void +){ + int32_t ret = __imported_wasi_snapshot_preview1_sched_yield(); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_random_get(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("random_get") +)); + +__wasi_errno_t __wasi_random_get( + uint8_t * buf, + __wasi_size_t buf_len +){ + int32_t ret = __imported_wasi_snapshot_preview1_random_get((int32_t) buf, (int32_t) buf_len); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_sock_recv(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("sock_recv") +)); + +__wasi_errno_t __wasi_sock_recv( + __wasi_fd_t fd, + const __wasi_iovec_t *ri_data, + size_t ri_data_len, + __wasi_riflags_t ri_flags, + __wasi_size_t *retptr0, + __wasi_roflags_t *retptr1 +){ + int32_t ret = __imported_wasi_snapshot_preview1_sock_recv((int32_t) fd, (int32_t) ri_data, (int32_t) ri_data_len, ri_flags, (int32_t) retptr0, (int32_t) retptr1); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_sock_send(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("sock_send") +)); + +__wasi_errno_t __wasi_sock_send( + __wasi_fd_t fd, + const __wasi_ciovec_t *si_data, + size_t si_data_len, + __wasi_siflags_t si_flags, + __wasi_size_t *retptr0 +){ + int32_t ret = __imported_wasi_snapshot_preview1_sock_send((int32_t) fd, (int32_t) si_data, (int32_t) si_data_len, (int32_t) si_flags, (int32_t) retptr0); + return (uint16_t) ret; +} + +int32_t __imported_wasi_snapshot_preview1_sock_shutdown(int32_t arg0, int32_t arg1) __attribute__(( + __import_module__("wasi_snapshot_preview1"), + __import_name__("sock_shutdown") +)); + +__wasi_errno_t __wasi_sock_shutdown( + __wasi_fd_t fd, + __wasi_sdflags_t how +){ + int32_t ret = __imported_wasi_snapshot_preview1_sock_shutdown((int32_t) fd, how); + return (uint16_t) ret; +} + diff --git a/libc-bottom-half/sources/__wasilibc_rmdirat.c b/libc-bottom-half/sources/__wasilibc_rmdirat.c index acb9528..2730c23 100644 --- a/libc-bottom-half/sources/__wasilibc_rmdirat.c +++ b/libc-bottom-half/sources/__wasilibc_rmdirat.c @@ -2,11 +2,9 @@ #include #include #include -#include -int __wasilibc_rmdirat(int fd, const char *path) { - size_t path_len = strlen(path); - __wasi_errno_t error = __wasi_path_remove_directory(fd, path, path_len); +int __wasilibc_nocwd___wasilibc_rmdirat(int fd, const char *path) { + __wasi_errno_t error = __wasi_path_remove_directory(fd, path); if (error != 0) { errno = errno_fixup_directory(fd, error); return -1; diff --git a/libc-bottom-half/sources/__wasilibc_unlinkat.c b/libc-bottom-half/sources/__wasilibc_unlinkat.c index a266348..21ae69a 100644 --- a/libc-bottom-half/sources/__wasilibc_unlinkat.c +++ b/libc-bottom-half/sources/__wasilibc_unlinkat.c @@ -2,11 +2,9 @@ #include #include #include -#include -int __wasilibc_unlinkat(int fd, const char *path) { - size_t path_len = strlen(path); - __wasi_errno_t error = __wasi_path_unlink_file(fd, path, path_len); +int __wasilibc_nocwd___wasilibc_unlinkat(int fd, const char *path) { + __wasi_errno_t error = __wasi_path_unlink_file(fd, path); if (error != 0) { errno = error; return -1; diff --git a/libc-bottom-half/sources/at_fdcwd.c b/libc-bottom-half/sources/at_fdcwd.c new file mode 100644 index 0000000..c83797d --- /dev/null +++ b/libc-bottom-half/sources/at_fdcwd.c @@ -0,0 +1,141 @@ +// Handle AT_FDCWD and absolute paths for the *at functions. +// +// In the case of an AT_FDCWD file descriptor or an absolute path, call the +// corresponding non-`at` function. This will send it through the libpreopen +// wrappers to convert the path into a directory file descriptor and relative +// path before translating it into the corresponding `__wasilibc_nocwd_*at` +// function, which then calls the appropriate WASI function. + +#include +#include +#include +#include +#include +#include +#include +#include + +// If the platform doesn't define O_TMPFILE, we don't need to worry about it. +#ifndef O_TMPFILE +#define O_TMPFILE 0 +#endif + +int openat(int dirfd, const char *pathname, int flags, ...) { + if (dirfd == AT_FDCWD || pathname[0] == '/') { + return open(pathname, flags); + } + + return __wasilibc_nocwd_openat_nomode(dirfd, pathname, flags); +} + +int symlinkat(const char *target, int dirfd, const char *linkpath) { + if (dirfd == AT_FDCWD || linkpath[0] == '/') { + return symlink(target, linkpath); + } + + return __wasilibc_nocwd_symlinkat(target, dirfd, linkpath); +} + +ssize_t readlinkat(int dirfd, const char *__restrict pathname, char *__restrict buf, size_t bufsiz) { + if (dirfd == AT_FDCWD || pathname[0] == '/') { + return readlink(pathname, buf, bufsiz); + } + + return __wasilibc_nocwd_readlinkat(dirfd, pathname, buf, bufsiz); +} + +int mkdirat(int dirfd, const char *pathname, mode_t mode) { + if (dirfd == AT_FDCWD || pathname[0] == '/') { + return mkdir(pathname, mode); + } + + return __wasilibc_nocwd_mkdirat_nomode(dirfd, pathname); +} + +DIR *opendirat(int dirfd, const char *path) { + if (dirfd == AT_FDCWD || path[0] == '/') { + return opendir(path); + } + + return __wasilibc_nocwd_opendirat(dirfd, path); +} + +int scandirat(int dirfd, const char *dirp, struct dirent ***namelist, + int (*filter)(const struct dirent *), + int (*compar)(const struct dirent **, const struct dirent **)) { + if (dirfd == AT_FDCWD || dirp[0] == '/') { + return scandir(dirp, namelist, filter, compar); + } + + return __wasilibc_nocwd_scandirat(dirfd, dirp, namelist, filter, compar); +} + +int faccessat(int dirfd, const char *pathname, int mode, int flags) { + if (dirfd == AT_FDCWD || pathname[0] == '/') { + return __wasilibc_access(pathname, mode, flags); + } + + return __wasilibc_nocwd_faccessat(dirfd, pathname, mode, flags); +} + +int fstatat(int dirfd, const char *__restrict pathname, struct stat *__restrict statbuf, int flags) { + if (dirfd == AT_FDCWD || pathname[0] == '/') { + return __wasilibc_stat(pathname, statbuf, flags); + } + + return __wasilibc_nocwd_fstatat(dirfd, pathname, statbuf, flags); +} + +int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) { + if (dirfd == AT_FDCWD || pathname[0] == '/') { + return __wasilibc_utimens(pathname, times, flags); + } + + return __wasilibc_nocwd_utimensat(dirfd, pathname, times, flags); +} + +int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) { + if ((olddirfd == AT_FDCWD || oldpath[0] == '/') && + (newdirfd == AT_FDCWD || newpath[0] == '/')) { + return __wasilibc_link(oldpath, newpath, flags); + } + if (olddirfd == AT_FDCWD || oldpath[0] == '/') { + return __wasilibc_link_newat(oldpath, newdirfd, newpath, flags); + } + if (newdirfd == AT_FDCWD || newpath[0] == '/') { + return __wasilibc_link_oldat(olddirfd, oldpath, newpath, flags); + } + + return __wasilibc_nocwd_linkat(olddirfd, oldpath, newdirfd, newpath, flags); +} + +int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { + if ((olddirfd == AT_FDCWD || oldpath[0] == '/') && + (newdirfd == AT_FDCWD || newpath[0] == '/')) { + return rename(oldpath, newpath); + } + if (olddirfd == AT_FDCWD || oldpath[0] == '/') { + return __wasilibc_rename_newat(oldpath, newdirfd, newpath); + } + if (newdirfd == AT_FDCWD || newpath[0] == '/') { + return __wasilibc_rename_oldat(olddirfd, oldpath, newpath); + } + + return __wasilibc_nocwd_renameat(olddirfd, oldpath, newdirfd, newpath); +} + +int __wasilibc_unlinkat(int dirfd, const char *path) { + if (dirfd == AT_FDCWD || path[0] == '/') { + return unlink(path); + } + + return __wasilibc_nocwd___wasilibc_unlinkat(dirfd, path); +} + +int __wasilibc_rmdirat(int dirfd, const char *path) { + if (dirfd == AT_FDCWD || path[0] == '/') { + return rmdir(path); + } + + return __wasilibc_nocwd___wasilibc_rmdirat(dirfd, path); +} diff --git a/libc-bottom-half/sources/complex-builtins.c b/libc-bottom-half/sources/complex-builtins.c index b6588f7..971d57e 100644 --- a/libc-bottom-half/sources/complex-builtins.c +++ b/libc-bottom-half/sources/complex-builtins.c @@ -4,18 +4,26 @@ #include -float crealf(float _Complex x) { - return __real__ x; +float (crealf)(float _Complex x) { + return __builtin_crealf(x); } -double creal(double _Complex x) { - return __real__ x; +double (creal)(double _Complex x) { + return __builtin_creal(x); } -float cimagf(float _Complex x) { - return __imag__ x; +long double (creall)(long double _Complex x) { + return __builtin_creall(x); } -double cimag(double _Complex x) { - return __imag__ x; +float (cimagf)(float _Complex x) { + return __builtin_cimagf(x); +} + +double (cimag)(double _Complex x) { + return __builtin_cimag(x); +} + +long double (cimagl)(long double _Complex x) { + return __builtin_cimagl(x); } diff --git a/libc-bottom-half/sources/environ.c b/libc-bottom-half/sources/environ.c index bc5a078..94d82ee 100644 --- a/libc-bottom-half/sources/environ.c +++ b/libc-bottom-half/sources/environ.c @@ -24,3 +24,10 @@ __attribute__((constructor(50))) static void __wasilibc_initialize_environ_eagerly(void) { __wasilibc_initialize_environ(); } + +// See the comments in libc-environ.h. +void __wasilibc_maybe_reinitialize_environ_eagerly(void) { + // This translation unit is linked in if `environ` is used, meaning we need + // to eagerly reinitialize the environment variables. + __wasilibc_initialize_environ(); +} diff --git a/libc-bottom-half/sources/getcwd.c b/libc-bottom-half/sources/getcwd.c index 6a2080e..6fea2a2 100644 --- a/libc-bottom-half/sources/getcwd.c +++ b/libc-bottom-half/sources/getcwd.c @@ -19,7 +19,7 @@ char *getcwd(char *buf, size_t size) } } else { size_t len = strlen(__wasilibc_cwd); - if (size < strlen(__wasilibc_cwd) + 1) { + if (size < len + 1) { errno = ERANGE; return NULL; } diff --git a/libc-bottom-half/sources/posix.c b/libc-bottom-half/sources/posix.c index 388a57d..153280f 100644 --- a/libc-bottom-half/sources/posix.c +++ b/libc-bottom-half/sources/posix.c @@ -10,6 +10,7 @@ #include #include #include +#include static int find_relpath2( const char *path, @@ -59,7 +60,7 @@ int __wasilibc_open_nomode(const char *path, int oflag) { return -1; } - return __wasilibc_openat_nomode(dirfd, relative_path, oflag); + return __wasilibc_nocwd_openat_nomode(dirfd, relative_path, oflag); } int access(const char *path, int amode) { @@ -72,7 +73,7 @@ int access(const char *path, int amode) { return -1; } - return faccessat(dirfd, relative_path, amode, 0); + return __wasilibc_nocwd_faccessat(dirfd, relative_path, amode, 0); } ssize_t readlink( @@ -89,7 +90,7 @@ ssize_t readlink( return -1; } - return readlinkat(dirfd, relative_path, buf, bufsize); + return __wasilibc_nocwd_readlinkat(dirfd, relative_path, buf, bufsize); } int stat(const char *restrict path, struct stat *restrict buf) { @@ -102,7 +103,7 @@ int stat(const char *restrict path, struct stat *restrict buf) { return -1; } - return fstatat(dirfd, relative_path, buf, 0); + return __wasilibc_nocwd_fstatat(dirfd, relative_path, buf, 0); } int lstat(const char *restrict path, struct stat *restrict buf) { @@ -115,7 +116,7 @@ int lstat(const char *restrict path, struct stat *restrict buf) { return -1; } - return fstatat(dirfd, relative_path, buf, AT_SYMLINK_NOFOLLOW); + return __wasilibc_nocwd_fstatat(dirfd, relative_path, buf, AT_SYMLINK_NOFOLLOW); } int utime(const char *path, const struct utimbuf *times) { @@ -128,7 +129,8 @@ int utime(const char *path, const struct utimbuf *times) { return -1; } - return utimensat(dirfd, relative_path, + return __wasilibc_nocwd_utimensat( + dirfd, relative_path, times ? ((struct timespec [2]) { { .tv_sec = times->actime }, { .tv_sec = times->modtime } @@ -150,7 +152,7 @@ int unlink(const char *path) { // `unlinkat` imports `__wasi_path_remove_directory` even when // `AT_REMOVEDIR` isn't passed. Instead, use a specialized function which // just imports `__wasi_path_unlink_file`. - return __wasilibc_unlinkat(dirfd, relative_path); + return __wasilibc_nocwd___wasilibc_unlinkat(dirfd, relative_path); } int rmdir(const char *path) { @@ -163,7 +165,7 @@ int rmdir(const char *path) { return -1; } - return __wasilibc_rmdirat(dirfd, relative_path); + return __wasilibc_nocwd___wasilibc_rmdirat(dirfd, relative_path); } int remove(const char *path) { @@ -177,10 +179,10 @@ int remove(const char *path) { } // First try to remove it as a file. - int r = __wasilibc_unlinkat(dirfd, relative_path); + int r = __wasilibc_nocwd___wasilibc_unlinkat(dirfd, relative_path); if (r != 0 && (errno == EISDIR || errno == ENOTCAPABLE)) { // That failed, but it might be a directory. - r = __wasilibc_rmdirat(dirfd, relative_path); + r = __wasilibc_nocwd___wasilibc_rmdirat(dirfd, relative_path); // If it isn't a directory, we lack capabilities to remove it as a file. if (errno == ENOTDIR) @@ -199,7 +201,7 @@ int mkdir(const char *path, mode_t mode) { return -1; } - return mkdirat(dirfd, relative_path, mode); + return __wasilibc_nocwd_mkdirat_nomode(dirfd, relative_path); } DIR *opendir(const char *dirname) { @@ -212,7 +214,7 @@ DIR *opendir(const char *dirname) { return NULL; } - return opendirat(dirfd, relative_path); + return __wasilibc_nocwd_opendirat(dirfd, relative_path); } int scandir( @@ -230,7 +232,7 @@ int scandir( return -1; } - return scandirat(dirfd, relative_path, namelist, filter, compar); + return __wasilibc_nocwd_scandirat(dirfd, relative_path, namelist, filter, compar); } int symlink(const char *target, const char *linkpath) { @@ -243,7 +245,7 @@ int symlink(const char *target, const char *linkpath) { return -1; } - return symlinkat(target, dirfd, relative_path); + return __wasilibc_nocwd_symlinkat(target, dirfd, relative_path); } int link(const char *old, const char *new) { @@ -255,8 +257,8 @@ int link(const char *old, const char *new) { int new_dirfd = find_relpath(new, &new_relative_path); if (new_dirfd != -1) - return linkat(old_dirfd, old_relative_path, - new_dirfd, new_relative_path, 0); + return __wasilibc_nocwd_linkat(old_dirfd, old_relative_path, + new_dirfd, new_relative_path, 0); } // We couldn't find a preopen for it; indicate that we lack capabilities. @@ -273,11 +275,149 @@ int rename(const char *old, const char *new) { int new_dirfd = find_relpath(new, &new_relative_path); if (new_dirfd != -1) - return renameat(old_dirfd, old_relative_path, - new_dirfd, new_relative_path); + return __wasilibc_nocwd_renameat(old_dirfd, old_relative_path, + new_dirfd, new_relative_path); } // We couldn't find a preopen for it; indicate that we lack capabilities. errno = ENOTCAPABLE; return -1; } + +// Like `access`, but with `faccessat`'s flags argument. +int +__wasilibc_access(const char *path, int mode, int flags) +{ + char *relative_path; + int dirfd = find_relpath(path, &relative_path); + + // If we can't find a preopen for it, indicate that we lack capabilities. + if (dirfd == -1) { + errno = ENOTCAPABLE; + return -1; + } + + return __wasilibc_nocwd_faccessat(dirfd, relative_path, + mode, flags); +} + +// Like `utimensat`, but without the `at` part. +int +__wasilibc_utimens(const char *path, const struct timespec times[2], int flags) +{ + char *relative_path; + int dirfd = find_relpath(path, &relative_path); + + // If we can't find a preopen for it, indicate that we lack capabilities. + if (dirfd == -1) { + errno = ENOTCAPABLE; + return -1; + } + + return __wasilibc_nocwd_utimensat(dirfd, relative_path, + times, flags); +} + +// Like `stat`, but with `fstatat`'s flags argument. +int +__wasilibc_stat(const char *__restrict path, struct stat *__restrict st, int flags) +{ + char *relative_path; + int dirfd = find_relpath(path, &relative_path); + + // If we can't find a preopen for it, indicate that we lack capabilities. + if (dirfd == -1) { + errno = ENOTCAPABLE; + return -1; + } + + return __wasilibc_nocwd_fstatat(dirfd, relative_path, st, flags); +} + +// Like `link`, but with `linkat`'s flags argument. +int +__wasilibc_link(const char *oldpath, const char *newpath, int flags) +{ + char *old_relative_path; + char *new_relative_path; + int old_dirfd = find_relpath(oldpath, &old_relative_path); + int new_dirfd = find_relpath(newpath, &new_relative_path); + + // If we can't find a preopen for it, indicate that we lack capabilities. + if (old_dirfd == -1 || new_dirfd == -1) { + errno = ENOTCAPABLE; + return -1; + } + + return __wasilibc_nocwd_linkat(old_dirfd, old_relative_path, + new_dirfd, new_relative_path, + flags); +} + +// Like `__wasilibc_link`, but oldpath is relative to olddirfd. +int +__wasilibc_link_oldat(int olddirfd, const char *oldpath, const char *newpath, int flags) +{ + char *new_relative_path; + int new_dirfd = find_relpath(newpath, &new_relative_path); + + // If we can't find a preopen for it, indicate that we lack capabilities. + if (new_dirfd == -1) { + errno = ENOTCAPABLE; + return -1; + } + + return __wasilibc_nocwd_linkat(olddirfd, oldpath, + new_dirfd, new_relative_path, + flags); +} + +// Like `__wasilibc_link`, but newpath is relative to newdirfd. +int +__wasilibc_link_newat(const char *oldpath, int newdirfd, const char *newpath, int flags) +{ + char *old_relative_path; + int old_dirfd = find_relpath(oldpath, &old_relative_path); + + // If we can't find a preopen for it, indicate that we lack capabilities. + if (old_dirfd == -1) { + errno = ENOTCAPABLE; + return -1; + } + + return __wasilibc_nocwd_linkat(old_dirfd, old_relative_path, + newdirfd, newpath, + flags); +} + +// Like `rename`, but from is relative to fromdirfd. +int +__wasilibc_rename_oldat(int fromdirfd, const char *from, const char *to) +{ + char *to_relative_path; + int to_dirfd = find_relpath(to, &to_relative_path); + + // If we can't find a preopen for it, indicate that we lack capabilities. + if (to_dirfd == -1) { + errno = ENOTCAPABLE; + return -1; + } + + return __wasilibc_nocwd_renameat(fromdirfd, from, to_dirfd, to_relative_path); +} + +// Like `rename`, but to is relative to todirfd. +int +__wasilibc_rename_newat(const char *from, int todirfd, const char *to) +{ + char *from_relative_path; + int from_dirfd = find_relpath(from, &from_relative_path); + + // If we can't find a preopen for it, indicate that we lack capabilities. + if (from_dirfd == -1) { + errno = ENOTCAPABLE; + return -1; + } + + return __wasilibc_nocwd_renameat(from_dirfd, from_relative_path, todirfd, to); +} diff --git a/libc-bottom-half/sources/preopens.c b/libc-bottom-half/sources/preopens.c index 8c68826..b6fb9f7 100644 --- a/libc-bottom-half/sources/preopens.c +++ b/libc-bottom-half/sources/preopens.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -96,7 +97,11 @@ static const char *strip_prefixes(const char *path) { /// /// This function takes ownership of `prefix`. static int internal_register_preopened_fd(__wasi_fd_t fd, const char *relprefix) { + // Check preconditions. assert_invariants(); + assert(fd != AT_FDCWD); + assert(fd != -1); + assert(relprefix != NULL); if (num_preopens == preopen_capacity && resize() != 0) return -1; diff --git a/libc-top-half/musl/INSTALL b/libc-top-half/musl/INSTALL index 22477b6..c583691 100644 --- a/libc-top-half/musl/INSTALL +++ b/libc-top-half/musl/INSTALL @@ -86,7 +86,7 @@ and ABI combinations: * SuperH (SH) * Standard ELF ABI or FDPIC ABI (shared-text without MMU) - * Little-endian by default; big-engian variant also supported + * Little-endian by default; big-endian variant also supported * Full FPU ABI or soft-float ABI is supported, but the single-precision-only FPU ABI is not diff --git a/libc-top-half/musl/VERSION b/libc-top-half/musl/VERSION index 6085e94..23aa839 100644 --- a/libc-top-half/musl/VERSION +++ b/libc-top-half/musl/VERSION @@ -1 +1 @@ -1.2.1 +1.2.2 diff --git a/libc-top-half/musl/WHATSNEW b/libc-top-half/musl/WHATSNEW index d9826fc..e1d0198 100644 --- a/libc-top-half/musl/WHATSNEW +++ b/libc-top-half/musl/WHATSNEW @@ -2236,3 +2236,54 @@ arch-specific bugs fixed: - mips* had negated error codes for some syscalls (kernel bug) - mips* SIGEMT was wrongly called SIGSTKFLT - sh fesetround didn't work correctly on sh + + + +1.2.2 release notes + +major changes: +- child restrictions lifted after fork of multithreaded parent + +new features: +- _Fork function (POSIX-future) +- reallocarray function (extension from OpenBSD, now widespread) +- gettid function (kernel tid as supported concept) +- SIGEV_THREAD_ID sigevent API (Linux extension) +- tcgetwinsize and tcsetwinsize functions (POSIX-future) + +performance: +- faster software sqrt on archs without native sqrt instruction + +compatibility: +- realpath no longer depends on procfs availability & accuracy +- time zone parser now always prefers 64-bit tables if present +- crypt_blowfish now supports $2b$ prefix +- res_query now reports errors via h_errno +- set*id and setrlimit are now safe in vforked/cloned child +- setgroups now applies to all threads +- dlopen debugger notification is improved, should work with lldb +- setrlimit no longer needs __synccall broadcast on linux 2.6.36+ +- faccessat with AT_EACCESS no longer needs child process on linux 5.8+ + +bugs fixed: +- buffer overflow and infinite loop errors in wcsnrtombs (CVE-2020-28928) +- sem_close unmapped still-referenced semaphores +- fork of process with active aio could deadlock or crash paren +- pthread_cond_wait was broken with priority-inheritance mutex +- getgrouplist wrongly failed when nscd reported an empty list +- abort could leak modified SIGABRT disposition to fork or posix_spawn child +- regression with mallocng: malloc_usable_size(0) crashed +- readlink wrongly gave EINVAL on zero length dest buffer +- sqrtl was severely inaccurate (not correctly rounded) on ldquad archs +- assert failure wrongly flushed stdio (possible deadlock) +- MUSL_LOCPATH search was broken with multiple components +- missing newline in herror output +- possible deadlock in pthread_exit with pshared mutex or barrier usage +- pthread_mutexattr_getprotocol didn't read back protocol +- v4l2 ioctl translation for pre-time64 kernels didn't work + +arch-specific bugs fixed: +- x86_64 longjmp failed to handle 0 argument reliably +- i386 __set_thread_area fallback for pre-2.6 kernels didn't work +- missing O_LARGEFILE macro value on x86_64, x32, mips64 +- unpredictable s390x breakage from failure to preserve call-saved registers diff --git a/libc-top-half/musl/arch/aarch64/bits/hwcap.h b/libc-top-half/musl/arch/aarch64/bits/hwcap.h index a748402..7ab73f9 100644 --- a/libc-top-half/musl/arch/aarch64/bits/hwcap.h +++ b/libc-top-half/musl/arch/aarch64/bits/hwcap.h @@ -38,3 +38,13 @@ #define HWCAP2_SVEBITPERM (1 << 4) #define HWCAP2_SVESHA3 (1 << 5) #define HWCAP2_SVESM4 (1 << 6) +#define HWCAP2_FLAGM2 (1 << 7) +#define HWCAP2_FRINT (1 << 8) +#define HWCAP2_SVEI8MM (1 << 9) +#define HWCAP2_SVEF32MM (1 << 10) +#define HWCAP2_SVEF64MM (1 << 11) +#define HWCAP2_SVEBF16 (1 << 12) +#define HWCAP2_I8MM (1 << 13) +#define HWCAP2_BF16 (1 << 14) +#define HWCAP2_DGH (1 << 15) +#define HWCAP2_RNG (1 << 16) diff --git a/libc-top-half/musl/arch/aarch64/bits/signal.h b/libc-top-half/musl/arch/aarch64/bits/signal.h index b71261f..5098c73 100644 --- a/libc-top-half/musl/arch/aarch64/bits/signal.h +++ b/libc-top-half/musl/arch/aarch64/bits/signal.h @@ -11,7 +11,7 @@ typedef unsigned long greg_t; typedef unsigned long gregset_t[34]; typedef struct { - long double vregs[32]; + __uint128_t vregs[32]; unsigned int fpsr; unsigned int fpcr; } fpregset_t; @@ -34,7 +34,7 @@ struct fpsimd_context { struct _aarch64_ctx head; unsigned int fpsr; unsigned int fpcr; - long double vregs[32]; + __uint128_t vregs[32]; }; struct esr_context { struct _aarch64_ctx head; diff --git a/libc-top-half/musl/arch/aarch64/bits/syscall.h.in b/libc-top-half/musl/arch/aarch64/bits/syscall.h.in index 93648af..f9457c1 100644 --- a/libc-top-half/musl/arch/aarch64/bits/syscall.h.in +++ b/libc-top-half/musl/arch/aarch64/bits/syscall.h.in @@ -289,4 +289,8 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/aarch64/bits/user.h b/libc-top-half/musl/arch/aarch64/bits/user.h index d12cdf7..8a1002a 100644 --- a/libc-top-half/musl/arch/aarch64/bits/user.h +++ b/libc-top-half/musl/arch/aarch64/bits/user.h @@ -6,7 +6,7 @@ struct user_regs_struct { }; struct user_fpsimd_struct { - long double vregs[32]; + __uint128_t vregs[32]; unsigned int fpsr; unsigned int fpcr; }; diff --git a/libc-top-half/musl/arch/aarch64/pthread_arch.h b/libc-top-half/musl/arch/aarch64/pthread_arch.h index e64b126..3909616 100644 --- a/libc-top-half/musl/arch/aarch64/pthread_arch.h +++ b/libc-top-half/musl/arch/aarch64/pthread_arch.h @@ -1,12 +1,11 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - char *self; - __asm__ ("mrs %0,tpidr_el0" : "=r"(self)); - return (void*)(self - sizeof(struct pthread)); + uintptr_t tp; + __asm__ ("mrs %0,tpidr_el0" : "=r"(tp)); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 16 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread)) #define MC_PC pc diff --git a/libc-top-half/musl/arch/arm/bits/syscall.h.in b/libc-top-half/musl/arch/arm/bits/syscall.h.in index 11d6776..7e2fc26 100644 --- a/libc-top-half/musl/arch/arm/bits/syscall.h.in +++ b/libc-top-half/musl/arch/arm/bits/syscall.h.in @@ -389,6 +389,10 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 diff --git a/libc-top-half/musl/arch/arm/pthread_arch.h b/libc-top-half/musl/arch/arm/pthread_arch.h index e689ea2..157e2ea 100644 --- a/libc-top-half/musl/arch/arm/pthread_arch.h +++ b/libc-top-half/musl/arch/arm/pthread_arch.h @@ -1,11 +1,11 @@ #if ((__ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7 -static inline pthread_t __pthread_self() +static inline uintptr_t __get_tp() { - char *p; - __asm__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(p) ); - return (void *)(p-sizeof(struct pthread)); + uintptr_t tp; + __asm__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(tp) ); + return tp; } #else @@ -16,18 +16,17 @@ static inline pthread_t __pthread_self() #define BLX "blx" #endif -static inline pthread_t __pthread_self() +static inline uintptr_t __get_tp() { extern hidden uintptr_t __a_gettp_ptr; - register uintptr_t p __asm__("r0"); - __asm__ ( BLX " %1" : "=r"(p) : "r"(__a_gettp_ptr) : "cc", "lr" ); - return (void *)(p-sizeof(struct pthread)); + register uintptr_t tp __asm__("r0"); + __asm__ ( BLX " %1" : "=r"(tp) : "r"(__a_gettp_ptr) : "cc", "lr" ); + return tp; } #endif #define TLS_ABOVE_TP #define GAP_ABOVE_TP 8 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread)) #define MC_PC arm_pc diff --git a/libc-top-half/musl/arch/generic/bits/fcntl.h b/libc-top-half/musl/arch/generic/bits/fcntl.h index ae233cc..730a98c 100644 --- a/libc-top-half/musl/arch/generic/bits/fcntl.h +++ b/libc-top-half/musl/arch/generic/bits/fcntl.h @@ -30,9 +30,15 @@ #define F_SETSIG 10 #define F_GETSIG 11 +#if __LONG_MAX == 0x7fffffffL #define F_GETLK 12 #define F_SETLK 13 #define F_SETLKW 14 +#else +#define F_GETLK 5 +#define F_SETLK 6 +#define F_SETLKW 7 +#endif #define F_SETOWN_EX 15 #define F_GETOWN_EX 16 diff --git a/libc-top-half/musl/arch/i386/bits/syscall.h.in b/libc-top-half/musl/arch/i386/bits/syscall.h.in index 1ae4e48..abdb210 100644 --- a/libc-top-half/musl/arch/i386/bits/syscall.h.in +++ b/libc-top-half/musl/arch/i386/bits/syscall.h.in @@ -426,4 +426,8 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/i386/pthread_arch.h b/libc-top-half/musl/arch/i386/pthread_arch.h index 6f600b9..a639c38 100644 --- a/libc-top-half/musl/arch/i386/pthread_arch.h +++ b/libc-top-half/musl/arch/i386/pthread_arch.h @@ -1,10 +1,8 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - struct pthread *self; - __asm__ ("movl %%gs:0,%0" : "=r" (self) ); - return self; + uintptr_t tp; + __asm__ ("movl %%gs:0,%0" : "=r" (tp) ); + return tp; } -#define TP_ADJ(p) (p) - #define MC_PC gregs[REG_EIP] diff --git a/libc-top-half/musl/arch/i386/syscall_arch.h b/libc-top-half/musl/arch/i386/syscall_arch.h index 69642e5..f92b7aa 100644 --- a/libc-top-half/musl/arch/i386/syscall_arch.h +++ b/libc-top-half/musl/arch/i386/syscall_arch.h @@ -87,5 +87,3 @@ static inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a #define VDSO_CGT32_VER "LINUX_2.6" #define VDSO_CGT_SYM "__vdso_clock_gettime64" #define VDSO_CGT_VER "LINUX_2.6" - -#define SYSCALL_USE_SOCKETCALL diff --git a/libc-top-half/musl/arch/m68k/bits/syscall.h.in b/libc-top-half/musl/arch/m68k/bits/syscall.h.in index ddfa72e..e10969a 100644 --- a/libc-top-half/musl/arch/m68k/bits/syscall.h.in +++ b/libc-top-half/musl/arch/m68k/bits/syscall.h.in @@ -405,3 +405,8 @@ #define __NR_fsmount 432 #define __NR_fspick 433 #define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/m68k/pthread_arch.h b/libc-top-half/musl/arch/m68k/pthread_arch.h index 02d5b8a..5bea4e1 100644 --- a/libc-top-half/musl/arch/m68k/pthread_arch.h +++ b/libc-top-half/musl/arch/m68k/pthread_arch.h @@ -1,13 +1,12 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - uintptr_t tp = __syscall(SYS_get_thread_area); - return (pthread_t)(tp - 0x7000 - sizeof(struct pthread)); + return __syscall(SYS_get_thread_area); } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 0 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) +#define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 #define MC_PC gregs[R_PC] diff --git a/libc-top-half/musl/arch/m68k/syscall_arch.h b/libc-top-half/musl/arch/m68k/syscall_arch.h index af79c30..6a9d0ae 100644 --- a/libc-top-half/musl/arch/m68k/syscall_arch.h +++ b/libc-top-half/musl/arch/m68k/syscall_arch.h @@ -87,5 +87,4 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo return d0; } -#define SYSCALL_USE_SOCKETCALL #define SYSCALL_IPC_BROKEN_MODE diff --git a/libc-top-half/musl/arch/microblaze/bits/syscall.h.in b/libc-top-half/musl/arch/microblaze/bits/syscall.h.in index 963386a..9d46904 100644 --- a/libc-top-half/musl/arch/microblaze/bits/syscall.h.in +++ b/libc-top-half/musl/arch/microblaze/bits/syscall.h.in @@ -427,4 +427,8 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/microblaze/pthread_arch.h b/libc-top-half/musl/arch/microblaze/pthread_arch.h index f6ba8de..ff26624 100644 --- a/libc-top-half/musl/arch/microblaze/pthread_arch.h +++ b/libc-top-half/musl/arch/microblaze/pthread_arch.h @@ -1,10 +1,8 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - struct pthread *self; - __asm__ ("ori %0, r21, 0" : "=r" (self) ); - return self; + uintptr_t tp; + __asm__ ("ori %0, r21, 0" : "=r" (tp) ); + return tp; } -#define TP_ADJ(p) (p) - #define MC_PC regs.pc diff --git a/libc-top-half/musl/arch/microblaze/syscall_arch.h b/libc-top-half/musl/arch/microblaze/syscall_arch.h index 169013f..61d8248 100644 --- a/libc-top-half/musl/arch/microblaze/syscall_arch.h +++ b/libc-top-half/musl/arch/microblaze/syscall_arch.h @@ -95,3 +95,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo } #define SYSCALL_IPC_BROKEN_MODE + +#undef SYS_socketcall diff --git a/libc-top-half/musl/arch/mips/bits/syscall.h.in b/libc-top-half/musl/arch/mips/bits/syscall.h.in index 86251bf..2bb03f0 100644 --- a/libc-top-half/musl/arch/mips/bits/syscall.h.in +++ b/libc-top-half/musl/arch/mips/bits/syscall.h.in @@ -408,4 +408,8 @@ #define __NR_fspick 4433 #define __NR_pidfd_open 4434 #define __NR_clone3 4435 +#define __NR_close_range 4436 +#define __NR_openat2 4437 +#define __NR_pidfd_getfd 4438 +#define __NR_faccessat2 4439 diff --git a/libc-top-half/musl/arch/mips/pthread_arch.h b/libc-top-half/musl/arch/mips/pthread_arch.h index 1e7839e..c45347a 100644 --- a/libc-top-half/musl/arch/mips/pthread_arch.h +++ b/libc-top-half/musl/arch/mips/pthread_arch.h @@ -1,19 +1,19 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { #if __mips_isa_rev < 2 - register char *tp __asm__("$3"); + register uintptr_t tp __asm__("$3"); __asm__ (".word 0x7c03e83b" : "=r" (tp) ); #else - char *tp; + uintptr_t tp; __asm__ ("rdhwr %0, $29" : "=r" (tp) ); #endif - return (pthread_t)(tp - 0x7000 - sizeof(struct pthread)); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 0 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) +#define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 #define MC_PC pc diff --git a/libc-top-half/musl/arch/mips/syscall_arch.h b/libc-top-half/musl/arch/mips/syscall_arch.h index 380a94b..5b7c38d 100644 --- a/libc-top-half/musl/arch/mips/syscall_arch.h +++ b/libc-top-half/musl/arch/mips/syscall_arch.h @@ -149,3 +149,5 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo #define SO_SNDTIMEO_OLD 0x1005 #define SO_RCVTIMEO_OLD 0x1006 + +#undef SYS_socketcall diff --git a/libc-top-half/musl/arch/mips64/bits/fcntl.h b/libc-top-half/musl/arch/mips64/bits/fcntl.h index 3bcec15..5da1eef 100644 --- a/libc-top-half/musl/arch/mips64/bits/fcntl.h +++ b/libc-top-half/musl/arch/mips64/bits/fcntl.h @@ -13,7 +13,7 @@ #define O_ASYNC 010000 #define O_DIRECT 0100000 -#define O_LARGEFILE 0 +#define O_LARGEFILE 020000 #define O_NOATIME 01000000 #define O_PATH 010000000 #define O_TMPFILE 020200000 diff --git a/libc-top-half/musl/arch/mips64/bits/syscall.h.in b/libc-top-half/musl/arch/mips64/bits/syscall.h.in index 9b406e9..045e823 100644 --- a/libc-top-half/musl/arch/mips64/bits/syscall.h.in +++ b/libc-top-half/musl/arch/mips64/bits/syscall.h.in @@ -338,4 +338,8 @@ #define __NR_fspick 5433 #define __NR_pidfd_open 5434 #define __NR_clone3 5435 +#define __NR_close_range 5436 +#define __NR_openat2 5437 +#define __NR_pidfd_getfd 5438 +#define __NR_faccessat2 5439 diff --git a/libc-top-half/musl/arch/mips64/pthread_arch.h b/libc-top-half/musl/arch/mips64/pthread_arch.h index 1e7839e..c45347a 100644 --- a/libc-top-half/musl/arch/mips64/pthread_arch.h +++ b/libc-top-half/musl/arch/mips64/pthread_arch.h @@ -1,19 +1,19 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { #if __mips_isa_rev < 2 - register char *tp __asm__("$3"); + register uintptr_t tp __asm__("$3"); __asm__ (".word 0x7c03e83b" : "=r" (tp) ); #else - char *tp; + uintptr_t tp; __asm__ ("rdhwr %0, $29" : "=r" (tp) ); #endif - return (pthread_t)(tp - 0x7000 - sizeof(struct pthread)); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 0 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) +#define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 #define MC_PC pc diff --git a/libc-top-half/musl/arch/mipsn32/bits/syscall.h.in b/libc-top-half/musl/arch/mipsn32/bits/syscall.h.in index 2ad48d1..5b32255 100644 --- a/libc-top-half/musl/arch/mipsn32/bits/syscall.h.in +++ b/libc-top-half/musl/arch/mipsn32/bits/syscall.h.in @@ -362,4 +362,8 @@ #define __NR_fspick 6433 #define __NR_pidfd_open 6434 #define __NR_clone3 6435 +#define __NR_close_range 6436 +#define __NR_openat2 6437 +#define __NR_pidfd_getfd 6438 +#define __NR_faccessat2 6439 diff --git a/libc-top-half/musl/arch/mipsn32/pthread_arch.h b/libc-top-half/musl/arch/mipsn32/pthread_arch.h index 1e7839e..c45347a 100644 --- a/libc-top-half/musl/arch/mipsn32/pthread_arch.h +++ b/libc-top-half/musl/arch/mipsn32/pthread_arch.h @@ -1,19 +1,19 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { #if __mips_isa_rev < 2 - register char *tp __asm__("$3"); + register uintptr_t tp __asm__("$3"); __asm__ (".word 0x7c03e83b" : "=r" (tp) ); #else - char *tp; + uintptr_t tp; __asm__ ("rdhwr %0, $29" : "=r" (tp) ); #endif - return (pthread_t)(tp - 0x7000 - sizeof(struct pthread)); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 0 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) +#define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 #define MC_PC pc diff --git a/libc-top-half/musl/arch/or1k/bits/syscall.h.in b/libc-top-half/musl/arch/or1k/bits/syscall.h.in index e9c925e..b360389 100644 --- a/libc-top-half/musl/arch/or1k/bits/syscall.h.in +++ b/libc-top-half/musl/arch/or1k/bits/syscall.h.in @@ -311,4 +311,8 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/or1k/pthread_arch.h b/libc-top-half/musl/arch/or1k/pthread_arch.h index 1b806f8..f75ea7e 100644 --- a/libc-top-half/musl/arch/or1k/pthread_arch.h +++ b/libc-top-half/musl/arch/or1k/pthread_arch.h @@ -1,18 +1,16 @@ -/* or1k use variant I, but with the twist that tp points to the end of TCB */ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { #ifdef __clang__ - char *tp; + uintptr_t tp; __asm__ ("l.ori %0, r10, 0" : "=r" (tp) ); #else - register char *tp __asm__("r10"); + register uintptr_t tp __asm__("r10"); __asm__ ("" : "=r" (tp) ); #endif - return (struct pthread *) (tp - sizeof(struct pthread)); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 0 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread)) #define MC_PC regs.pc diff --git a/libc-top-half/musl/arch/powerpc/bits/syscall.h.in b/libc-top-half/musl/arch/powerpc/bits/syscall.h.in index 8d4f79b..5c6fae3 100644 --- a/libc-top-half/musl/arch/powerpc/bits/syscall.h.in +++ b/libc-top-half/musl/arch/powerpc/bits/syscall.h.in @@ -415,4 +415,8 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/powerpc/pthread_arch.h b/libc-top-half/musl/arch/powerpc/pthread_arch.h index ae0f28d..42e88b0 100644 --- a/libc-top-half/musl/arch/powerpc/pthread_arch.h +++ b/libc-top-half/musl/arch/powerpc/pthread_arch.h @@ -1,18 +1,16 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - register char *tp __asm__("r2"); + register uintptr_t tp __asm__("r2"); __asm__ ("" : "=r" (tp) ); - return (pthread_t)(tp - 0x7000 - sizeof(struct pthread)); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 0 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) +#define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 // the kernel calls the ip "nip", it's the first saved value after the 32 // GPRs. #define MC_PC gregs[32] - -#define CANARY canary_at_end diff --git a/libc-top-half/musl/arch/powerpc64/bits/syscall.h.in b/libc-top-half/musl/arch/powerpc64/bits/syscall.h.in index b935864..edf73d3 100644 --- a/libc-top-half/musl/arch/powerpc64/bits/syscall.h.in +++ b/libc-top-half/musl/arch/powerpc64/bits/syscall.h.in @@ -387,4 +387,8 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/powerpc64/pthread_arch.h b/libc-top-half/musl/arch/powerpc64/pthread_arch.h index 79c3ecd..1b7b907 100644 --- a/libc-top-half/musl/arch/powerpc64/pthread_arch.h +++ b/libc-top-half/musl/arch/powerpc64/pthread_arch.h @@ -1,18 +1,16 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - register char *tp __asm__("r13"); + register uintptr_t tp __asm__("r13"); __asm__ ("" : "=r" (tp) ); - return (pthread_t)(tp - 0x7000 - sizeof(struct pthread)); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 0 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) +#define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 // the kernel calls the ip "nip", it's the first saved value after the 32 // GPRs. #define MC_PC gp_regs[32] - -#define CANARY canary_at_end diff --git a/libc-top-half/musl/arch/riscv64/bits/fcntl.h b/libc-top-half/musl/arch/riscv64/bits/fcntl.h deleted file mode 100644 index ecb4d18..0000000 --- a/libc-top-half/musl/arch/riscv64/bits/fcntl.h +++ /dev/null @@ -1,38 +0,0 @@ -#define O_CREAT 0100 -#define O_EXCL 0200 -#define O_NOCTTY 0400 -#define O_TRUNC 01000 -#define O_APPEND 02000 -#define O_NONBLOCK 04000 -#define O_DSYNC 010000 -#define O_SYNC 04010000 -#define O_RSYNC 04010000 -#define O_DIRECTORY 0200000 -#define O_NOFOLLOW 0400000 -#define O_CLOEXEC 02000000 - -#define O_ASYNC 020000 -#define O_DIRECT 040000 -#define O_LARGEFILE 0100000 -#define O_NOATIME 01000000 -#define O_PATH 010000000 -#define O_TMPFILE 020200000 -#define O_NDELAY O_NONBLOCK - -#define F_DUPFD 0 -#define F_GETFD 1 -#define F_SETFD 2 -#define F_GETFL 3 -#define F_SETFL 4 -#define F_GETLK 5 -#define F_SETLK 6 -#define F_SETLKW 7 -#define F_SETOWN 8 -#define F_GETOWN 9 -#define F_SETSIG 10 -#define F_GETSIG 11 - -#define F_SETOWN_EX 15 -#define F_GETOWN_EX 16 - -#define F_GETOWNER_UIDS 17 diff --git a/libc-top-half/musl/arch/riscv64/bits/signal.h b/libc-top-half/musl/arch/riscv64/bits/signal.h index b006334..287367d 100644 --- a/libc-top-half/musl/arch/riscv64/bits/signal.h +++ b/libc-top-half/musl/arch/riscv64/bits/signal.h @@ -60,10 +60,10 @@ struct sigaltstack { size_t ss_size; }; -typedef struct ucontext_t +typedef struct __ucontext { unsigned long uc_flags; - struct ucontext_t *uc_link; + struct __ucontext *uc_link; stack_t uc_stack; sigset_t uc_sigmask; mcontext_t uc_mcontext; diff --git a/libc-top-half/musl/arch/riscv64/bits/syscall.h.in b/libc-top-half/musl/arch/riscv64/bits/syscall.h.in index 0043eeb..5def016 100644 --- a/libc-top-half/musl/arch/riscv64/bits/syscall.h.in +++ b/libc-top-half/musl/arch/riscv64/bits/syscall.h.in @@ -289,6 +289,10 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/libc-top-half/musl/arch/riscv64/pthread_arch.h b/libc-top-half/musl/arch/riscv64/pthread_arch.h index db414b1..a20d7fb 100644 --- a/libc-top-half/musl/arch/riscv64/pthread_arch.h +++ b/libc-top-half/musl/arch/riscv64/pthread_arch.h @@ -1,13 +1,12 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - char *tp; + uintptr_t tp; __asm__ __volatile__("mv %0, tp" : "=r"(tp)); - return (void *)(tp - sizeof(struct pthread)); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 0 -#define TP_ADJ(p) ((char *)p + sizeof(struct pthread)) #define DTP_OFFSET 0x800 diff --git a/libc-top-half/musl/arch/s390x/bits/alltypes.h.in b/libc-top-half/musl/arch/s390x/bits/alltypes.h.in index 15d18c8..6c0eb7f 100644 --- a/libc-top-half/musl/arch/s390x/bits/alltypes.h.in +++ b/libc-top-half/musl/arch/s390x/bits/alltypes.h.in @@ -9,7 +9,11 @@ TYPEDEF int wchar_t; #endif +#if defined(__FLT_EVAL_METHOD__) && __FLT_EVAL_METHOD__ == 1 TYPEDEF double float_t; +#else +TYPEDEF float float_t; +#endif TYPEDEF double double_t; TYPEDEF struct { long long __ll; long double __ld; } max_align_t; diff --git a/libc-top-half/musl/arch/s390x/bits/float.h b/libc-top-half/musl/arch/s390x/bits/float.h index 90b73be..e188cb6 100644 --- a/libc-top-half/musl/arch/s390x/bits/float.h +++ b/libc-top-half/musl/arch/s390x/bits/float.h @@ -1,4 +1,8 @@ -#define FLT_EVAL_METHOD 1 +#ifdef __FLT_EVAL_METHOD__ +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ +#else +#define FLT_EVAL_METHOD 0 +#endif #define LDBL_TRUE_MIN 6.47517511943802511092443895822764655e-4966L #define LDBL_MIN 3.36210314311209350626267781732175260e-4932L diff --git a/libc-top-half/musl/arch/s390x/bits/syscall.h.in b/libc-top-half/musl/arch/s390x/bits/syscall.h.in index e89f378..fb2e60e 100644 --- a/libc-top-half/musl/arch/s390x/bits/syscall.h.in +++ b/libc-top-half/musl/arch/s390x/bits/syscall.h.in @@ -352,4 +352,8 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/s390x/pthread_arch.h b/libc-top-half/musl/arch/s390x/pthread_arch.h index e2251f1..e54fec3 100644 --- a/libc-top-half/musl/arch/s390x/pthread_arch.h +++ b/libc-top-half/musl/arch/s390x/pthread_arch.h @@ -1,14 +1,12 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - struct pthread *self; + uintptr_t tp; __asm__ ( "ear %0, %%a0\n" "sllg %0, %0, 32\n" "ear %0, %%a1\n" - : "=r"(self)); - return self; + : "=r"(tp)); + return tp; } -#define TP_ADJ(p) (p) - #define MC_PC psw.addr diff --git a/libc-top-half/musl/arch/s390x/syscall_arch.h b/libc-top-half/musl/arch/s390x/syscall_arch.h index afb9985..83cc9a2 100644 --- a/libc-top-half/musl/arch/s390x/syscall_arch.h +++ b/libc-top-half/musl/arch/s390x/syscall_arch.h @@ -72,5 +72,3 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo register long r7 __asm__("r7") = f; __asm_syscall("+r"(r2), "r"(r1), "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)); } - -#define SYSCALL_USE_SOCKETCALL diff --git a/libc-top-half/musl/arch/sh/bits/signal.h b/libc-top-half/musl/arch/sh/bits/signal.h index 160311f..d0b1482 100644 --- a/libc-top-half/musl/arch/sh/bits/signal.h +++ b/libc-top-half/musl/arch/sh/bits/signal.h @@ -9,7 +9,16 @@ #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) typedef int greg_t, gregset_t[16]; typedef int freg_t, fpregset_t[16]; -typedef struct sigcontext { +typedef struct { + unsigned long oldmask; + unsigned long gregs[16]; + unsigned long pc, pr, sr; + unsigned long gbr, mach, macl; + unsigned long fpregs[16]; + unsigned long xfpregs[16]; + unsigned int fpscr, fpul, ownedfp; +} mcontext_t; +struct sigcontext { unsigned long oldmask; unsigned long sc_regs[16]; unsigned long sc_pc, sc_pr, sc_sr; @@ -17,7 +26,7 @@ typedef struct sigcontext { unsigned long sc_fpregs[16]; unsigned long sc_xfpregs[16]; unsigned int sc_fpscr, sc_fpul, sc_ownedfp; -} mcontext_t; +}; #else typedef struct { unsigned long __regs[58]; diff --git a/libc-top-half/musl/arch/sh/bits/syscall.h.in b/libc-top-half/musl/arch/sh/bits/syscall.h.in index 0102dda..158afc0 100644 --- a/libc-top-half/musl/arch/sh/bits/syscall.h.in +++ b/libc-top-half/musl/arch/sh/bits/syscall.h.in @@ -398,4 +398,9 @@ #define __NR_fsmount 432 #define __NR_fspick 433 #define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/sh/pthread_arch.h b/libc-top-half/musl/arch/sh/pthread_arch.h index 3ee9c1a..199c2d5 100644 --- a/libc-top-half/musl/arch/sh/pthread_arch.h +++ b/libc-top-half/musl/arch/sh/pthread_arch.h @@ -1,17 +1,16 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - char *self; - __asm__ ("stc gbr,%0" : "=r" (self) ); - return (struct pthread *) (self - sizeof(struct pthread)); + uintptr_t tp; + __asm__ ("stc gbr,%0" : "=r" (tp) ); + return tp; } #define TLS_ABOVE_TP #define GAP_ABOVE_TP 8 -#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread)) -#define MC_PC sc_pc +#define MC_PC pc #ifdef __FDPIC__ -#define MC_GOT sc_regs[12] +#define MC_GOT gregs[12] #define CANCEL_GOT (*(uintptr_t *)((char *)__syscall_cp_asm+sizeof(uintptr_t))) #endif diff --git a/libc-top-half/musl/arch/x32/bits/fcntl.h b/libc-top-half/musl/arch/x32/bits/fcntl.h index 1b88ad3..08627f8 100644 --- a/libc-top-half/musl/arch/x32/bits/fcntl.h +++ b/libc-top-half/musl/arch/x32/bits/fcntl.h @@ -13,7 +13,7 @@ #define O_ASYNC 020000 #define O_DIRECT 040000 -#define O_LARGEFILE 0 +#define O_LARGEFILE 0100000 #define O_NOATIME 01000000 #define O_PATH 010000000 #define O_TMPFILE 020200000 diff --git a/libc-top-half/musl/arch/x32/bits/syscall.h.in b/libc-top-half/musl/arch/x32/bits/syscall.h.in index f47bdee..cfd9856 100644 --- a/libc-top-half/musl/arch/x32/bits/syscall.h.in +++ b/libc-top-half/musl/arch/x32/bits/syscall.h.in @@ -298,6 +298,10 @@ #define __NR_fspick (0x40000000 + 433) #define __NR_pidfd_open (0x40000000 + 434) #define __NR_clone3 (0x40000000 + 435) +#define __NR_close_range (0x40000000 + 436) +#define __NR_openat2 (0x40000000 + 437) +#define __NR_pidfd_getfd (0x40000000 + 438) +#define __NR_faccessat2 (0x40000000 + 439) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/libc-top-half/musl/arch/x32/pthread_arch.h b/libc-top-half/musl/arch/x32/pthread_arch.h index f640a1a..c1e7716 100644 --- a/libc-top-half/musl/arch/x32/pthread_arch.h +++ b/libc-top-half/musl/arch/x32/pthread_arch.h @@ -1,14 +1,12 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - struct pthread *self; - __asm__ ("mov %%fs:0,%0" : "=r" (self) ); - return self; + uintptr_t tp; + __asm__ ("mov %%fs:0,%0" : "=r" (tp) ); + return tp; } -#define TP_ADJ(p) (p) - #define MC_PC gregs[REG_RIP] -#define CANARY canary2 +#define CANARY_PAD #define tls_mod_off_t unsigned long long diff --git a/libc-top-half/musl/arch/x86_64/bits/fcntl.h b/libc-top-half/musl/arch/x86_64/bits/fcntl.h deleted file mode 100644 index 1b88ad3..0000000 --- a/libc-top-half/musl/arch/x86_64/bits/fcntl.h +++ /dev/null @@ -1,40 +0,0 @@ -#define O_CREAT 0100 -#define O_EXCL 0200 -#define O_NOCTTY 0400 -#define O_TRUNC 01000 -#define O_APPEND 02000 -#define O_NONBLOCK 04000 -#define O_DSYNC 010000 -#define O_SYNC 04010000 -#define O_RSYNC 04010000 -#define O_DIRECTORY 0200000 -#define O_NOFOLLOW 0400000 -#define O_CLOEXEC 02000000 - -#define O_ASYNC 020000 -#define O_DIRECT 040000 -#define O_LARGEFILE 0 -#define O_NOATIME 01000000 -#define O_PATH 010000000 -#define O_TMPFILE 020200000 -#define O_NDELAY O_NONBLOCK - -#define F_DUPFD 0 -#define F_GETFD 1 -#define F_SETFD 2 -#define F_GETFL 3 -#define F_SETFL 4 - -#define F_SETOWN 8 -#define F_GETOWN 9 -#define F_SETSIG 10 -#define F_GETSIG 11 - -#define F_GETLK 5 -#define F_SETLK 6 -#define F_SETLKW 7 - -#define F_SETOWN_EX 15 -#define F_GETOWN_EX 16 - -#define F_GETOWNER_UIDS 17 diff --git a/libc-top-half/musl/arch/x86_64/bits/syscall.h.in b/libc-top-half/musl/arch/x86_64/bits/syscall.h.in index 6a646ad..a611795 100644 --- a/libc-top-half/musl/arch/x86_64/bits/syscall.h.in +++ b/libc-top-half/musl/arch/x86_64/bits/syscall.h.in @@ -345,4 +345,8 @@ #define __NR_fspick 433 #define __NR_pidfd_open 434 #define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 diff --git a/libc-top-half/musl/arch/x86_64/pthread_arch.h b/libc-top-half/musl/arch/x86_64/pthread_arch.h index 65e880c..c8c63f2 100644 --- a/libc-top-half/musl/arch/x86_64/pthread_arch.h +++ b/libc-top-half/musl/arch/x86_64/pthread_arch.h @@ -1,10 +1,8 @@ -static inline struct pthread *__pthread_self() +static inline uintptr_t __get_tp() { - struct pthread *self; - __asm__ ("mov %%fs:0,%0" : "=r" (self) ); - return self; + uintptr_t tp; + __asm__ ("mov %%fs:0,%0" : "=r" (tp) ); + return tp; } -#define TP_ADJ(p) (p) - #define MC_PC gregs[REG_RIP] diff --git a/libc-top-half/musl/configure b/libc-top-half/musl/configure index c50a661..3a4ed7a 100755 --- a/libc-top-half/musl/configure +++ b/libc-top-half/musl/configure @@ -30,7 +30,7 @@ System types: Optional features: --enable-optimize=... optimize listed components for speed over size [auto] --enable-debug build with debugging information [disabled] - --enable-warnings build with recommended warnings flags [disabled] + --disable-warnings build with recommended warnings flags [enabled] --enable-wrapper=... build given musl toolchain wrapper [auto] --disable-shared inhibit building shared library [enabled] --disable-static inhibit building static library [enabled] @@ -136,7 +136,7 @@ build= target= optimize=auto debug=no -warnings=no +warnings=yes shared=auto static=yes wrapper=auto @@ -204,7 +204,7 @@ fi abs_builddir="$(pwd)" || fail "$0: cannot determine working directory" abs_srcdir="$(cd $srcdir && pwd)" || fail "$0: invalid source directory $srcdir" test "$abs_srcdir" = "$abs_builddir" && srcdir=. -test "$srcdir" != "." -a -f Makefile -a ! -h Makefile && fail "$0: Makefile already exists in the working directory" +test "$srcdir" != "." && test -f Makefile && test ! -h Makefile && fail "$0: Makefile already exists in the working directory" # # Get a temp filename we can use @@ -279,7 +279,7 @@ echo "$cc_family" # # Figure out toolchain wrapper to build # -if test "$wrapper" = auto -o "$wrapper" = detect ; then +if test "$wrapper" = auto || test "$wrapper" = detect ; then echo "#include " > "$tmpc" echo "#if ! __GLIBC__" >> "$tmpc" echo "#error no" >> "$tmpc" @@ -470,7 +470,7 @@ tryflag CFLAGS_AUTO -pipe # pointer is no longer needed for debugging. # if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" ; then : -else +else tryflag CFLAGS_AUTO -fomit-frame-pointer fi @@ -510,10 +510,13 @@ fi # # GCC defines -w as overriding any -W options, regardless of order, but # clang has a bunch of annoying warnings enabled by default and needs -w -# to start from a clean slate. So use -w if building with clang. +# to start from a clean slate. So use -w if building with clang. Also +# turn off a common on-by-default cast warning regardless of compiler. # test "$cc_family" = clang && tryflag CFLAGS_AUTO -w +tryflag CFLAGS_AUTO -Wno-pointer-to-int-cast + # # Even with -std=c99, gcc accepts some constructs which are constraint # violations. We want to treat these as errors regardless of whether @@ -524,6 +527,10 @@ tryflag CFLAGS_AUTO -Werror=implicit-function-declaration tryflag CFLAGS_AUTO -Werror=implicit-int tryflag CFLAGS_AUTO -Werror=pointer-sign tryflag CFLAGS_AUTO -Werror=pointer-arith +tryflag CFLAGS_AUTO -Werror=int-conversion +tryflag CFLAGS_AUTO -Werror=incompatible-pointer-types +tryflag CFLAGS_AUTO -Werror=discarded-qualifiers +tryflag CFLAGS_AUTO -Werror=discarded-array-qualifiers # # GCC ignores unused arguements by default, but Clang needs this extra @@ -533,14 +540,17 @@ tryflag CFLAGS_AUTO -Werror=pointer-arith test "$cc_family" = clang && tryflag CFLAGS_AUTO -Qunused-arguments if test "x$warnings" = xyes ; then -tryflag CFLAGS_AUTO -Wall -tryflag CFLAGS_AUTO -Wno-parentheses -tryflag CFLAGS_AUTO -Wno-uninitialized -tryflag CFLAGS_AUTO -Wno-missing-braces -tryflag CFLAGS_AUTO -Wno-unused-value -tryflag CFLAGS_AUTO -Wno-unused-but-set-variable -tryflag CFLAGS_AUTO -Wno-unknown-pragmas -tryflag CFLAGS_AUTO -Wno-pointer-to-int-cast +tryflag CFLAGS_AUTO -Waddress +tryflag CFLAGS_AUTO -Warray-bounds +tryflag CFLAGS_AUTO -Wchar-subscripts +tryflag CFLAGS_AUTO -Wduplicate-decl-specifier +tryflag CFLAGS_AUTO -Winit-self +tryflag CFLAGS_AUTO -Wreturn-type +tryflag CFLAGS_AUTO -Wsequence-point +tryflag CFLAGS_AUTO -Wstrict-aliasing +tryflag CFLAGS_AUTO -Wunused-function +tryflag CFLAGS_AUTO -Wunused-label +tryflag CFLAGS_AUTO -Wunused-variable fi # Determine if the compiler produces position-independent code (PIC) diff --git a/libc-top-half/musl/include/alltypes.h.in b/libc-top-half/musl/include/alltypes.h.in index 3daf9f6..dcd474f 100644 --- a/libc-top-half/musl/include/alltypes.h.in +++ b/libc-top-half/musl/include/alltypes.h.in @@ -100,6 +100,8 @@ STRUCT iovec { void *iov_base; size_t iov_len; }; #include <__struct_iovec.h> #endif +STRUCT winsize { unsigned short ws_row, ws_col, ws_xpixel, ws_ypixel; }; + TYPEDEF unsigned socklen_t; TYPEDEF unsigned short sa_family_t; diff --git a/libc-top-half/musl/include/complex.h b/libc-top-half/musl/include/complex.h index daa7f85..a645eb1 100644 --- a/libc-top-half/musl/include/complex.h +++ b/libc-top-half/musl/include/complex.h @@ -114,6 +114,14 @@ long double creall(long double complex); #define cimagf(x) __CIMAG(x, float) #define cimagl(x) __CIMAG(x, long double) #endif +#else +#define creal(x) (__builtin_creal(x)) +#define crealf(x) (__builtin_crealf(x)) +#define creall(x) (__builtin_creall(x)) + +#define cimag(x) (__builtin_cimag(x)) +#define cimagf(x) (__builtin_cimagf(x)) +#define cimagl(x) (__builtin_cimagl(x)) #endif #if __STDC_VERSION__ >= 201112L diff --git a/libc-top-half/musl/include/elf.h b/libc-top-half/musl/include/elf.h index 549f92c..b5e7bef 100644 --- a/libc-top-half/musl/include/elf.h +++ b/libc-top-half/musl/include/elf.h @@ -603,6 +603,7 @@ typedef struct { #define PT_GNU_EH_FRAME 0x6474e550 #define PT_GNU_STACK 0x6474e551 #define PT_GNU_RELRO 0x6474e552 +#define PT_GNU_PROPERTY 0x6474e553 #define PT_LOSUNW 0x6ffffffa #define PT_SUNWBSS 0x6ffffffa #define PT_SUNWSTACK 0x6ffffffb @@ -1085,6 +1086,7 @@ typedef struct { #define NT_GNU_BUILD_ID 3 #define NT_GNU_GOLD_VERSION 4 +#define NT_GNU_PROPERTY_TYPE_0 5 diff --git a/libc-top-half/musl/include/netinet/if_ether.h b/libc-top-half/musl/include/netinet/if_ether.h index a08485e..55a2ff1 100644 --- a/libc-top-half/musl/include/netinet/if_ether.h +++ b/libc-top-half/musl/include/netinet/if_ether.h @@ -59,6 +59,7 @@ #define ETH_P_PREAUTH 0x88C7 #define ETH_P_TIPC 0x88CA #define ETH_P_LLDP 0x88CC +#define ETH_P_MRP 0x88E3 #define ETH_P_MACSEC 0x88E5 #define ETH_P_8021AH 0x88E7 #define ETH_P_MVRP 0x88F5 diff --git a/libc-top-half/musl/include/netinet/in.h b/libc-top-half/musl/include/netinet/in.h index 0696489..b09efab 100644 --- a/libc-top-half/musl/include/netinet/in.h +++ b/libc-top-half/musl/include/netinet/in.h @@ -116,8 +116,10 @@ uint16_t ntohs(uint16_t); #define IPPROTO_MH 135 #define IPPROTO_UDPLITE 136 #define IPPROTO_MPLS 137 +#define IPPROTO_ETHERNET 143 #define IPPROTO_RAW 255 -#define IPPROTO_MAX 256 +#define IPPROTO_MPTCP 262 +#define IPPROTO_MAX 263 #endif #define IN6_IS_ADDR_UNSPECIFIED(a) \ @@ -216,6 +218,7 @@ uint16_t ntohs(uint16_t); #define IP_CHECKSUM 23 #define IP_BIND_ADDRESS_NO_PORT 24 #define IP_RECVFRAGSIZE 25 +#define IP_RECVERR_RFC4884 26 #define IP_MULTICAST_IF 32 #define IP_MULTICAST_TTL 33 #define IP_MULTICAST_LOOP 34 diff --git a/libc-top-half/musl/include/netinet/tcp.h b/libc-top-half/musl/include/netinet/tcp.h index 44a007a..b7b997f 100644 --- a/libc-top-half/musl/include/netinet/tcp.h +++ b/libc-top-half/musl/include/netinet/tcp.h @@ -78,6 +78,8 @@ enum { TCP_NLA_DSACK_DUPS, TCP_NLA_REORD_SEEN, TCP_NLA_SRTT, + TCP_NLA_TIMEOUT_REHASH, + TCP_NLA_BYTES_NOTSENT, }; #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) @@ -181,6 +183,13 @@ struct tcphdr { #define TCP_CA_Recovery 3 #define TCP_CA_Loss 4 +enum tcp_fastopen_client_fail { + TFO_STATUS_UNSPEC, + TFO_COOKIE_UNAVAILABLE, + TFO_DATA_NOT_ACKED, + TFO_SYN_RETRANSMITTED, +}; + struct tcp_info { uint8_t tcpi_state; uint8_t tcpi_ca_state; @@ -189,7 +198,7 @@ struct tcp_info { uint8_t tcpi_backoff; uint8_t tcpi_options; uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; - uint8_t tcpi_delivery_rate_app_limited : 1; + uint8_t tcpi_delivery_rate_app_limited : 1, tcpi_fastopen_client_fail : 2; uint32_t tcpi_rto; uint32_t tcpi_ato; uint32_t tcpi_snd_mss; @@ -240,14 +249,15 @@ struct tcp_info { #define TCP_MD5SIG_MAXKEYLEN 80 -#define TCP_MD5SIG_FLAG_PREFIX 1 +#define TCP_MD5SIG_FLAG_PREFIX 0x1 +#define TCP_MD5SIG_FLAG_IFINDEX 0x2 struct tcp_md5sig { struct sockaddr_storage tcpm_addr; uint8_t tcpm_flags; uint8_t tcpm_prefixlen; uint16_t tcpm_keylen; - uint32_t __tcpm_pad; + int tcpm_ifindex; uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; }; @@ -275,6 +285,8 @@ struct tcp_zerocopy_receive { uint64_t address; uint32_t length; uint32_t recv_skip_hint; + uint32_t inq; + int32_t err; }; #endif diff --git a/libc-top-half/musl/include/netinet/udp.h b/libc-top-half/musl/include/netinet/udp.h index ffd8907..40c3f20 100644 --- a/libc-top-half/musl/include/netinet/udp.h +++ b/libc-top-half/musl/include/netinet/udp.h @@ -35,6 +35,7 @@ struct udphdr { #define UDP_ENCAP_GTP0 4 #define UDP_ENCAP_GTP1U 5 #define UDP_ENCAP_RXRPC 6 +#define TCP_ENCAP_ESPINTCP 7 #define SOL_UDP 17 diff --git a/libc-top-half/musl/include/sched.h b/libc-top-half/musl/include/sched.h index 36dd4df..a3a7f56 100644 --- a/libc-top-half/musl/include/sched.h +++ b/libc-top-half/musl/include/sched.h @@ -52,6 +52,7 @@ int sched_yield(void); #ifdef _GNU_SOURCE #define CSIGNAL 0x000000ff +#define CLONE_NEWTIME 0x00000080 #define CLONE_VM 0x00000100 #define CLONE_FS 0x00000200 #define CLONE_FILES 0x00000400 diff --git a/libc-top-half/musl/include/signal.h b/libc-top-half/musl/include/signal.h index a835032..ae74966 100644 --- a/libc-top-half/musl/include/signal.h +++ b/libc-top-half/musl/include/signal.h @@ -187,14 +187,24 @@ struct sigevent { union sigval sigev_value; int sigev_signo; int sigev_notify; - void (*sigev_notify_function)(union sigval); - pthread_attr_t *sigev_notify_attributes; - char __pad[56-3*sizeof(long)]; + union { + char __pad[64 - 2*sizeof(int) - sizeof(union sigval)]; + pid_t sigev_notify_thread_id; + struct { + void (*sigev_notify_function)(union sigval); + pthread_attr_t *sigev_notify_attributes; + } __sev_thread; + } __sev_fields; }; +#define sigev_notify_thread_id __sev_fields.sigev_notify_thread_id +#define sigev_notify_function __sev_fields.__sev_thread.sigev_notify_function +#define sigev_notify_attributes __sev_fields.__sev_thread.sigev_notify_attributes + #define SIGEV_SIGNAL 0 #define SIGEV_NONE 1 #define SIGEV_THREAD 2 +#define SIGEV_THREAD_ID 4 #endif #ifdef __wasilibc_unmodified_upstream /* WASI has no realtime signals */ diff --git a/libc-top-half/musl/include/stdlib.h b/libc-top-half/musl/include/stdlib.h index 3d4b1f3..e635275 100644 --- a/libc-top-half/musl/include/stdlib.h +++ b/libc-top-half/musl/include/stdlib.h @@ -170,6 +170,7 @@ int clearenv(void); #ifdef __wasilibc_unmodified_upstream /* WASI has no wait */ #define WCOREDUMP(s) ((s) & 0x80) #define WIFCONTINUED(s) ((s) == 0xffff) +void *reallocarray (void *, size_t, size_t); #endif #endif diff --git a/libc-top-half/musl/include/sys/fanotify.h b/libc-top-half/musl/include/sys/fanotify.h index b637c8f..10e5f15 100644 --- a/libc-top-half/musl/include/sys/fanotify.h +++ b/libc-top-half/musl/include/sys/fanotify.h @@ -55,8 +55,9 @@ struct fanotify_response { #define FAN_OPEN_PERM 0x10000 #define FAN_ACCESS_PERM 0x20000 #define FAN_OPEN_EXEC_PERM 0x40000 -#define FAN_ONDIR 0x40000000 +#define FAN_DIR_MODIFY 0x00080000 #define FAN_EVENT_ON_CHILD 0x08000000 +#define FAN_ONDIR 0x40000000 #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) #define FAN_MOVE (FAN_MOVED_FROM | FAN_MOVED_TO) #define FAN_CLOEXEC 0x01 @@ -70,6 +71,9 @@ struct fanotify_response { #define FAN_ENABLE_AUDIT 0x40 #define FAN_REPORT_TID 0x100 #define FAN_REPORT_FID 0x200 +#define FAN_REPORT_DIR_FID 0x00000400 +#define FAN_REPORT_NAME 0x00000800 +#define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME) #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS) #define FAN_MARK_ADD 0x01 #define FAN_MARK_REMOVE 0x02 @@ -88,6 +92,8 @@ struct fanotify_response { #define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_Q_OVERFLOW) #define FANOTIFY_METADATA_VERSION 3 #define FAN_EVENT_INFO_TYPE_FID 1 +#define FAN_EVENT_INFO_TYPE_DFID_NAME 2 +#define FAN_EVENT_INFO_TYPE_DFID 3 #define FAN_ALLOW 0x01 #define FAN_DENY 0x02 #define FAN_AUDIT 0x10 diff --git a/libc-top-half/musl/include/sys/ioctl.h b/libc-top-half/musl/include/sys/ioctl.h index 3877ca4..cf3acb3 100644 --- a/libc-top-half/musl/include/sys/ioctl.h +++ b/libc-top-half/musl/include/sys/ioctl.h @@ -5,6 +5,8 @@ extern "C" { #endif +#define __NEED_struct_winsize + #include #include @@ -48,13 +50,6 @@ extern "C" { #define TIOCSER_TEMT 1 -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - #define SIOCADDRT 0x890B #define SIOCDELRT 0x890C #define SIOCRTMSG 0x890D diff --git a/libc-top-half/musl/include/sys/mman.h b/libc-top-half/musl/include/sys/mman.h index e6079c8..80615c5 100644 --- a/libc-top-half/musl/include/sys/mman.h +++ b/libc-top-half/musl/include/sys/mman.h @@ -105,6 +105,7 @@ extern "C" { #ifdef _GNU_SOURCE #define MREMAP_MAYMOVE 1 #define MREMAP_FIXED 2 +#define MREMAP_DONTUNMAP 4 #define MLOCK_ONFAULT 0x01 diff --git a/libc-top-half/musl/include/sys/param.h b/libc-top-half/musl/include/sys/param.h index ce6b801..0141172 100644 --- a/libc-top-half/musl/include/sys/param.h +++ b/libc-top-half/musl/include/sys/param.h @@ -28,7 +28,9 @@ #define roundup(n,d) (howmany(n,d)*(d)) #define powerof2(n) !(((n)-1) & (n)) +#if defined(__wasilibc_unmodified_upstream) || defined(_WASI_EMULATED_PROCESS_CLOCKS) #include +#endif #include #include diff --git a/libc-top-half/musl/include/sys/personality.h b/libc-top-half/musl/include/sys/personality.h index 31d43df..411dc47 100644 --- a/libc-top-half/musl/include/sys/personality.h +++ b/libc-top-half/musl/include/sys/personality.h @@ -5,7 +5,9 @@ extern "C" { #endif +#define UNAME26 0x0020000 #define ADDR_NO_RANDOMIZE 0x0040000 +#define FDPIC_FUNCPTRS 0x0080000 #define MMAP_PAGE_ZERO 0x0100000 #define ADDR_COMPAT_LAYOUT 0x0200000 #define READ_IMPLIES_EXEC 0x0400000 @@ -17,6 +19,7 @@ extern "C" { #define PER_LINUX 0 #define PER_LINUX_32BIT ADDR_LIMIT_32BIT +#define PER_LINUX_FDPIC FDPIC_FUNCPTRS #define PER_SVR4 (1 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO) #define PER_SVR3 (2 | STICKY_TIMEOUTS | SHORT_INODE) #define PER_SCOSVR3 (3 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE) diff --git a/libc-top-half/musl/include/sys/prctl.h b/libc-top-half/musl/include/sys/prctl.h index d9c846e..4b9fcc0 100644 --- a/libc-top-half/musl/include/sys/prctl.h +++ b/libc-top-half/musl/include/sys/prctl.h @@ -158,6 +158,9 @@ struct prctl_mm_map { #define PR_GET_TAGGED_ADDR_CTRL 56 #define PR_TAGGED_ADDR_ENABLE (1UL << 0) +#define PR_SET_IO_FLUSHER 57 +#define PR_GET_IO_FLUSHER 58 + int prctl (int, ...); #ifdef __cplusplus diff --git a/libc-top-half/musl/include/sys/random.h b/libc-top-half/musl/include/sys/random.h index 0920425..51cf9d7 100644 --- a/libc-top-half/musl/include/sys/random.h +++ b/libc-top-half/musl/include/sys/random.h @@ -11,6 +11,7 @@ extern "C" { #define GRND_NONBLOCK 0x0001 #define GRND_RANDOM 0x0002 +#define GRND_INSECURE 0x0004 ssize_t getrandom(void *, size_t, unsigned); #else diff --git a/libc-top-half/musl/include/sys/resource.h b/libc-top-half/musl/include/sys/resource.h index 8b55331..6c3a7ff 100644 --- a/libc-top-half/musl/include/sys/resource.h +++ b/libc-top-half/musl/include/sys/resource.h @@ -1,3 +1,8 @@ +#ifndef _WASI_EMULATED_PROCESS_CLOCKS +#error WASI lacks process-associated clocks; to enable emulation of the `getrusage` function using \ +the wall clock, which isn't sensitive to whether the program is running or suspended, \ +compile with -D_WASI_EMULATED_PROCESS_CLOCKS and link with -lwasi-emulated-process-clocks +#else #ifndef _SYS_RESOURCE_H #define _SYS_RESOURCE_H @@ -118,3 +123,4 @@ __REDIR(getrusage, __getrusage_time64); #endif #endif +#endif diff --git a/libc-top-half/musl/include/sys/times.h b/libc-top-half/musl/include/sys/times.h index 2256334..cdaeeee 100644 --- a/libc-top-half/musl/include/sys/times.h +++ b/libc-top-half/musl/include/sys/times.h @@ -1,3 +1,8 @@ +#ifndef _WASI_EMULATED_PROCESS_CLOCKS +#error WASI lacks process-associated clocks; to enable emulation of the `times` function using \ +the wall clock, which isn't sensitive to whether the program is running or suspended, \ +compile with -D_WASI_EMULATED_PROCESS_CLOCKS and link with -lwasi-emulated-process-clocks +#else #ifndef _SYS_TIMES_H #define _SYS_TIMES_H @@ -26,4 +31,4 @@ clock_t times (struct tms *); #endif #endif - +#endif diff --git a/libc-top-half/musl/include/termios.h b/libc-top-half/musl/include/termios.h index d73c780..cbb5330 100644 --- a/libc-top-half/musl/include/termios.h +++ b/libc-top-half/musl/include/termios.h @@ -8,6 +8,7 @@ extern "C" { #include #define __NEED_pid_t +#define __NEED_struct_winsize #include @@ -27,6 +28,9 @@ int cfsetispeed (struct termios *, speed_t); int tcgetattr (int, struct termios *); int tcsetattr (int, int, const struct termios *); +int tcgetwinsize (int, struct winsize *); +int tcsetwinsize (int, const struct winsize *); + int tcsendbreak (int, int); int tcdrain (int); int tcflush (int, int); diff --git a/libc-top-half/musl/include/time.h b/libc-top-half/musl/include/time.h index 01ba89b..1fb8768 100644 --- a/libc-top-half/musl/include/time.h +++ b/libc-top-half/musl/include/time.h @@ -58,7 +58,16 @@ struct tm { #include <__header_time.h> #endif +#if defined(__wasilibc_unmodified_upstream) || defined(_WASI_EMULATED_PROCESS_CLOCKS) clock_t clock (void); +#else +__attribute__((__deprecated__( +"WASI lacks process-associated clocks; to enable emulation of the `clock` function using " +"the wall clock, which isn't sensitive to whether the program is running or suspended, " +"compile with -D_WASI_EMULATED_PROCESS_CLOCKS and link with -lwasi-emulated-process-clocks" +))) +clock_t clock (void); +#endif time_t time (time_t *); double difftime (time_t, time_t); time_t mktime (struct tm *); diff --git a/libc-top-half/musl/include/unistd.h b/libc-top-half/musl/include/unistd.h index 0eac1cf..7ca99ae 100644 --- a/libc-top-half/musl/include/unistd.h +++ b/libc-top-half/musl/include/unistd.h @@ -134,6 +134,7 @@ int pause(void); #ifdef __wasilibc_unmodified_upstream /* WASI has no fork/exec */ pid_t fork(void); +pid_t _Fork(void); int execve(const char *, char *const [], char *const []); int execv(const char *, char *const []); int execle(const char *, const char *, ...); @@ -144,8 +145,17 @@ int fexecve(int, char *const [], char *const []); #endif _Noreturn void _exit(int); -#ifdef __wasilibc_unmodified_upstream /* WASI has no getpid etc. */ +#if defined(__wasilibc_unmodified_upstream) || defined(_WASI_EMULATED_GETPID) pid_t getpid(void); +#else +__attribute__((__deprecated__( +"WASI lacks process identifiers; to enable emulation of the `getpid` function using " +"a placeholder value, which doesn't reflect the host PID of the program, " +"compile with -D_WASI_EMULATED_GETPID and link with -lwasi-emulated-getpid" +))) +pid_t getpid(void); +#endif +#ifdef __wasilibc_unmodified_upstream /* WASI has no getpid etc. */ pid_t getppid(void); pid_t getpgrp(void); pid_t getpgid(pid_t); @@ -268,6 +278,7 @@ int syncfs(int); int euidaccess(const char *, int); int eaccess(const char *, int); ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned); +pid_t gettid(void); #endif #endif diff --git a/libc-top-half/musl/ldso/dynlink.c b/libc-top-half/musl/ldso/dynlink.c index d3d4ddd..6b868c8 100644 --- a/libc-top-half/musl/ldso/dynlink.c +++ b/libc-top-half/musl/ldso/dynlink.c @@ -1,6 +1,5 @@ #define _GNU_SOURCE #define SYSCALL_NO_TLS 1 -#include #include #include #include @@ -21,9 +20,15 @@ #include #include #include "pthread_impl.h" +#include "fork_impl.h" #include "libc.h" #include "dynlink.h" +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc __libc_realloc +#define free __libc_free + static void error(const char *, ...); #define MAXP2(a,b) (-(-(a)&-(b))) @@ -78,7 +83,7 @@ struct dso { struct dso **deps, *needed_by; size_t ndeps_direct; size_t next_dep; - int ctor_visitor; + pthread_t ctor_visitor; char *rpath_orig, *rpath; struct tls_module tls; size_t tls_id; @@ -556,6 +561,20 @@ static void reclaim_gaps(struct dso *dso) } } +static ssize_t read_loop(int fd, void *p, size_t n) +{ + for (size_t i=0; i=0) { + size_t n = 0; + if (!fstat(fd, &st)) n = st.st_size; + if ((sys_path = malloc(n+1))) + sys_path[n] = 0; + if (!sys_path || read_loop(fd, sys_path, n)<0) { free(sys_path); sys_path = ""; } - fclose(f); + close(fd); } else if (errno != ENOENT) { sys_path = ""; } @@ -1378,7 +1401,7 @@ void __libc_exit_fini() { struct dso *p; size_t dyn[DYN_CNT]; - int self = __pthread_self()->tid; + pthread_t self = __pthread_self(); /* Take both locks before setting shutting_down, so that * either lock is sufficient to read its value. The lock @@ -1404,6 +1427,17 @@ void __libc_exit_fini() } } +void __ldso_atfork(int who) +{ + if (who<0) { + pthread_rwlock_wrlock(&lock); + pthread_mutex_lock(&init_fini_lock); + } else { + pthread_mutex_unlock(&init_fini_lock); + pthread_rwlock_unlock(&lock); + } +} + static struct dso **queue_ctors(struct dso *dso) { size_t cnt, qpos, spos, i; @@ -1462,6 +1496,13 @@ static struct dso **queue_ctors(struct dso *dso) } queue[qpos] = 0; for (i=0; imark = 0; + for (i=0; ictor_visitor && queue[i]->ctor_visitor->tid < 0) { + error("State of %s is inconsistent due to multithreaded fork\n", + queue[i]->name); + free(queue); + if (runtime) longjmp(*rtld_fail, 1); + } return queue; } @@ -1470,7 +1511,7 @@ static void do_init_fini(struct dso **queue) { struct dso *p; size_t dyn[DYN_CNT], i; - int self = __pthread_self()->tid; + pthread_t self = __pthread_self(); pthread_mutex_lock(&init_fini_lock); for (i=0; (p=queue[i]); i++) { @@ -1579,7 +1620,7 @@ static void install_new_tls(void) /* Install new dtv for each thread. */ for (j=0, td=self; !j || td!=self; j++, td=td->next) { - td->dtv = td->dtv_copy = newdtv[j]; + td->dtv = newdtv[j]; } __tl_unlock(); @@ -1947,7 +1988,7 @@ void __dls3(size_t *sp, size_t *auxv) debug.bp = dl_debug_state; debug.head = head; debug.base = ldso.base; - debug.state = 0; + debug.state = RT_CONSISTENT; _dl_debug_state(); if (replace_argv0) argv[0] = replace_argv0; @@ -1996,6 +2037,9 @@ void *dlopen(const char *file, int mode) pthread_rwlock_wrlock(&lock); __inhibit_ptc(); + debug.state = RT_ADD; + _dl_debug_state(); + p = 0; if (shutting_down) { error("Cannot dlopen while program is exiting."); @@ -2055,8 +2099,9 @@ void *dlopen(const char *file, int mode) load_deps(p); extend_bfs_deps(p); pthread_mutex_lock(&init_fini_lock); - if (!p->constructed) ctor_queue = queue_ctors(p); + int constructed = p->constructed; pthread_mutex_unlock(&init_fini_lock); + if (!constructed) ctor_queue = queue_ctors(p); if (!p->relocated && (mode & RTLD_LAZY)) { prepare_lazy(p); for (i=0; p->deps[i]; i++) @@ -2088,9 +2133,10 @@ void *dlopen(const char *file, int mode) update_tls_size(); if (tls_cnt != orig_tls_cnt) install_new_tls(); - _dl_debug_state(); orig_tail = tail; end: + debug.state = RT_CONSISTENT; + _dl_debug_state(); __release_ptc(); if (p) gencnt++; pthread_rwlock_unlock(&lock); diff --git a/libc-top-half/musl/src/aio/aio.c b/libc-top-half/musl/src/aio/aio.c index 6d34fa8..a1a3e79 100644 --- a/libc-top-half/musl/src/aio/aio.c +++ b/libc-top-half/musl/src/aio/aio.c @@ -9,6 +9,12 @@ #include "syscall.h" #include "atomic.h" #include "pthread_impl.h" +#include "aio_impl.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc __libc_realloc +#define free __libc_free /* The following is a threads-based implementation of AIO with minimal * dependence on implementation details. Most synchronization is @@ -70,6 +76,10 @@ static struct aio_queue *****map; static volatile int aio_fd_cnt; volatile int __aio_fut; +static size_t io_thread_stack_size; + +#define MAX(a,b) ((a)>(b) ? (a) : (b)) + static struct aio_queue *__aio_get_queue(int fd, int need) { if (fd < 0) { @@ -84,6 +94,10 @@ static struct aio_queue *__aio_get_queue(int fd, int need) pthread_rwlock_unlock(&maplock); if (fcntl(fd, F_GETFD) < 0) return 0; pthread_rwlock_wrlock(&maplock); + if (!io_thread_stack_size) { + unsigned long val = __getauxval(AT_MINSIGSTKSZ); + io_thread_stack_size = MAX(MINSIGSTKSZ+2048, val+512); + } if (!map) map = calloc(sizeof *map, (-1U/2+1)>>24); if (!map) goto out; if (!map[a]) map[a] = calloc(sizeof **map, 256); @@ -259,15 +273,6 @@ static void *io_thread_func(void *ctx) return 0; } -static size_t io_thread_stack_size = MINSIGSTKSZ+2048; -static pthread_once_t init_stack_size_once; - -static void init_stack_size() -{ - unsigned long val = __getauxval(AT_MINSIGSTKSZ); - if (val > MINSIGSTKSZ) io_thread_stack_size = val + 512; -} - static int submit(struct aiocb *cb, int op) { int ret = 0; @@ -293,7 +298,6 @@ static int submit(struct aiocb *cb, int op) else pthread_attr_init(&a); } else { - pthread_once(&init_stack_size_once, init_stack_size); pthread_attr_init(&a); pthread_attr_setstacksize(&a, io_thread_stack_size); pthread_attr_setguardsize(&a, 0); @@ -392,6 +396,20 @@ int __aio_close(int fd) return fd; } +void __aio_atfork(int who) +{ + if (who<0) { + pthread_rwlock_rdlock(&maplock); + return; + } + if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++) + if (map[a]) for (int b=0; b<256; b++) + if (map[a][b]) for (int c=0; c<256; c++) + if (map[a][b][c]) for (int d=0; d<256; d++) + map[a][b][c][d] = 0; + pthread_rwlock_unlock(&maplock); +} + weak_alias(aio_cancel, aio_cancel64); weak_alias(aio_error, aio_error64); weak_alias(aio_fsync, aio_fsync64); diff --git a/libc-top-half/musl/src/aio/aio_suspend.c b/libc-top-half/musl/src/aio/aio_suspend.c index 34b66f8..1c1060e 100644 --- a/libc-top-half/musl/src/aio/aio_suspend.c +++ b/libc-top-half/musl/src/aio/aio_suspend.c @@ -3,6 +3,7 @@ #include #include "atomic.h" #include "pthread_impl.h" +#include "aio_impl.h" int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts) { diff --git a/libc-top-half/musl/src/conf/sysconf.c b/libc-top-half/musl/src/conf/sysconf.c index d58da7f..1a406e6 100644 --- a/libc-top-half/musl/src/conf/sysconf.c +++ b/libc-top-half/musl/src/conf/sysconf.c @@ -1,12 +1,16 @@ #include #include #include +#ifdef __wasilibc_unmodified_upstream // WASI has no process-level accounting #include +#endif #ifdef __wasilibc_unmodified_upstream // WASI has no realtime signals #include #endif #include +#ifdef __wasilibc_unmodified_upstream #include "syscall.h" +#endif #include "libc.h" #define JT(x) (-256|(x)) diff --git a/libc-top-half/musl/src/crypt/crypt_blowfish.c b/libc-top-half/musl/src/crypt/crypt_blowfish.c index d3f7985..d722607 100644 --- a/libc-top-half/musl/src/crypt/crypt_blowfish.c +++ b/libc-top-half/musl/src/crypt/crypt_blowfish.c @@ -15,7 +15,7 @@ * No copyright is claimed, and the software is hereby placed in the public * domain. In case this attempt to disclaim copyright and place the software * in the public domain is deemed null and void, then the software is - * Copyright (c) 1998-2012 Solar Designer and it is hereby released to the + * Copyright (c) 1998-2014 Solar Designer and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without @@ -31,12 +31,12 @@ * you place this code and any modifications you make under a license * of your choice. * - * This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix - * "$2a$") by Niels Provos , and uses some of his - * ideas. The password hashing algorithm was designed by David Mazieres - * . For more information on the level of compatibility, - * please refer to the comments in BF_set_key() below and to the included - * crypt(3) man page. + * This implementation is fully compatible with OpenBSD's bcrypt.c for prefix + * "$2b$", originally by Niels Provos , and it uses + * some of his ideas. The password hashing algorithm was designed by David + * Mazieres . For information on the level of + * compatibility for bcrypt hash prefixes other than "$2b$", please refer to + * the comments in BF_set_key() below and to the included crypt(3) man page. * * There's a paper on the algorithm that explains its design decisions: * @@ -533,6 +533,7 @@ static void BF_set_key(const char *key, BF_key expanded, BF_key initial, * Valid combinations of settings are: * * Prefix "$2a$": bug = 0, safety = 0x10000 + * Prefix "$2b$": bug = 0, safety = 0 * Prefix "$2x$": bug = 1, safety = 0 * Prefix "$2y$": bug = 0, safety = 0 */ @@ -596,12 +597,14 @@ static void BF_set_key(const char *key, BF_key expanded, BF_key initial, initial[0] ^= sign; } +static const unsigned char flags_by_subtype[26] = { + 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0 +}; + static char *BF_crypt(const char *key, const char *setting, char *output, BF_word min) { - static const unsigned char flags_by_subtype[26] = - {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0}; struct { BF_ctx ctx; BF_key expanded_key; @@ -746,9 +749,11 @@ char *__crypt_blowfish(const char *key, const char *setting, char *output) { const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8"; const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu"; - static const char test_hash[2][34] = - {"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* $2x$ */ - "i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55"}; /* $2a$, $2y$ */ + static const char test_hashes[2][34] = { + "i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */ + "VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* 'x' */ + }; + const char *test_hash = test_hashes[0]; char *retval; const char *p; int ok; @@ -768,8 +773,11 @@ char *__crypt_blowfish(const char *key, const char *setting, char *output) * detected by the self-test. */ memcpy(buf.s, test_setting, sizeof(buf.s)); - if (retval) + if (retval) { + unsigned int flags = flags_by_subtype[setting[2] - 'a']; + test_hash = test_hashes[flags & 1]; buf.s[2] = setting[2]; + } memset(buf.o, 0x55, sizeof(buf.o)); buf.o[sizeof(buf.o) - 1] = 0; p = BF_crypt(test_key, buf.s, buf.o, 1); @@ -777,7 +785,7 @@ char *__crypt_blowfish(const char *key, const char *setting, char *output) ok = (p == buf.o && !memcmp(p, buf.s, 7 + 22) && !memcmp(p + (7 + 22), - test_hash[buf.s[2] & 1], + test_hash, 31 + 1 + 1 + 1)); { diff --git a/libc-top-half/musl/src/env/__init_tls.c b/libc-top-half/musl/src/env/__init_tls.c index 772baba..a93141e 100644 --- a/libc-top-half/musl/src/env/__init_tls.c +++ b/libc-top-half/musl/src/env/__init_tls.c @@ -67,7 +67,7 @@ void *__copy_tls(unsigned char *mem) } #endif dtv[0] = libc.tls_cnt; - td->dtv = td->dtv_copy = dtv; + td->dtv = dtv; return td; } diff --git a/libc-top-half/musl/src/env/__stack_chk_fail.c b/libc-top-half/musl/src/env/__stack_chk_fail.c index e32596d..bf5a280 100644 --- a/libc-top-half/musl/src/env/__stack_chk_fail.c +++ b/libc-top-half/musl/src/env/__stack_chk_fail.c @@ -9,7 +9,7 @@ void __init_ssp(void *entropy) if (entropy) memcpy(&__stack_chk_guard, entropy, sizeof(uintptr_t)); else __stack_chk_guard = (uintptr_t)&__stack_chk_guard * 1103515245; - __pthread_self()->CANARY = __stack_chk_guard; + __pthread_self()->canary = __stack_chk_guard; } void __stack_chk_fail(void) diff --git a/libc-top-half/musl/src/exit/abort.c b/libc-top-half/musl/src/exit/abort.c index e1980f1..f21f458 100644 --- a/libc-top-half/musl/src/exit/abort.c +++ b/libc-top-half/musl/src/exit/abort.c @@ -6,8 +6,6 @@ #include "lock.h" #include "ksigaction.h" -hidden volatile int __abort_lock[1]; - _Noreturn void abort(void) { raise(SIGABRT); diff --git a/libc-top-half/musl/src/exit/abort_lock.c b/libc-top-half/musl/src/exit/abort_lock.c new file mode 100644 index 0000000..3af72c7 --- /dev/null +++ b/libc-top-half/musl/src/exit/abort_lock.c @@ -0,0 +1,3 @@ +#include "pthread_impl.h" + +volatile int __abort_lock[1]; diff --git a/libc-top-half/musl/src/exit/assert.c b/libc-top-half/musl/src/exit/assert.c index 49b0dc3..94edd82 100644 --- a/libc-top-half/musl/src/exit/assert.c +++ b/libc-top-half/musl/src/exit/assert.c @@ -4,6 +4,5 @@ _Noreturn void __assert_fail(const char *expr, const char *file, int line, const char *func) { fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line); - fflush(NULL); abort(); } diff --git a/libc-top-half/musl/src/exit/at_quick_exit.c b/libc-top-half/musl/src/exit/at_quick_exit.c index d3ce652..429d0b0 100644 --- a/libc-top-half/musl/src/exit/at_quick_exit.c +++ b/libc-top-half/musl/src/exit/at_quick_exit.c @@ -1,12 +1,16 @@ #include #include "libc.h" #include "lock.h" +#include "fork_impl.h" #define COUNT 32 static void (*funcs[COUNT])(void); static int count; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) static volatile int lock[1]; +volatile int *const __at_quick_exit_lockptr = lock; +#endif void __funcs_on_quick_exit() { diff --git a/libc-top-half/musl/src/exit/atexit.c b/libc-top-half/musl/src/exit/atexit.c index 160d277..155292d 100644 --- a/libc-top-half/musl/src/exit/atexit.c +++ b/libc-top-half/musl/src/exit/atexit.c @@ -2,6 +2,12 @@ #include #include "libc.h" #include "lock.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc undef +#define free undef /* Ensure that at least 32 atexit handlers can be registered without malloc */ #define COUNT 32 @@ -14,7 +20,11 @@ static struct fl } builtin, *head; static int slot; + +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) static volatile int lock[1]; +volatile int *const __atexit_lockptr = lock; +#endif void __funcs_on_exit() { diff --git a/libc-top-half/musl/src/include/stdlib.h b/libc-top-half/musl/src/include/stdlib.h index d38a541..e9da201 100644 --- a/libc-top-half/musl/src/include/stdlib.h +++ b/libc-top-half/musl/src/include/stdlib.h @@ -9,4 +9,10 @@ hidden int __mkostemps(char *, int, int); hidden int __ptsname_r(int, char *, size_t); hidden char *__randname(char *); +hidden void *__libc_malloc(size_t); +hidden void *__libc_malloc_impl(size_t); +hidden void *__libc_calloc(size_t, size_t); +hidden void *__libc_realloc(void *, size_t); +hidden void __libc_free(void *); + #endif diff --git a/libc-top-half/musl/src/include/unistd.h b/libc-top-half/musl/src/include/unistd.h index f372afe..d02206e 100644 --- a/libc-top-half/musl/src/include/unistd.h +++ b/libc-top-half/musl/src/include/unistd.h @@ -15,7 +15,6 @@ extern char **__environ; hidden int __dup3(int, int, int); hidden int __mkostemps(char *, int, int); hidden int __execvpe(const char *, char *const *, char *const *); -hidden int __aio_close(int); hidden off_t __lseek(int, off_t, int); #endif diff --git a/libc-top-half/musl/src/internal/aio_impl.h b/libc-top-half/musl/src/internal/aio_impl.h new file mode 100644 index 0000000..a865766 --- /dev/null +++ b/libc-top-half/musl/src/internal/aio_impl.h @@ -0,0 +1,9 @@ +#ifndef AIO_IMPL_H +#define AIO_IMPL_H + +extern hidden volatile int __aio_fut; + +extern hidden int __aio_close(int); +extern hidden void __aio_atfork(int); + +#endif diff --git a/libc-top-half/musl/src/internal/fork_impl.h b/libc-top-half/musl/src/internal/fork_impl.h new file mode 100644 index 0000000..f6b3aa0 --- /dev/null +++ b/libc-top-half/musl/src/internal/fork_impl.h @@ -0,0 +1,21 @@ +#include + +#ifdef __wasilibc_unmodified_upstream +extern hidden volatile int *const __at_quick_exit_lockptr; +extern hidden volatile int *const __atexit_lockptr; +extern hidden volatile int *const __dlerror_lockptr; +extern hidden volatile int *const __gettext_lockptr; +extern hidden volatile int *const __locale_lockptr; +extern hidden volatile int *const __random_lockptr; +extern hidden volatile int *const __sem_open_lockptr; +extern hidden volatile int *const __stdio_ofl_lockptr; +extern hidden volatile int *const __syslog_lockptr; +extern hidden volatile int *const __timezone_lockptr; + +extern hidden volatile int *const __bump_lockptr; + +extern hidden volatile int *const __vmlock_lockptr; + +hidden void __malloc_atfork(int); +hidden void __ldso_atfork(int); +#endif diff --git a/libc-top-half/musl/src/internal/libm.h b/libc-top-half/musl/src/internal/libm.h index a45894b..2b06ac4 100644 --- a/libc-top-half/musl/src/internal/libm.h +++ b/libc-top-half/musl/src/internal/libm.h @@ -285,5 +285,8 @@ hidden double __math_uflow(uint32_t); hidden double __math_oflow(uint32_t); hidden double __math_divzero(uint32_t); hidden double __math_invalid(double); +#if LDBL_MANT_DIG != DBL_MANT_DIG +hidden long double __math_invalidl(long double); +#endif #endif diff --git a/libc-top-half/musl/src/internal/locale_impl.h b/libc-top-half/musl/src/internal/locale_impl.h index 228ca64..7f79b7f 100644 --- a/libc-top-half/musl/src/internal/locale_impl.h +++ b/libc-top-half/musl/src/internal/locale_impl.h @@ -17,6 +17,10 @@ struct __locale_map { const struct __locale_map *next; }; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +extern hidden volatile int __locale_lock[1]; +#endif + extern hidden const struct __locale_map __c_dot_utf8; extern hidden const struct __locale_struct __c_locale; extern hidden const struct __locale_struct __c_dot_utf8_locale; diff --git a/libc-top-half/musl/src/internal/lock.h b/libc-top-half/musl/src/internal/lock.h index 37115e6..29787fb 100644 --- a/libc-top-half/musl/src/internal/lock.h +++ b/libc-top-half/musl/src/internal/lock.h @@ -8,8 +8,8 @@ hidden void __unlock(volatile int *); #define UNLOCK(x) __unlock(x) #else // No locking needed. -#define LOCK(x) ((void)(x)) -#define UNLOCK(x) ((void)(x)) +#define LOCK(x) ((void)0) +#define UNLOCK(x) ((void)0) #endif #endif diff --git a/libc-top-half/musl/src/internal/pthread_impl.h b/libc-top-half/musl/src/internal/pthread_impl.h index 5742dfc..de2b9d8 100644 --- a/libc-top-half/musl/src/internal/pthread_impl.h +++ b/libc-top-half/musl/src/internal/pthread_impl.h @@ -11,16 +11,25 @@ #include "atomic.h" #include "futex.h" +#include "pthread_arch.h" + #define pthread __pthread struct pthread { /* Part 1 -- these fields may be external or * internal (accessed via asm) ABI. Do not change. */ struct pthread *self; +#ifndef TLS_ABOVE_TP uintptr_t *dtv; +#endif struct pthread *prev, *next; /* non-ABI */ uintptr_t sysinfo; - uintptr_t canary, canary2; +#ifndef TLS_ABOVE_TP +#ifdef CANARY_PAD + uintptr_t canary_pad; +#endif + uintptr_t canary; +#endif /* Part 2 -- implementation details, non-ABI. */ int tid; @@ -43,6 +52,7 @@ struct pthread { long off; volatile void *volatile pending; } robust_list; + int h_errno_val; volatile int timer_id; locale_t locale; volatile int killlock[1]; @@ -51,21 +61,19 @@ struct pthread { /* Part 3 -- the positions of these fields relative to * the end of the structure is external and internal ABI. */ - uintptr_t canary_at_end; - uintptr_t *dtv_copy; +#ifdef TLS_ABOVE_TP + uintptr_t canary; + uintptr_t *dtv; +#endif }; enum { - DT_EXITING = 0, + DT_EXITED = 0, + DT_EXITING, DT_JOINABLE, DT_DETACHED, }; -struct __timer { - int timerid; - pthread_t thread; -}; - #define __SU (sizeof(size_t)/sizeof(int)) #define _a_stacksize __u.__s[0] @@ -98,16 +106,22 @@ struct __timer { #define _b_waiters2 __u.__vi[4] #define _b_inst __u.__p[3] -#include "pthread_arch.h" - -#ifndef CANARY -#define CANARY canary +#ifndef TP_OFFSET +#define TP_OFFSET 0 #endif #ifndef DTP_OFFSET #define DTP_OFFSET 0 #endif +#ifdef TLS_ABOVE_TP +#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + TP_OFFSET) +#define __pthread_self() ((pthread_t)(__get_tp() - sizeof(struct __pthread) - TP_OFFSET)) +#else +#define TP_ADJ(p) (p) +#define __pthread_self() ((pthread_t)__get_tp()) +#endif + #ifndef tls_mod_off_t #define tls_mod_off_t size_t #endif @@ -141,7 +155,6 @@ hidden int __pthread_key_delete_impl(pthread_key_t); extern hidden volatile size_t __pthread_tsd_size; extern hidden void *__pthread_tsd_main[]; -extern hidden volatile int __aio_fut; extern hidden volatile int __eintr_valid_flag; hidden int __clone(int (*)(void *), void *, int, void *, ...); @@ -176,6 +189,8 @@ hidden void __tl_sync(pthread_t); extern hidden volatile int __thread_list_lock; +extern hidden volatile int __abort_lock[1]; + extern hidden unsigned __default_stacksize; extern hidden unsigned __default_guardsize; diff --git a/libc-top-half/musl/src/internal/stdio_impl.h b/libc-top-half/musl/src/internal/stdio_impl.h index 4167ba7..7f19dd9 100644 --- a/libc-top-half/musl/src/internal/stdio_impl.h +++ b/libc-top-half/musl/src/internal/stdio_impl.h @@ -2,7 +2,9 @@ #define _STDIO_IMPL_H #include +#if defined(__wasilibc_unmodified_upstream) #include "syscall.h" +#endif #define UNGET 8 diff --git a/libc-top-half/musl/src/internal/syscall.h b/libc-top-half/musl/src/internal/syscall.h index 975a003..d5f294d 100644 --- a/libc-top-half/musl/src/internal/syscall.h +++ b/libc-top-half/musl/src/internal/syscall.h @@ -2,6 +2,7 @@ #define _INTERNAL_SYSCALL_H #include +#include #include #include "syscall_arch.h" @@ -57,15 +58,22 @@ hidden long __syscall_ret(unsigned long), #define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) #define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) -#ifndef SYSCALL_USE_SOCKETCALL -#define __socketcall(nm,a,b,c,d,e,f) __syscall(SYS_##nm, a, b, c, d, e, f) -#define __socketcall_cp(nm,a,b,c,d,e,f) __syscall_cp(SYS_##nm, a, b, c, d, e, f) -#else -#define __socketcall(nm,a,b,c,d,e,f) __syscall(SYS_socketcall, __SC_##nm, \ - ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f })) -#define __socketcall_cp(nm,a,b,c,d,e,f) __syscall_cp(SYS_socketcall, __SC_##nm, \ - ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f })) +static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, long c, long d, long e, long f) +{ + long r; + if (cp) r = __syscall_cp(sys, a, b, c, d, e, f); + else r = __syscall(sys, a, b, c, d, e, f); + if (r != -ENOSYS) return r; +#ifdef SYS_socketcall + if (cp) r = __syscall_cp(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f})); + else r = __syscall(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f})); #endif + return r; +} +#define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \ + (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) +#define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \ + (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) /* fixup legacy 16-bit junk */ @@ -338,6 +346,12 @@ hidden long __syscall_ret(unsigned long), #define __SC_recvmmsg 19 #define __SC_sendmmsg 20 +/* This is valid only because all socket syscalls are made via + * socketcall, which always fills unused argument slots with zeros. */ +#ifndef SYS_accept +#define SYS_accept SYS_accept4 +#endif + #ifndef SO_RCVTIMEO_OLD #define SO_RCVTIMEO_OLD 20 #endif diff --git a/libc-top-half/musl/src/ldso/dlerror.c b/libc-top-half/musl/src/ldso/dlerror.c index 3fcc777..afe5925 100644 --- a/libc-top-half/musl/src/ldso/dlerror.c +++ b/libc-top-half/musl/src/ldso/dlerror.c @@ -4,6 +4,12 @@ #include "pthread_impl.h" #include "dynlink.h" #include "lock.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc __libc_realloc +#define free __libc_free char *dlerror() { @@ -19,6 +25,7 @@ char *dlerror() static volatile int freebuf_queue_lock[1]; static void **freebuf_queue; +volatile int *const __dlerror_lockptr = freebuf_queue_lock; void __dl_thread_cleanup(void) { @@ -35,13 +42,16 @@ void __dl_thread_cleanup(void) hidden void __dl_vseterr(const char *fmt, va_list ap) { LOCK(freebuf_queue_lock); - while (freebuf_queue) { - void **p = freebuf_queue; - freebuf_queue = *p; - free(p); - } + void **q = freebuf_queue; + freebuf_queue = 0; UNLOCK(freebuf_queue_lock); + while (q) { + void **p = *q; + free(q); + q = p; + } + va_list ap2; va_copy(ap2, ap); pthread_t self = __pthread_self(); diff --git a/libc-top-half/musl/src/legacy/lutimes.c b/libc-top-half/musl/src/legacy/lutimes.c index 2e5502d..dd46592 100644 --- a/libc-top-half/musl/src/legacy/lutimes.c +++ b/libc-top-half/musl/src/legacy/lutimes.c @@ -6,9 +6,11 @@ int lutimes(const char *filename, const struct timeval tv[2]) { struct timespec times[2]; - times[0].tv_sec = tv[0].tv_sec; - times[0].tv_nsec = tv[0].tv_usec * 1000; - times[1].tv_sec = tv[1].tv_sec; - times[1].tv_nsec = tv[1].tv_usec * 1000; - return utimensat(AT_FDCWD, filename, times, AT_SYMLINK_NOFOLLOW); + if (tv) { + times[0].tv_sec = tv[0].tv_sec; + times[0].tv_nsec = tv[0].tv_usec * 1000; + times[1].tv_sec = tv[1].tv_sec; + times[1].tv_nsec = tv[1].tv_usec * 1000; + } + return utimensat(AT_FDCWD, filename, tv ? times : 0, AT_SYMLINK_NOFOLLOW); } diff --git a/libc-top-half/musl/src/linux/gettid.c b/libc-top-half/musl/src/linux/gettid.c new file mode 100644 index 0000000..7076713 --- /dev/null +++ b/libc-top-half/musl/src/linux/gettid.c @@ -0,0 +1,8 @@ +#define _GNU_SOURCE +#include +#include "pthread_impl.h" + +pid_t gettid(void) +{ + return __pthread_self()->tid; +} diff --git a/libc-top-half/musl/src/linux/membarrier.c b/libc-top-half/musl/src/linux/membarrier.c index 9ebe906..343f736 100644 --- a/libc-top-half/musl/src/linux/membarrier.c +++ b/libc-top-half/musl/src/linux/membarrier.c @@ -9,13 +9,8 @@ static void dummy_0(void) { } -static void dummy_1(pthread_t t) -{ -} - weak_alias(dummy_0, __tl_lock); weak_alias(dummy_0, __tl_unlock); -weak_alias(dummy_1, __tl_sync); static sem_t barrier_sem; diff --git a/libc-top-half/musl/src/linux/setgroups.c b/libc-top-half/musl/src/linux/setgroups.c index 1248fdb..47142f1 100644 --- a/libc-top-half/musl/src/linux/setgroups.c +++ b/libc-top-half/musl/src/linux/setgroups.c @@ -1,8 +1,36 @@ #define _GNU_SOURCE #include +#include #include "syscall.h" +#include "libc.h" + +struct ctx { + size_t count; + const gid_t *list; + int ret; +}; + +static void do_setgroups(void *p) +{ + struct ctx *c = p; + if (c->ret<0) return; + int ret = __syscall(SYS_setgroups, c->count, c->list); + if (ret && !c->ret) { + /* If one thread fails to set groups after another has already + * succeeded, forcibly killing the process is the only safe + * thing to do. State is inconsistent and dangerous. Use + * SIGKILL because it is uncatchable. */ + __block_all_sigs(0); + __syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL); + } + c->ret = ret; +} int setgroups(size_t count, const gid_t list[]) { - return syscall(SYS_setgroups, count, list); + /* ret is initially nonzero so that failure of the first thread does not + * trigger the safety kill above. */ + struct ctx c = { .count = count, .list = list, .ret = 1 }; + __synccall(do_setgroups, &c); + return __syscall_ret(c.ret); } diff --git a/libc-top-half/musl/src/locale/dcngettext.c b/libc-top-half/musl/src/locale/dcngettext.c index 4c30439..d1e6c6d 100644 --- a/libc-top-half/musl/src/locale/dcngettext.c +++ b/libc-top-half/musl/src/locale/dcngettext.c @@ -10,6 +10,12 @@ #include "atomic.h" #include "pleval.h" #include "lock.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc undef +#define free undef struct binding { struct binding *next; @@ -34,9 +40,11 @@ static char *gettextdir(const char *domainname, size_t *dirlen) return 0; } +static volatile int lock[1]; +volatile int *const __gettext_lockptr = lock; + char *bindtextdomain(const char *domainname, const char *dirname) { - static volatile int lock[1]; struct binding *p, *q; if (!domainname) return 0; diff --git a/libc-top-half/musl/src/locale/freelocale.c b/libc-top-half/musl/src/locale/freelocale.c index 802b8bf..385d120 100644 --- a/libc-top-half/musl/src/locale/freelocale.c +++ b/libc-top-half/musl/src/locale/freelocale.c @@ -1,6 +1,11 @@ #include #include "locale_impl.h" +#define malloc undef +#define calloc undef +#define realloc undef +#define free __libc_free + void freelocale(locale_t l) { if (__loc_is_allocated(l)) free(l); diff --git a/libc-top-half/musl/src/locale/locale_map.c b/libc-top-half/musl/src/locale/locale_map.c index ff9ae98..ebfb158 100644 --- a/libc-top-half/musl/src/locale/locale_map.c +++ b/libc-top-half/musl/src/locale/locale_map.c @@ -3,9 +3,16 @@ #ifdef __wasilibc_unmodified_upstream // WASI has no mmap #include #endif +#include #include "locale_impl.h" #include "libc.h" #include "lock.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef const char *__lctrans_impl(const char *msg, const struct __locale_map *lm) { @@ -23,9 +30,13 @@ static const char envvars[][12] = { "LC_MESSAGES", }; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) +volatile int __locale_lock[1]; +volatile int *const __locale_lockptr = __locale_lock; +#endif + const struct __locale_map *__get_locale(int cat, const char *val) { - static volatile int lock[1]; static void *volatile loc_head; const struct __locale_map *p; struct __locale_map *new = 0; @@ -56,21 +67,13 @@ const struct __locale_map *__get_locale(int cat, const char *val) for (p=loc_head; p; p=p->next) if (!strcmp(val, p->name)) return p; - LOCK(lock); - - for (p=loc_head; p; p=p->next) - if (!strcmp(val, p->name)) { - UNLOCK(lock); - return p; - } - #ifdef __wasilibc_unmodified_upstream // WASI has no mmap, though this code could be made to use something else if (!libc.secure) path = getenv("MUSL_LOCPATH"); /* FIXME: add a default path? */ if (path) for (; *path; path=z+!!*z) { z = __strchrnul(path, ':'); - l = z - path - !!*z; + l = z - path; if (l >= sizeof buf - n - 2) continue; memcpy(buf, path, l); buf[l] = '/'; @@ -112,6 +115,5 @@ const struct __locale_map *__get_locale(int cat, const char *val) * requested name was "C" or "POSIX". */ if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8; - UNLOCK(lock); return new; } diff --git a/libc-top-half/musl/src/locale/newlocale.c b/libc-top-half/musl/src/locale/newlocale.c index be8fe44..11c7785 100644 --- a/libc-top-half/musl/src/locale/newlocale.c +++ b/libc-top-half/musl/src/locale/newlocale.c @@ -4,26 +4,23 @@ #include #endif #include "locale_impl.h" +#include "lock.h" -#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) -static pthread_once_t default_locale_once; -#endif +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef + +static int default_locale_init_done; static struct __locale_struct default_locale, default_ctype_locale; -static void default_locale_init(void) -{ - for (int i=0; i LC_ALL) return 0; - LOCK(lock); + LOCK(__locale_lock); /* For LC_ALL, setlocale is required to return a string which * encodes the current setting for all categories. The format of @@ -36,7 +35,7 @@ char *setlocale(int cat, const char *name) } lm = __get_locale(i, part); if (lm == LOC_MAP_FAILED) { - UNLOCK(lock); + UNLOCK(__locale_lock); return 0; } tmp_locale.cat[i] = lm; @@ -57,14 +56,14 @@ char *setlocale(int cat, const char *name) s += l+1; } *--s = 0; - UNLOCK(lock); + UNLOCK(__locale_lock); return same==LC_ALL ? (char *)part : buf; } if (name) { lm = __get_locale(cat, name); if (lm == LOC_MAP_FAILED) { - UNLOCK(lock); + UNLOCK(__locale_lock); return 0; } libc.global_locale.cat[cat] = lm; @@ -73,7 +72,7 @@ char *setlocale(int cat, const char *name) } char *ret = lm ? (char *)lm->name : "C"; - UNLOCK(lock); + UNLOCK(__locale_lock); return ret; } diff --git a/libc-top-half/musl/src/malloc/free.c b/libc-top-half/musl/src/malloc/free.c new file mode 100644 index 0000000..f17a952 --- /dev/null +++ b/libc-top-half/musl/src/malloc/free.c @@ -0,0 +1,6 @@ +#include + +void free(void *p) +{ + return __libc_free(p); +} diff --git a/libc-top-half/musl/src/malloc/libc_calloc.c b/libc-top-half/musl/src/malloc/libc_calloc.c new file mode 100644 index 0000000..d25eabe --- /dev/null +++ b/libc-top-half/musl/src/malloc/libc_calloc.c @@ -0,0 +1,4 @@ +#define calloc __libc_calloc +#define malloc __libc_malloc + +#include "calloc.c" diff --git a/libc-top-half/musl/src/malloc/lite_malloc.c b/libc-top-half/musl/src/malloc/lite_malloc.c index f8931ba..43a988f 100644 --- a/libc-top-half/musl/src/malloc/lite_malloc.c +++ b/libc-top-half/musl/src/malloc/lite_malloc.c @@ -6,6 +6,7 @@ #include "libc.h" #include "lock.h" #include "syscall.h" +#include "fork_impl.h" #define ALIGN 16 @@ -31,10 +32,12 @@ static int traverses_stack_p(uintptr_t old, uintptr_t new) return 0; } +static volatile int lock[1]; +volatile int *const __bump_lockptr = lock; + static void *__simple_malloc(size_t n) { static uintptr_t brk, cur, end; - static volatile int lock[1]; static unsigned mmap_step; size_t align=1; void *p; @@ -100,4 +103,16 @@ static void *__simple_malloc(size_t n) return p; } -weak_alias(__simple_malloc, malloc); +weak_alias(__simple_malloc, __libc_malloc_impl); + +void *__libc_malloc(size_t n) +{ + return __libc_malloc_impl(n); +} + +static void *default_malloc(size_t n) +{ + return __libc_malloc_impl(n); +} + +weak_alias(default_malloc, malloc); diff --git a/libc-top-half/musl/src/malloc/mallocng/glue.h b/libc-top-half/musl/src/malloc/mallocng/glue.h index 16acd1e..151c48b 100644 --- a/libc-top-half/musl/src/malloc/mallocng/glue.h +++ b/libc-top-half/musl/src/malloc/mallocng/glue.h @@ -20,6 +20,10 @@ #define is_allzero __malloc_allzerop #define dump_heap __dump_heap +#define malloc __libc_malloc_impl +#define realloc __libc_realloc +#define free __libc_free + #if USE_REAL_ASSERT #include #else @@ -56,7 +60,8 @@ __attribute__((__visibility__("hidden"))) extern int __malloc_lock[1]; #define LOCK_OBJ_DEF \ -int __malloc_lock[1]; +int __malloc_lock[1]; \ +void __malloc_atfork(int who) { malloc_atfork(who); } static inline void rdlock() { @@ -73,5 +78,16 @@ static inline void unlock() static inline void upgradelock() { } +static inline void resetlock() +{ + __malloc_lock[0] = 0; +} + +static inline void malloc_atfork(int who) +{ + if (who<0) rdlock(); + else if (who>0) resetlock(); + else unlock(); +} #endif diff --git a/libc-top-half/musl/src/malloc/mallocng/malloc_usable_size.c b/libc-top-half/musl/src/malloc/mallocng/malloc_usable_size.c index a440a4e..ce6a960 100644 --- a/libc-top-half/musl/src/malloc/mallocng/malloc_usable_size.c +++ b/libc-top-half/musl/src/malloc/mallocng/malloc_usable_size.c @@ -3,6 +3,7 @@ size_t malloc_usable_size(void *p) { + if (!p) return 0; struct meta *g = get_meta(p); int idx = get_slot_index(p); size_t stride = get_stride(g); diff --git a/libc-top-half/musl/src/malloc/oldmalloc/malloc.c b/libc-top-half/musl/src/malloc/oldmalloc/malloc.c index c0997ad..53f5f95 100644 --- a/libc-top-half/musl/src/malloc/oldmalloc/malloc.c +++ b/libc-top-half/musl/src/malloc/oldmalloc/malloc.c @@ -9,6 +9,11 @@ #include "atomic.h" #include "pthread_impl.h" #include "malloc_impl.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define realloc __libc_realloc +#define free __libc_free #if defined(__GNUC__) && defined(__PIC__) #define inline inline __attribute__((always_inline)) @@ -527,3 +532,21 @@ void __malloc_donate(char *start, char *end) c->csize = n->psize = C_INUSE | (end-start); __bin_chunk(c); } + +void __malloc_atfork(int who) +{ + if (who<0) { + lock(mal.split_merge_lock); + for (int i=0; i<64; i++) + lock(mal.bins[i].lock); + } else if (!who) { + for (int i=0; i<64; i++) + unlock(mal.bins[i].lock); + unlock(mal.split_merge_lock); + } else { + for (int i=0; i<64; i++) + mal.bins[i].lock[0] = mal.bins[i].lock[1] = 0; + mal.split_merge_lock[1] = 0; + mal.split_merge_lock[0] = 0; + } +} diff --git a/libc-top-half/musl/src/malloc/realloc.c b/libc-top-half/musl/src/malloc/realloc.c new file mode 100644 index 0000000..fb0e8b7 --- /dev/null +++ b/libc-top-half/musl/src/malloc/realloc.c @@ -0,0 +1,6 @@ +#include + +void *realloc(void *p, size_t n) +{ + return __libc_realloc(p, n); +} diff --git a/libc-top-half/musl/src/malloc/reallocarray.c b/libc-top-half/musl/src/malloc/reallocarray.c new file mode 100644 index 0000000..4a6ebe4 --- /dev/null +++ b/libc-top-half/musl/src/malloc/reallocarray.c @@ -0,0 +1,13 @@ +#define _BSD_SOURCE +#include +#include + +void *reallocarray(void *ptr, size_t m, size_t n) +{ + if (n && m > -1 / n) { + errno = ENOMEM; + return 0; + } + + return realloc(ptr, m * n); +} diff --git a/libc-top-half/musl/src/math/__math_invalidl.c b/libc-top-half/musl/src/math/__math_invalidl.c new file mode 100644 index 0000000..1fca99d --- /dev/null +++ b/libc-top-half/musl/src/math/__math_invalidl.c @@ -0,0 +1,9 @@ +#include +#include "libm.h" + +#if LDBL_MANT_DIG != DBL_MANT_DIG +long double __math_invalidl(long double x) +{ + return (x - x) / (x - x); +} +#endif diff --git a/libc-top-half/musl/src/math/arm/fabs.c b/libc-top-half/musl/src/math/arm/fabs.c index f890520..6e1d367 100644 --- a/libc-top-half/musl/src/math/arm/fabs.c +++ b/libc-top-half/musl/src/math/arm/fabs.c @@ -1,6 +1,6 @@ #include -#if __ARM_PCS_VFP +#if __ARM_PCS_VFP && __ARM_FP&8 double fabs(double x) { diff --git a/libc-top-half/musl/src/math/arm/sqrt.c b/libc-top-half/musl/src/math/arm/sqrt.c index 874af96..567e2e9 100644 --- a/libc-top-half/musl/src/math/arm/sqrt.c +++ b/libc-top-half/musl/src/math/arm/sqrt.c @@ -1,6 +1,6 @@ #include -#if __ARM_PCS_VFP || (__VFP_FP__ && !__SOFTFP__) +#if (__ARM_PCS_VFP || (__VFP_FP__ && !__SOFTFP__)) && (__ARM_FP&8) double sqrt(double x) { diff --git a/libc-top-half/musl/src/math/sinh.c b/libc-top-half/musl/src/math/sinh.c index 8463abc..c8dda8d 100644 --- a/libc-top-half/musl/src/math/sinh.c +++ b/libc-top-half/musl/src/math/sinh.c @@ -37,7 +37,7 @@ double sinh(double x) #ifdef __wasilibc_unmodified_upstream // Wasm doesn't have alternate rounding modes t = __expo2(absx, 2*h); #else - t = __expo2(absx); + t = 2*h*__expo2(absx); #endif return t; } diff --git a/libc-top-half/musl/src/math/sinhf.c b/libc-top-half/musl/src/math/sinhf.c index 1fcd27a..3ac49e2 100644 --- a/libc-top-half/musl/src/math/sinhf.c +++ b/libc-top-half/musl/src/math/sinhf.c @@ -29,7 +29,7 @@ float sinhf(float x) #ifdef __wasilibc_unmodified_upstream // Wasm doesn't have alternate rounding modes t = __expo2f(absx, 2*h); #else - t = __expo2f(absx); + t = 2*h*__expo2f(absx); #endif return t; } diff --git a/libc-top-half/musl/src/math/sqrt.c b/libc-top-half/musl/src/math/sqrt.c index f1f6d76..5ba2655 100644 --- a/libc-top-half/musl/src/math/sqrt.c +++ b/libc-top-half/musl/src/math/sqrt.c @@ -1,184 +1,158 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* sqrt(x) - * Return correctly rounded sqrt. - * ------------------------------------------ - * | Use the hardware sqrt if you have one | - * ------------------------------------------ - * Method: - * Bit by bit method using integer arithmetic. (Slow, but portable) - * 1. Normalization - * Scale x to y in [1,4) with even powers of 2: - * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then - * sqrt(x) = 2^k * sqrt(y) - * 2. Bit by bit computation - * Let q = sqrt(y) truncated to i bit after binary point (q = 1), - * i 0 - * i+1 2 - * s = 2*q , and y = 2 * ( y - q ). (1) - * i i i i - * - * To compute q from q , one checks whether - * i+1 i - * - * -(i+1) 2 - * (q + 2 ) <= y. (2) - * i - * -(i+1) - * If (2) is false, then q = q ; otherwise q = q + 2 . - * i+1 i i+1 i - * - * With some algebric manipulation, it is not difficult to see - * that (2) is equivalent to - * -(i+1) - * s + 2 <= y (3) - * i i - * - * The advantage of (3) is that s and y can be computed by - * i i - * the following recurrence formula: - * if (3) is false - * - * s = s , y = y ; (4) - * i+1 i i+1 i - * - * otherwise, - * -i -(i+1) - * s = s + 2 , y = y - s - 2 (5) - * i+1 i i+1 i i - * - * One may easily use induction to prove (4) and (5). - * Note. Since the left hand side of (3) contain only i+2 bits, - * it does not necessary to do a full (53-bit) comparison - * in (3). - * 3. Final rounding - * After generating the 53 bits result, we compute one more bit. - * Together with the remainder, we can decide whether the - * result is exact, bigger than 1/2ulp, or less than 1/2ulp - * (it will never equal to 1/2ulp). - * The rounding mode can be detected by checking whether - * huge + tiny is equal to huge, and whether huge - tiny is - * equal to huge for some floating point number "huge" and "tiny". - * - * Special cases: - * sqrt(+-0) = +-0 ... exact - * sqrt(inf) = inf - * sqrt(-ve) = NaN ... with invalid signal - * sqrt(NaN) = NaN ... with invalid signal for signaling NaN - */ - +#include +#include #include "libm.h" +#include "sqrt_data.h" -static const double tiny = 1.0e-300; +#define FENV_SUPPORT 1 + +/* returns a*b*2^-32 - e, with error 0 <= e < 1. */ +static inline uint32_t mul32(uint32_t a, uint32_t b) +{ + return (uint64_t)a*b >> 32; +} + +/* returns a*b*2^-64 - e, with error 0 <= e < 3. */ +static inline uint64_t mul64(uint64_t a, uint64_t b) +{ + uint64_t ahi = a>>32; + uint64_t alo = a&0xffffffff; + uint64_t bhi = b>>32; + uint64_t blo = b&0xffffffff; + return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32); +} double sqrt(double x) { - double z; - int32_t sign = (int)0x80000000; - int32_t ix0,s0,q,m,t,i; - uint32_t r,t1,s1,ix1,q1; + uint64_t ix, top, m; - EXTRACT_WORDS(ix0, ix1, x); - - /* take care of Inf and NaN */ - if ((ix0&0x7ff00000) == 0x7ff00000) { - return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ - } - /* take care of zero */ - if (ix0 <= 0) { - if (((ix0&~sign)|ix1) == 0) - return x; /* sqrt(+-0) = +-0 */ - if (ix0 < 0) - return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = ix0>>20; - if (m == 0) { /* subnormal x */ - while (ix0 == 0) { - m -= 21; - ix0 |= (ix1>>11); - ix1 <<= 21; - } - for (i=0; (ix0&0x00100000) == 0; i++) - ix0<<=1; - m -= i - 1; - ix0 |= ix1>>(32-i); - ix1 <<= i; - } - m -= 1023; /* unbias exponent */ - ix0 = (ix0&0x000fffff)|0x00100000; - if (m & 1) { /* odd m, double x to make it even */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - } - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ - r = 0x00200000; /* r = moving bit from right to left */ - - while (r != 0) { - t = s0 + r; - if (t <= ix0) { - s0 = t + r; - ix0 -= t; - q += r; - } - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - r >>= 1; + /* special case handling. */ + ix = asuint64(x); + top = ix >> 52; + if (predict_false(top - 0x001 >= 0x7ff - 0x001)) { + /* x < 0x1p-1022 or inf or nan. */ + if (ix * 2 == 0) + return x; + if (ix == 0x7ff0000000000000) + return x; + if (ix > 0x7ff0000000000000) + return __math_invalid(x); + /* x is subnormal, normalize it. */ + ix = asuint64(x * 0x1p52); + top = ix >> 52; + top -= 52; } - r = sign; - while (r != 0) { - t1 = s1 + r; - t = s0; - if (t < ix0 || (t == ix0 && t1 <= ix1)) { - s1 = t1 + r; - if ((t1&sign) == sign && (s1&sign) == 0) - s0++; - ix0 -= t; - if (ix1 < t1) - ix0--; - ix1 -= t1; - q1 += r; - } - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - r >>= 1; - } + /* argument reduction: + x = 4^e m; with integer e, and m in [1, 4) + m: fixed point representation [2.62] + 2^e is the exponent part of the result. */ + int even = top & 1; + m = (ix << 11) | 0x8000000000000000; + if (even) m >>= 1; + top = (top + 0x3ff) >> 1; - /* use floating add to find out rounding direction */ - if ((ix0|ix1) != 0) { - z = 1.0 - tiny; /* raise inexact flag */ - if (z >= 1.0) { - z = 1.0 + tiny; - if (q1 == (uint32_t)0xffffffff) { - q1 = 0; - q++; - } else if (z > 1.0) { - if (q1 == (uint32_t)0xfffffffe) - q++; - q1 += 2; - } else - q1 += q1 & 1; - } + /* approximate r ~ 1/sqrt(m) and s ~ sqrt(m) when m in [1,4) + + initial estimate: + 7bit table lookup (1bit exponent and 6bit significand). + + iterative approximation: + using 2 goldschmidt iterations with 32bit int arithmetics + and a final iteration with 64bit int arithmetics. + + details: + + the relative error (e = r0 sqrt(m)-1) of a linear estimate + (r0 = a m + b) is |e| < 0.085955 ~ 0x1.6p-4 at best, + a table lookup is faster and needs one less iteration + 6 bit lookup table (128b) gives |e| < 0x1.f9p-8 + 7 bit lookup table (256b) gives |e| < 0x1.fdp-9 + for single and double prec 6bit is enough but for quad + prec 7bit is needed (or modified iterations). to avoid + one more iteration >=13bit table would be needed (16k). + + a newton-raphson iteration for r is + w = r*r + u = 3 - m*w + r = r*u/2 + can use a goldschmidt iteration for s at the end or + s = m*r + + first goldschmidt iteration is + s = m*r + u = 3 - s*r + r = r*u/2 + s = s*u/2 + next goldschmidt iteration is + u = 3 - s*r + r = r*u/2 + s = s*u/2 + and at the end r is not computed only s. + + they use the same amount of operations and converge at the + same quadratic rate, i.e. if + r1 sqrt(m) - 1 = e, then + r2 sqrt(m) - 1 = -3/2 e^2 - 1/2 e^3 + the advantage of goldschmidt is that the mul for s and r + are independent (computed in parallel), however it is not + "self synchronizing": it only uses the input m in the + first iteration so rounding errors accumulate. at the end + or when switching to larger precision arithmetics rounding + errors dominate so the first iteration should be used. + + the fixed point representations are + m: 2.30 r: 0.32, s: 2.30, d: 2.30, u: 2.30, three: 2.30 + and after switching to 64 bit + m: 2.62 r: 0.64, s: 2.62, d: 2.62, u: 2.62, three: 2.62 */ + + static const uint64_t three = 0xc0000000; + uint64_t r, s, d, u, i; + + i = (ix >> 46) % 128; + r = (uint32_t)__rsqrt_tab[i] << 16; + /* |r sqrt(m) - 1| < 0x1.fdp-9 */ + s = mul32(m>>32, r); + /* |s/sqrt(m) - 1| < 0x1.fdp-9 */ + d = mul32(s, r); + u = three - d; + r = mul32(r, u) << 1; + /* |r sqrt(m) - 1| < 0x1.7bp-16 */ + s = mul32(s, u) << 1; + /* |s/sqrt(m) - 1| < 0x1.7bp-16 */ + d = mul32(s, r); + u = three - d; + r = mul32(r, u) << 1; + /* |r sqrt(m) - 1| < 0x1.3704p-29 (measured worst-case) */ + r = r << 32; + s = mul64(m, r); + d = mul64(s, r); + u = (three<<32) - d; + s = mul64(s, u); /* repr: 3.61 */ + /* -0x1p-57 < s - sqrt(m) < 0x1.8001p-61 */ + s = (s - 2) >> 9; /* repr: 12.52 */ + /* -0x1.09p-52 < s - sqrt(m) < -0x1.fffcp-63 */ + + /* s < sqrt(m) < s + 0x1.09p-52, + compute nearest rounded result: + the nearest result to 52 bits is either s or s+0x1p-52, + we can decide by comparing (2^52 s + 0.5)^2 to 2^104 m. */ + uint64_t d0, d1, d2; + double y, t; + d0 = (m << 42) - s*s; + d1 = s - d0; + d2 = d1 + s + 1; + s += d1 >> 63; + s &= 0x000fffffffffffff; + s |= top << 52; + y = asdouble(s); + if (FENV_SUPPORT) { + /* handle rounding modes and inexact exception: + only (s+1)^2 == 2^42 m case is exact otherwise + add a tiny value to cause the fenv effects. */ + uint64_t tiny = predict_false(d2==0) ? 0 : 0x0010000000000000; + tiny |= (d1^d2) & 0x8000000000000000; + t = asdouble(tiny); + y = eval_as_double(y + t); } - ix0 = (q>>1) + 0x3fe00000; - ix1 = q1>>1; - if (q&1) - ix1 |= sign; - INSERT_WORDS(z, ix0 + ((uint32_t)m << 20), ix1); - return z; + return y; } diff --git a/libc-top-half/musl/src/math/sqrt_data.c b/libc-top-half/musl/src/math/sqrt_data.c new file mode 100644 index 0000000..61bc22f --- /dev/null +++ b/libc-top-half/musl/src/math/sqrt_data.c @@ -0,0 +1,19 @@ +#include "sqrt_data.h" +const uint16_t __rsqrt_tab[128] = { +0xb451,0xb2f0,0xb196,0xb044,0xaef9,0xadb6,0xac79,0xab43, +0xaa14,0xa8eb,0xa7c8,0xa6aa,0xa592,0xa480,0xa373,0xa26b, +0xa168,0xa06a,0x9f70,0x9e7b,0x9d8a,0x9c9d,0x9bb5,0x9ad1, +0x99f0,0x9913,0x983a,0x9765,0x9693,0x95c4,0x94f8,0x9430, +0x936b,0x92a9,0x91ea,0x912e,0x9075,0x8fbe,0x8f0a,0x8e59, +0x8daa,0x8cfe,0x8c54,0x8bac,0x8b07,0x8a64,0x89c4,0x8925, +0x8889,0x87ee,0x8756,0x86c0,0x862b,0x8599,0x8508,0x8479, +0x83ec,0x8361,0x82d8,0x8250,0x81c9,0x8145,0x80c2,0x8040, +0xff02,0xfd0e,0xfb25,0xf947,0xf773,0xf5aa,0xf3ea,0xf234, +0xf087,0xeee3,0xed47,0xebb3,0xea27,0xe8a3,0xe727,0xe5b2, +0xe443,0xe2dc,0xe17a,0xe020,0xdecb,0xdd7d,0xdc34,0xdaf1, +0xd9b3,0xd87b,0xd748,0xd61a,0xd4f1,0xd3cd,0xd2ad,0xd192, +0xd07b,0xcf69,0xce5b,0xcd51,0xcc4a,0xcb48,0xca4a,0xc94f, +0xc858,0xc764,0xc674,0xc587,0xc49d,0xc3b7,0xc2d4,0xc1f4, +0xc116,0xc03c,0xbf65,0xbe90,0xbdbe,0xbcef,0xbc23,0xbb59, +0xba91,0xb9cc,0xb90a,0xb84a,0xb78c,0xb6d0,0xb617,0xb560, +}; diff --git a/libc-top-half/musl/src/math/sqrt_data.h b/libc-top-half/musl/src/math/sqrt_data.h new file mode 100644 index 0000000..260c7f9 --- /dev/null +++ b/libc-top-half/musl/src/math/sqrt_data.h @@ -0,0 +1,13 @@ +#ifndef _SQRT_DATA_H +#define _SQRT_DATA_H + +#include +#include + +/* if x in [1,2): i = (int)(64*x); + if x in [2,4): i = (int)(32*x-64); + __rsqrt_tab[i]*2^-16 is estimating 1/sqrt(x) with small relative error: + |__rsqrt_tab[i]*0x1p-16*sqrt(x) - 1| < -0x1.fdp-9 < 2^-8 */ +extern hidden const uint16_t __rsqrt_tab[128]; + +#endif diff --git a/libc-top-half/musl/src/math/sqrtf.c b/libc-top-half/musl/src/math/sqrtf.c index d6ace38..740d81c 100644 --- a/libc-top-half/musl/src/math/sqrtf.c +++ b/libc-top-half/musl/src/math/sqrtf.c @@ -1,83 +1,83 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrtf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - +#include +#include #include "libm.h" +#include "sqrt_data.h" -static const float tiny = 1.0e-30; +#define FENV_SUPPORT 1 + +static inline uint32_t mul32(uint32_t a, uint32_t b) +{ + return (uint64_t)a*b >> 32; +} + +/* see sqrt.c for more detailed comments. */ float sqrtf(float x) { - float z; - int32_t sign = (int)0x80000000; - int32_t ix,s,q,m,t,i; - uint32_t r; + uint32_t ix, m, m1, m0, even, ey; - GET_FLOAT_WORD(ix, x); - - /* take care of Inf and NaN */ - if ((ix&0x7f800000) == 0x7f800000) - return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ - - /* take care of zero */ - if (ix <= 0) { - if ((ix&~sign) == 0) - return x; /* sqrt(+-0) = +-0 */ - if (ix < 0) - return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = ix>>23; - if (m == 0) { /* subnormal x */ - for (i = 0; (ix&0x00800000) == 0; i++) - ix<<=1; - m -= i - 1; - } - m -= 127; /* unbias exponent */ - ix = (ix&0x007fffff)|0x00800000; - if (m&1) /* odd m, double x to make it even */ - ix += ix; - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix += ix; - q = s = 0; /* q = sqrt(x) */ - r = 0x01000000; /* r = moving bit from right to left */ - - while (r != 0) { - t = s + r; - if (t <= ix) { - s = t+r; - ix -= t; - q += r; - } - ix += ix; - r >>= 1; + ix = asuint(x); + if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000)) { + /* x < 0x1p-126 or inf or nan. */ + if (ix * 2 == 0) + return x; + if (ix == 0x7f800000) + return x; + if (ix > 0x7f800000) + return __math_invalidf(x); + /* x is subnormal, normalize it. */ + ix = asuint(x * 0x1p23f); + ix -= 23 << 23; } - /* use floating add to find out rounding direction */ - if (ix != 0) { - z = 1.0f - tiny; /* raise inexact flag */ - if (z >= 1.0f) { - z = 1.0f + tiny; - if (z > 1.0f) - q += 2; - else - q += q & 1; - } + /* x = 4^e m; with int e and m in [1, 4). */ + even = ix & 0x00800000; + m1 = (ix << 8) | 0x80000000; + m0 = (ix << 7) & 0x7fffffff; + m = even ? m0 : m1; + + /* 2^e is the exponent part of the return value. */ + ey = ix >> 1; + ey += 0x3f800000 >> 1; + ey &= 0x7f800000; + + /* compute r ~ 1/sqrt(m), s ~ sqrt(m) with 2 goldschmidt iterations. */ + static const uint32_t three = 0xc0000000; + uint32_t r, s, d, u, i; + i = (ix >> 17) % 128; + r = (uint32_t)__rsqrt_tab[i] << 16; + /* |r*sqrt(m) - 1| < 0x1p-8 */ + s = mul32(m, r); + /* |s/sqrt(m) - 1| < 0x1p-8 */ + d = mul32(s, r); + u = three - d; + r = mul32(r, u) << 1; + /* |r*sqrt(m) - 1| < 0x1.7bp-16 */ + s = mul32(s, u) << 1; + /* |s/sqrt(m) - 1| < 0x1.7bp-16 */ + d = mul32(s, r); + u = three - d; + s = mul32(s, u); + /* -0x1.03p-28 < s/sqrt(m) - 1 < 0x1.fp-31 */ + s = (s - 1)>>6; + /* s < sqrt(m) < s + 0x1.08p-23 */ + + /* compute nearest rounded result. */ + uint32_t d0, d1, d2; + float y, t; + d0 = (m << 16) - s*s; + d1 = s - d0; + d2 = d1 + s + 1; + s += d1 >> 31; + s &= 0x007fffff; + s |= ey; + y = asfloat(s); + if (FENV_SUPPORT) { + /* handle rounding and inexact exception. */ + uint32_t tiny = predict_false(d2==0) ? 0 : 0x01000000; + tiny |= (d1^d2) & 0x80000000; + t = asfloat(tiny); + y = eval_as_float(y + t); } - ix = (q>>1) + 0x3f000000; - SET_FLOAT_WORD(z, ix + ((uint32_t)m << 23)); - return z; + return y; } diff --git a/libc-top-half/musl/src/math/sqrtl.c b/libc-top-half/musl/src/math/sqrtl.c index 83a8f80..1b9f19c 100644 --- a/libc-top-half/musl/src/math/sqrtl.c +++ b/libc-top-half/musl/src/math/sqrtl.c @@ -1,7 +1,259 @@ +#include #include +#include +#include "libm.h" + +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 +long double sqrtl(long double x) +{ + return sqrt(x); +} +#elif (LDBL_MANT_DIG == 113 || LDBL_MANT_DIG == 64) && LDBL_MAX_EXP == 16384 +#include "sqrt_data.h" + +#define FENV_SUPPORT 1 + +typedef struct { + uint64_t hi; + uint64_t lo; +} u128; + +/* top: 16 bit sign+exponent, x: significand. */ +static inline long double mkldbl(uint64_t top, u128 x) +{ + union ldshape u; +#if LDBL_MANT_DIG == 113 + u.i2.hi = x.hi; + u.i2.lo = x.lo; + u.i2.hi &= 0x0000ffffffffffff; + u.i2.hi |= top << 48; +#elif LDBL_MANT_DIG == 64 + u.i.se = top; + u.i.m = x.lo; + /* force the top bit on non-zero (and non-subnormal) results. */ + if (top & 0x7fff) + u.i.m |= 0x8000000000000000; +#endif + return u.f; +} + +/* return: top 16 bit is sign+exp and following bits are the significand. */ +static inline u128 asu128(long double x) +{ + union ldshape u = {.f=x}; + u128 r; +#if LDBL_MANT_DIG == 113 + r.hi = u.i2.hi; + r.lo = u.i2.lo; +#elif LDBL_MANT_DIG == 64 + r.lo = u.i.m<<49; + /* ignore the top bit: pseudo numbers are not handled. */ + r.hi = u.i.m>>15; + r.hi &= 0x0000ffffffffffff; + r.hi |= (uint64_t)u.i.se << 48; +#endif + return r; +} + +/* returns a*b*2^-32 - e, with error 0 <= e < 1. */ +static inline uint32_t mul32(uint32_t a, uint32_t b) +{ + return (uint64_t)a*b >> 32; +} + +/* returns a*b*2^-64 - e, with error 0 <= e < 3. */ +static inline uint64_t mul64(uint64_t a, uint64_t b) +{ + uint64_t ahi = a>>32; + uint64_t alo = a&0xffffffff; + uint64_t bhi = b>>32; + uint64_t blo = b&0xffffffff; + return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32); +} + +static inline u128 add64(u128 a, uint64_t b) +{ + u128 r; + r.lo = a.lo + b; + r.hi = a.hi; + if (r.lo < a.lo) + r.hi++; + return r; +} + +static inline u128 add128(u128 a, u128 b) +{ + u128 r; + r.lo = a.lo + b.lo; + r.hi = a.hi + b.hi; + if (r.lo < a.lo) + r.hi++; + return r; +} + +static inline u128 sub64(u128 a, uint64_t b) +{ + u128 r; + r.lo = a.lo - b; + r.hi = a.hi; + if (a.lo < b) + r.hi--; + return r; +} + +static inline u128 sub128(u128 a, u128 b) +{ + u128 r; + r.lo = a.lo - b.lo; + r.hi = a.hi - b.hi; + if (a.lo < b.lo) + r.hi--; + return r; +} + +/* a<= 64) { + a.hi = a.lo<<(n-64); + a.lo = 0; + } else { + a.hi = (a.hi<>(64-n)); + a.lo = a.lo<>n, 0 <= n <= 127 */ +static inline u128 rsh(u128 a, int n) +{ + if (n == 0) + return a; + if (n >= 64) { + a.lo = a.hi>>(n-64); + a.hi = 0; + } else { + a.lo = (a.lo>>n) | (a.hi<<(64-n)); + a.hi = a.hi>>n; + } + return a; +} + +/* returns a*b exactly. */ +static inline u128 mul64_128(uint64_t a, uint64_t b) +{ + u128 r; + uint64_t ahi = a>>32; + uint64_t alo = a&0xffffffff; + uint64_t bhi = b>>32; + uint64_t blo = b&0xffffffff; + uint64_t lo1 = ((ahi*blo)&0xffffffff) + ((alo*bhi)&0xffffffff) + (alo*blo>>32); + uint64_t lo2 = (alo*blo)&0xffffffff; + r.hi = ahi*bhi + (ahi*blo>>32) + (alo*bhi>>32) + (lo1>>32); + r.lo = (lo1<<32) + lo2; + return r; +} + +/* returns a*b*2^-128 - e, with error 0 <= e < 7. */ +static inline u128 mul128(u128 a, u128 b) +{ + u128 hi = mul64_128(a.hi, b.hi); + uint64_t m1 = mul64(a.hi, b.lo); + uint64_t m2 = mul64(a.lo, b.hi); + return add64(add64(hi, m1), m2); +} + +/* returns a*b % 2^128. */ +static inline u128 mul128_tail(u128 a, u128 b) +{ + u128 lo = mul64_128(a.lo, b.lo); + lo.hi += a.hi*b.lo + a.lo*b.hi; + return lo; +} + + +/* see sqrt.c for detailed comments. */ long double sqrtl(long double x) { - /* FIXME: implement in C, this is for LDBL_MANT_DIG == 64 only */ - return sqrt(x); + u128 ix, ml; + uint64_t top; + + ix = asu128(x); + top = ix.hi >> 48; + if (predict_false(top - 0x0001 >= 0x7fff - 0x0001)) { + /* x < 0x1p-16382 or inf or nan. */ + if (2*ix.hi == 0 && ix.lo == 0) + return x; + if (ix.hi == 0x7fff000000000000 && ix.lo == 0) + return x; + if (top >= 0x7fff) + return __math_invalidl(x); + /* x is subnormal, normalize it. */ + ix = asu128(x * 0x1p112); + top = ix.hi >> 48; + top -= 112; + } + + /* x = 4^e m; with int e and m in [1, 4) */ + int even = top & 1; + ml = lsh(ix, 15); + ml.hi |= 0x8000000000000000; + if (even) ml = rsh(ml, 1); + top = (top + 0x3fff) >> 1; + + /* r ~ 1/sqrt(m) */ + static const uint64_t three = 0xc0000000; + uint64_t r, s, d, u, i; + i = (ix.hi >> 42) % 128; + r = (uint32_t)__rsqrt_tab[i] << 16; + /* |r sqrt(m) - 1| < 0x1p-8 */ + s = mul32(ml.hi>>32, r); + d = mul32(s, r); + u = three - d; + r = mul32(u, r) << 1; + /* |r sqrt(m) - 1| < 0x1.7bp-16, switch to 64bit */ + r = r<<32; + s = mul64(ml.hi, r); + d = mul64(s, r); + u = (three<<32) - d; + r = mul64(u, r) << 1; + /* |r sqrt(m) - 1| < 0x1.a5p-31 */ + s = mul64(u, s) << 1; + d = mul64(s, r); + u = (three<<32) - d; + r = mul64(u, r) << 1; + /* |r sqrt(m) - 1| < 0x1.c001p-59, switch to 128bit */ + + static const u128 threel = {.hi=three<<32, .lo=0}; + u128 rl, sl, dl, ul; + rl.hi = r; + rl.lo = 0; + sl = mul128(ml, rl); + dl = mul128(sl, rl); + ul = sub128(threel, dl); + sl = mul128(ul, sl); /* repr: 3.125 */ + /* -0x1p-116 < s - sqrt(m) < 0x3.8001p-125 */ + sl = rsh(sub64(sl, 4), 125-(LDBL_MANT_DIG-1)); + /* s < sqrt(m) < s + 1 ULP + tiny */ + + long double y; + u128 d2, d1, d0; + d0 = sub128(lsh(ml, 2*(LDBL_MANT_DIG-1)-126), mul128_tail(sl,sl)); + d1 = sub128(sl, d0); + d2 = add128(add64(sl, 1), d1); + sl = add64(sl, d1.hi >> 63); + y = mkldbl(top, sl); + if (FENV_SUPPORT) { + /* handle rounding modes and inexact exception. */ + top = predict_false((d2.hi|d2.lo)==0) ? 0 : 1; + top |= ((d1.hi^d2.hi)&0x8000000000000000) >> 48; + y += mkldbl(top, (u128){0}); + } + return y; } +#else +#error unsupported long double format +#endif diff --git a/libc-top-half/musl/src/misc/ioctl.c b/libc-top-half/musl/src/misc/ioctl.c index 8947751..4928281 100644 --- a/libc-top-half/musl/src/misc/ioctl.c +++ b/libc-top-half/musl/src/misc/ioctl.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "syscall.h" @@ -28,6 +29,12 @@ struct ioctl_compat_map { * number producing macros; only size of result is meaningful. */ #define new_misaligned(n) struct { int i; time_t t; char c[(n)-4]; } +struct v4l2_event { + uint32_t a; + uint64_t b[8]; + uint32_t c[2], ts[2], d[9]; +}; + static const struct ioctl_compat_map compat_map[] = { { SIOCGSTAMP, SIOCGSTAMP_OLD, 8, R, 0, OFFS(0, 4) }, { SIOCGSTAMPNS, SIOCGSTAMPNS_OLD, 8, R, 0, OFFS(0, 4) }, @@ -49,13 +56,14 @@ static const struct ioctl_compat_map compat_map[] = { { 0, 0, 8, WR, 1, OFFS(0,4) }, /* snd_pcm_mmap_control */ /* VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF */ - { _IOWR('V', 9, new_misaligned(72)), _IOWR('V', 9, char[72]), 72, WR, 0, OFFS(20) }, - { _IOWR('V', 15, new_misaligned(72)), _IOWR('V', 15, char[72]), 72, WR, 0, OFFS(20) }, - { _IOWR('V', 17, new_misaligned(72)), _IOWR('V', 17, char[72]), 72, WR, 0, OFFS(20) }, - { _IOWR('V', 93, new_misaligned(72)), _IOWR('V', 93, char[72]), 72, WR, 0, OFFS(20) }, + { _IOWR('V', 9, new_misaligned(68)), _IOWR('V', 9, char[68]), 68, WR, 1, OFFS(20, 24) }, + { _IOWR('V', 15, new_misaligned(68)), _IOWR('V', 15, char[68]), 68, WR, 1, OFFS(20, 24) }, + { _IOWR('V', 17, new_misaligned(68)), _IOWR('V', 17, char[68]), 68, WR, 1, OFFS(20, 24) }, + { _IOWR('V', 93, new_misaligned(68)), _IOWR('V', 93, char[68]), 68, WR, 1, OFFS(20, 24) }, /* VIDIOC_DQEVENT */ - { _IOR('V', 89, new_misaligned(96)), _IOR('V', 89, char[96]), 96, R, 0, OFFS(76,80) }, + { _IOR('V', 89, new_misaligned(120)), _IOR('V', 89, struct v4l2_event), sizeof(struct v4l2_event), + R, 0, OFFS(offsetof(struct v4l2_event, ts[0]), offsetof(struct v4l2_event, ts[1])) }, /* VIDIOC_OMAP3ISP_STAT_REQ */ { _IOWR('V', 192+6, char[32]), _IOWR('V', 192+6, char[24]), 22, WR, 0, OFFS(0,4) }, diff --git a/libc-top-half/musl/src/misc/realpath.c b/libc-top-half/musl/src/misc/realpath.c index d2708e5..db8b74d 100644 --- a/libc-top-half/musl/src/misc/realpath.c +++ b/libc-top-half/musl/src/misc/realpath.c @@ -1,43 +1,156 @@ #include #include -#include -#include #include #include #include -#include "syscall.h" + +static size_t slash_len(const char *s) +{ + const char *s0 = s; + while (*s == '/') s++; + return s-s0; +} char *realpath(const char *restrict filename, char *restrict resolved) { - int fd; - ssize_t r; - struct stat st1, st2; - char buf[15+3*sizeof(int)]; - char tmp[PATH_MAX]; + char stack[PATH_MAX+1]; + char output[PATH_MAX]; + size_t p, q, l, l0, cnt=0, nup=0; + int check_dir=0; if (!filename) { errno = EINVAL; return 0; } + l = strnlen(filename, sizeof stack); + if (!l) { + errno = ENOENT; + return 0; + } + if (l >= PATH_MAX) goto toolong; + p = sizeof stack - l - 1; + q = 0; + memcpy(stack+p, filename, l+1); - fd = sys_open(filename, O_PATH|O_NONBLOCK|O_CLOEXEC); - if (fd < 0) return 0; - __procfdname(buf, fd); + /* Main loop. Each iteration pops the next part from stack of + * remaining path components and consumes any slashes that follow. + * If not a link, it's moved to output; if a link, contents are + * pushed to the stack. */ +restart: + for (; ; p+=slash_len(stack+p)) { + /* If stack starts with /, the whole component is / or // + * and the output state must be reset. */ + if (stack[p] == '/') { + check_dir=0; + nup=0; + q=0; + output[q++] = '/'; + p++; + /* Initial // is special. */ + if (stack[p] == '/' && stack[p+1] != '/') + output[q++] = '/'; + continue; + } - r = readlink(buf, tmp, sizeof tmp - 1); - if (r < 0) goto err; - tmp[r] = 0; + char *z = __strchrnul(stack+p, '/'); + l0 = l = z-(stack+p); - fstat(fd, &st1); - r = stat(tmp, &st2); - if (r<0 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) { - if (!r) errno = ELOOP; - goto err; + if (!l && !check_dir) break; + + /* Skip any . component but preserve check_dir status. */ + if (l==1 && stack[p]=='.') { + p += l; + continue; + } + + /* Copy next component onto output at least temporarily, to + * call readlink, but wait to advance output position until + * determining it's not a link. */ + if (q && output[q-1] != '/') { + if (!p) goto toolong; + stack[--p] = '/'; + l++; + } + if (q+l >= PATH_MAX) goto toolong; + memcpy(output+q, stack+p, l); + output[q+l] = 0; + p += l; + + int up = 0; + if (l0==2 && stack[p-2]=='.' && stack[p-1]=='.') { + up = 1; + /* Any non-.. path components we could cancel start + * after nup repetitions of the 3-byte string "../"; + * if there are none, accumulate .. components to + * later apply to cwd, if needed. */ + if (q <= 3*nup) { + nup++; + q += l; + continue; + } + /* When previous components are already known to be + * directories, processing .. can skip readlink. */ + if (!check_dir) goto skip_readlink; + } + ssize_t k = readlink(output, stack, p); + if (k==p) goto toolong; + if (!k) { + errno = ENOENT; + return 0; + } + if (k<0) { + if (errno != EINVAL) return 0; +skip_readlink: + check_dir = 0; + if (up) { + while(q && output[q-1]!='/') q--; + if (q>1 && (q>2 || output[0]!='/')) q--; + continue; + } + if (l0) q += l; + check_dir = stack[p]; + continue; + } + if (++cnt == SYMLOOP_MAX) { + errno = ELOOP; + return 0; + } + + /* If link contents end in /, strip any slashes already on + * stack to avoid /->// or //->/// or spurious toolong. */ + if (stack[k-1]=='/') while (stack[p]=='/') p++; + p -= k; + memmove(stack+p, stack, k); + + /* Skip the stack advancement in case we have a new + * absolute base path. */ + goto restart; } - __syscall(SYS_close, fd); - return resolved ? strcpy(resolved, tmp) : strdup(tmp); -err: - __syscall(SYS_close, fd); + output[q] = 0; + + if (output[0] != '/') { + if (!getcwd(stack, sizeof stack)) return 0; + l = strlen(stack); + /* Cancel any initial .. components. */ + p = 0; + while (nup--) { + while(l>1 && stack[l-1]!='/') l--; + if (l>1) l--; + p += 2; + if (p= PATH_MAX) goto toolong; + memmove(output + l, output + p, q - p + 1); + memcpy(output, stack, l); + q = l + q-p; + } + + if (resolved) return memcpy(resolved, output, q+1); + else return strdup(output); + +toolong: + errno = ENAMETOOLONG; return 0; } diff --git a/libc-top-half/musl/src/misc/setrlimit.c b/libc-top-half/musl/src/misc/setrlimit.c index 7a66ab2..8340aee 100644 --- a/libc-top-half/musl/src/misc/setrlimit.c +++ b/libc-top-half/musl/src/misc/setrlimit.c @@ -6,25 +6,8 @@ #define MIN(a, b) ((a)<(b) ? (a) : (b)) #define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0) -static int __setrlimit(int resource, const struct rlimit *rlim) -{ - unsigned long k_rlim[2]; - struct rlimit tmp; - if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) { - tmp = *rlim; - FIX(tmp.rlim_cur); - FIX(tmp.rlim_max); - rlim = &tmp; - } - int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0); - if (ret != -ENOSYS) return ret; - k_rlim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY)); - k_rlim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY)); - return __syscall(SYS_setrlimit, resource, k_rlim); -} - struct ctx { - const struct rlimit *rlim; + unsigned long lim[2]; int res; int err; }; @@ -33,12 +16,26 @@ static void do_setrlimit(void *p) { struct ctx *c = p; if (c->err>0) return; - c->err = -__setrlimit(c->res, c->rlim); + c->err = -__syscall(SYS_setrlimit, c->res, c->lim); } int setrlimit(int resource, const struct rlimit *rlim) { - struct ctx c = { .res = resource, .rlim = rlim, .err = -1 }; + struct rlimit tmp; + if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) { + tmp = *rlim; + FIX(tmp.rlim_cur); + FIX(tmp.rlim_max); + rlim = &tmp; + } + int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0); + if (ret != -ENOSYS) return __syscall_ret(ret); + + struct ctx c = { + .lim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY)), + .lim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY)), + .res = resource, .err = -1 + }; __synccall(do_setrlimit, &c); if (c.err) { if (c.err>0) errno = c.err; diff --git a/libc-top-half/musl/src/misc/syslog.c b/libc-top-half/musl/src/misc/syslog.c index bed11b5..b802acd 100644 --- a/libc-top-half/musl/src/misc/syslog.c +++ b/libc-top-half/musl/src/misc/syslog.c @@ -12,6 +12,7 @@ #include #include #include "lock.h" +#include "fork_impl.h" static volatile int lock[1]; static char log_ident[32]; @@ -19,6 +20,7 @@ static int log_opt; static int log_facility = LOG_USER; static int log_mask = 0xff; static int log_fd = -1; +volatile int *const __syslog_lockptr = lock; int setlogmask(int maskpri) { diff --git a/libc-top-half/musl/src/misc/uname.c b/libc-top-half/musl/src/misc/uname.c index b6163c3..36e816a 100644 --- a/libc-top-half/musl/src/misc/uname.c +++ b/libc-top-half/musl/src/misc/uname.c @@ -1,6 +1,6 @@ #include -#include "syscall.h" #ifdef __wasilibc_unmodified_upstream // Implement uname with placeholders +#include "syscall.h" #else #include #endif diff --git a/libc-top-half/musl/src/multibyte/wcsnrtombs.c b/libc-top-half/musl/src/multibyte/wcsnrtombs.c index 676932b..95e25e7 100644 --- a/libc-top-half/musl/src/multibyte/wcsnrtombs.c +++ b/libc-top-half/musl/src/multibyte/wcsnrtombs.c @@ -1,41 +1,33 @@ #include +#include +#include size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st) { - size_t l, cnt=0, n2; - char *s, buf[256]; const wchar_t *ws = *wcs; - const wchar_t *tmp_ws; - - if (!dst) s = buf, n = sizeof buf; - else s = dst; - - while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) { - if (n2>=n) n2=n; - tmp_ws = ws; - l = wcsrtombs(s, &ws, n2, 0); - if (!(l+1)) { - cnt = l; - n = 0; + size_t cnt = 0; + if (!dst) n=0; + while (ws && wn) { + char tmp[MB_LEN_MAX]; + size_t l = wcrtomb(nn) break; + memcpy(dst, tmp, l); + } + dst += l; n -= l; } - wn = ws ? wn - (ws - tmp_ws) : 0; - cnt += l; - } - if (ws) while (n && wn) { - l = wcrtomb(s, *ws, 0); - if ((l+1)<=1) { - if (!l) ws = 0; - else cnt = l; + if (!*ws) { + ws = 0; break; } - ws++; wn--; - /* safe - this loop runs fewer than sizeof(buf) times */ - s+=l; n-=l; + ws++; + wn--; cnt += l; } if (dst) *wcs = ws; diff --git a/libc-top-half/musl/src/network/h_errno.c b/libc-top-half/musl/src/network/h_errno.c index 4f700ce..638f771 100644 --- a/libc-top-half/musl/src/network/h_errno.c +++ b/libc-top-half/musl/src/network/h_errno.c @@ -1,9 +1,11 @@ #include +#include "pthread_impl.h" #undef h_errno int h_errno; int *__h_errno_location(void) { - return &h_errno; + if (!__pthread_self()->stack) return &h_errno; + return &__pthread_self()->h_errno_val; } diff --git a/libc-top-half/musl/src/network/herror.c b/libc-top-half/musl/src/network/herror.c index 65f25ff..87f8cff 100644 --- a/libc-top-half/musl/src/network/herror.c +++ b/libc-top-half/musl/src/network/herror.c @@ -4,5 +4,5 @@ void herror(const char *msg) { - fprintf(stderr, "%s%s%s", msg?msg:"", msg?": ":"", hstrerror(h_errno)); + fprintf(stderr, "%s%s%s\n", msg?msg:"", msg?": ":"", hstrerror(h_errno)); } diff --git a/libc-top-half/musl/src/network/lookup_name.c b/libc-top-half/musl/src/network/lookup_name.c index aae0d95..aa558c1 100644 --- a/libc-top-half/musl/src/network/lookup_name.c +++ b/libc-top-half/musl/src/network/lookup_name.c @@ -50,7 +50,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati { char line[512]; size_t l = strlen(name); - int cnt = 0, badfam = 0; + int cnt = 0, badfam = 0, have_canon = 0; unsigned char _buf[1032]; FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf); if (!f) switch (errno) { @@ -80,14 +80,19 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati continue; default: badfam = EAI_NONAME; - continue; + break; } + if (have_canon) continue; + /* Extract first name as canonical name */ for (; *p && isspace(*p); p++); for (z=p; *z && !isspace(*z); z++); *z = 0; - if (is_valid_hostname(p)) memcpy(canon, p, z-p+1); + if (is_valid_hostname(p)) { + have_canon = 1; + memcpy(canon, p, z-p+1); + } } __fclose_ca(f); return cnt ? cnt : badfam; diff --git a/libc-top-half/musl/src/network/res_query.c b/libc-top-half/musl/src/network/res_query.c index 2f4da2e..506dc23 100644 --- a/libc-top-half/musl/src/network/res_query.c +++ b/libc-top-half/musl/src/network/res_query.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE #include #include @@ -6,7 +7,20 @@ int res_query(const char *name, int class, int type, unsigned char *dest, int le unsigned char q[280]; int ql = __res_mkquery(0, name, class, type, 0, 0, 0, q, sizeof q); if (ql < 0) return ql; - return __res_send(q, ql, dest, len); + int r = __res_send(q, ql, dest, len); + if (r<12) { + h_errno = TRY_AGAIN; + return -1; + } + if ((dest[3] & 15) == 3) { + h_errno = HOST_NOT_FOUND; + return -1; + } + if ((dest[3] & 15) == 0 && !dest[6] && !dest[7]) { + h_errno = NO_DATA; + return -1; + } + return r; } weak_alias(res_query, res_search); diff --git a/libc-top-half/musl/src/passwd/getgrouplist.c b/libc-top-half/musl/src/passwd/getgrouplist.c index 43e5182..301824c 100644 --- a/libc-top-half/musl/src/passwd/getgrouplist.c +++ b/libc-top-half/musl/src/passwd/getgrouplist.c @@ -31,7 +31,8 @@ int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups) if (resp[INITGRFOUND]) { nscdbuf = calloc(resp[INITGRNGRPS], sizeof(uint32_t)); if (!nscdbuf) goto cleanup; - if (!fread(nscdbuf, sizeof(*nscdbuf)*resp[INITGRNGRPS], 1, f)) { + size_t nbytes = sizeof(*nscdbuf)*resp[INITGRNGRPS]; + if (nbytes && !fread(nscdbuf, nbytes, 1, f)) { if (!ferror(f)) errno = EIO; goto cleanup; } diff --git a/libc-top-half/musl/src/prng/random.c b/libc-top-half/musl/src/prng/random.c index 633a17f..3326f09 100644 --- a/libc-top-half/musl/src/prng/random.c +++ b/libc-top-half/musl/src/prng/random.c @@ -1,6 +1,7 @@ #include #include #include "lock.h" +#include "fork_impl.h" /* this code uses the same lagged fibonacci generator as the @@ -22,7 +23,10 @@ static int n = 31; static int i = 3; static int j = 0; static uint32_t *x = init+1; +#ifdef __wasilibc_unmodified_upstream static volatile int lock[1]; +volatile int *const __random_lockptr = lock; +#endif static uint32_t lcg31(uint32_t x) { return (1103515245*x + 12345) & 0x7fffffff; diff --git a/libc-top-half/musl/src/process/_Fork.c b/libc-top-half/musl/src/process/_Fork.c new file mode 100644 index 0000000..da06386 --- /dev/null +++ b/libc-top-half/musl/src/process/_Fork.c @@ -0,0 +1,38 @@ +#include +#include +#include "syscall.h" +#include "libc.h" +#include "lock.h" +#include "pthread_impl.h" +#include "aio_impl.h" + +static void dummy(int x) { } +weak_alias(dummy, __aio_atfork); + +pid_t _Fork(void) +{ + pid_t ret; + sigset_t set; + __block_all_sigs(&set); + __aio_atfork(-1); + LOCK(__abort_lock); +#ifdef SYS_fork + ret = __syscall(SYS_fork); +#else + ret = __syscall(SYS_clone, SIGCHLD, 0); +#endif + if (!ret) { + pthread_t self = __pthread_self(); + self->tid = __syscall(SYS_gettid); + self->robust_list.off = 0; + self->robust_list.pending = 0; + self->next = self->prev = self; + __thread_list_lock = 0; + libc.threads_minus_1 = 0; + if (libc.need_locks) libc.need_locks = -1; + } + UNLOCK(__abort_lock); + __aio_atfork(!ret); + __restore_sigs(&set); + return __syscall_ret(ret); +} diff --git a/libc-top-half/musl/src/process/fork.c b/libc-top-half/musl/src/process/fork.c index 7e984ff..54bc289 100644 --- a/libc-top-half/musl/src/process/fork.c +++ b/libc-top-half/musl/src/process/fork.c @@ -1,38 +1,86 @@ #include -#include -#include -#include "syscall.h" +#include #include "libc.h" +#include "lock.h" #include "pthread_impl.h" +#include "fork_impl.h" -static void dummy(int x) -{ -} +static volatile int *const dummy_lockptr = 0; +weak_alias(dummy_lockptr, __at_quick_exit_lockptr); +weak_alias(dummy_lockptr, __atexit_lockptr); +weak_alias(dummy_lockptr, __dlerror_lockptr); +weak_alias(dummy_lockptr, __gettext_lockptr); +weak_alias(dummy_lockptr, __locale_lockptr); +weak_alias(dummy_lockptr, __random_lockptr); +weak_alias(dummy_lockptr, __sem_open_lockptr); +weak_alias(dummy_lockptr, __stdio_ofl_lockptr); +weak_alias(dummy_lockptr, __syslog_lockptr); +weak_alias(dummy_lockptr, __timezone_lockptr); +weak_alias(dummy_lockptr, __bump_lockptr); + +weak_alias(dummy_lockptr, __vmlock_lockptr); + +static volatile int *const *const atfork_locks[] = { + &__at_quick_exit_lockptr, + &__atexit_lockptr, + &__dlerror_lockptr, + &__gettext_lockptr, + &__locale_lockptr, + &__random_lockptr, + &__sem_open_lockptr, + &__stdio_ofl_lockptr, + &__syslog_lockptr, + &__timezone_lockptr, + &__bump_lockptr, +}; + +static void dummy(int x) { } weak_alias(dummy, __fork_handler); +weak_alias(dummy, __malloc_atfork); +weak_alias(dummy, __ldso_atfork); + +static void dummy_0(void) { } +weak_alias(dummy_0, __tl_lock); +weak_alias(dummy_0, __tl_unlock); pid_t fork(void) { - pid_t ret; sigset_t set; __fork_handler(-1); - __block_all_sigs(&set); -#ifdef SYS_fork - ret = __syscall(SYS_fork); -#else - ret = __syscall(SYS_clone, SIGCHLD, 0); -#endif - if (!ret) { - pthread_t self = __pthread_self(); - self->tid = __syscall(SYS_gettid); - self->robust_list.off = 0; - self->robust_list.pending = 0; - self->next = self->prev = self; - __thread_list_lock = 0; - libc.threads_minus_1 = 0; - if (libc.need_locks) libc.need_locks = -1; + __block_app_sigs(&set); + int need_locks = libc.need_locks > 0; + if (need_locks) { + __ldso_atfork(-1); + __inhibit_ptc(); + for (int i=0; inext; + pid_t ret = _Fork(); + int errno_save = errno; + if (need_locks) { + if (!ret) { + for (pthread_t td=next; td!=self; td=td->next) + td->tid = -1; + if (__vmlock_lockptr) { + __vmlock_lockptr[0] = 0; + __vmlock_lockptr[1] = 0; + } + } + __tl_unlock(); + __malloc_atfork(!ret); + for (int i=0; i #include #include "syscall.h" +#include "lock.h" #include "pthread_impl.h" #include "fdop.h" @@ -170,9 +171,6 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, int ec=0, cs; struct args args; - if (pipe2(args.p, O_CLOEXEC)) - return errno; - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); args.path = path; @@ -182,9 +180,20 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, args.envp = envp; pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask); + /* The lock guards both against seeing a SIGABRT disposition change + * by abort and against leaking the pipe fd to fork-without-exec. */ + LOCK(__abort_lock); + + if (pipe2(args.p, O_CLOEXEC)) { + UNLOCK(__abort_lock); + ec = errno; + goto fail; + } + pid = __clone(child, stack+sizeof stack, CLONE_VM|CLONE_VFORK|SIGCHLD, &args); close(args.p[1]); + UNLOCK(__abort_lock); if (pid > 0) { if (read(args.p[0], &ec, sizeof ec) != sizeof ec) ec = 0; @@ -197,6 +206,7 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, if (!ec && res) *res = pid; +fail: pthread_sigmask(SIG_SETMASK, &args.oldmask, 0); pthread_setcancelstate(cs, 0); diff --git a/libc-top-half/musl/src/setjmp/aarch64/longjmp.s b/libc-top-half/musl/src/setjmp/aarch64/longjmp.s index 7c4655f..0af9c50 100644 --- a/libc-top-half/musl/src/setjmp/aarch64/longjmp.s +++ b/libc-top-half/musl/src/setjmp/aarch64/longjmp.s @@ -18,7 +18,6 @@ longjmp: ldp d12, d13, [x0,#144] ldp d14, d15, [x0,#160] - mov x0, x1 - cbnz x1, 1f - mov x0, #1 -1: br x30 + cmp w1, 0 + csinc w0, w1, wzr, ne + br x30 diff --git a/libc-top-half/musl/src/setjmp/i386/longjmp.s b/libc-top-half/musl/src/setjmp/i386/longjmp.s index 772d28d..8188f06 100644 --- a/libc-top-half/musl/src/setjmp/i386/longjmp.s +++ b/libc-top-half/musl/src/setjmp/i386/longjmp.s @@ -6,15 +6,11 @@ _longjmp: longjmp: mov 4(%esp),%edx mov 8(%esp),%eax - test %eax,%eax - jnz 1f - inc %eax -1: + cmp $1,%eax + adc $0, %al mov (%edx),%ebx mov 4(%edx),%esi mov 8(%edx),%edi mov 12(%edx),%ebp - mov 16(%edx),%ecx - mov %ecx,%esp - mov 20(%edx),%ecx - jmp *%ecx + mov 16(%edx),%esp + jmp *20(%edx) diff --git a/libc-top-half/musl/src/setjmp/x32/longjmp.s b/libc-top-half/musl/src/setjmp/x32/longjmp.s index e175a4b..1b2661c 100644 --- a/libc-top-half/musl/src/setjmp/x32/longjmp.s +++ b/libc-top-half/musl/src/setjmp/x32/longjmp.s @@ -5,18 +5,14 @@ .type longjmp,@function _longjmp: longjmp: - mov %rsi,%rax /* val will be longjmp return */ - test %rax,%rax - jnz 1f - inc %rax /* if val==0, val=1 per longjmp semantics */ -1: + xor %eax,%eax + cmp $1,%esi /* CF = val ? 0 : 1 */ + adc %esi,%eax /* eax = val + !val */ mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */ mov 8(%rdi),%rbp mov 16(%rdi),%r12 mov 24(%rdi),%r13 mov 32(%rdi),%r14 mov 40(%rdi),%r15 - mov 48(%rdi),%rdx /* this ends up being the stack pointer */ - mov %rdx,%rsp - mov 56(%rdi),%rdx /* this is the instruction pointer */ - jmp *%rdx /* goto saved address without altering rsp */ + mov 48(%rdi),%rsp + jmp *56(%rdi) /* goto saved address without altering rsp */ diff --git a/libc-top-half/musl/src/setjmp/x32/setjmp.s b/libc-top-half/musl/src/setjmp/x32/setjmp.s index 98f58b8..d95e485 100644 --- a/libc-top-half/musl/src/setjmp/x32/setjmp.s +++ b/libc-top-half/musl/src/setjmp/x32/setjmp.s @@ -18,5 +18,5 @@ setjmp: mov %rdx,48(%rdi) mov (%rsp),%rdx /* save return addr ptr for new rip */ mov %rdx,56(%rdi) - xor %rax,%rax /* always return 0 */ + xor %eax,%eax /* always return 0 */ ret diff --git a/libc-top-half/musl/src/setjmp/x86_64/longjmp.s b/libc-top-half/musl/src/setjmp/x86_64/longjmp.s index e175a4b..1b2661c 100644 --- a/libc-top-half/musl/src/setjmp/x86_64/longjmp.s +++ b/libc-top-half/musl/src/setjmp/x86_64/longjmp.s @@ -5,18 +5,14 @@ .type longjmp,@function _longjmp: longjmp: - mov %rsi,%rax /* val will be longjmp return */ - test %rax,%rax - jnz 1f - inc %rax /* if val==0, val=1 per longjmp semantics */ -1: + xor %eax,%eax + cmp $1,%esi /* CF = val ? 0 : 1 */ + adc %esi,%eax /* eax = val + !val */ mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */ mov 8(%rdi),%rbp mov 16(%rdi),%r12 mov 24(%rdi),%r13 mov 32(%rdi),%r14 mov 40(%rdi),%r15 - mov 48(%rdi),%rdx /* this ends up being the stack pointer */ - mov %rdx,%rsp - mov 56(%rdi),%rdx /* this is the instruction pointer */ - jmp *%rdx /* goto saved address without altering rsp */ + mov 48(%rdi),%rsp + jmp *56(%rdi) /* goto saved address without altering rsp */ diff --git a/libc-top-half/musl/src/setjmp/x86_64/setjmp.s b/libc-top-half/musl/src/setjmp/x86_64/setjmp.s index 98f58b8..d95e485 100644 --- a/libc-top-half/musl/src/setjmp/x86_64/setjmp.s +++ b/libc-top-half/musl/src/setjmp/x86_64/setjmp.s @@ -18,5 +18,5 @@ setjmp: mov %rdx,48(%rdi) mov (%rsp),%rdx /* save return addr ptr for new rip */ mov %rdx,56(%rdi) - xor %rax,%rax /* always return 0 */ + xor %eax,%eax /* always return 0 */ ret diff --git a/libc-top-half/musl/src/signal/sigaction.c b/libc-top-half/musl/src/signal/sigaction.c index c109bea..2203471 100644 --- a/libc-top-half/musl/src/signal/sigaction.c +++ b/libc-top-half/musl/src/signal/sigaction.c @@ -7,12 +7,6 @@ #include "lock.h" #include "ksigaction.h" -static volatile int dummy_lock[1] = { 0 }; - -extern hidden volatile int __abort_lock[1]; - -weak_alias(dummy_lock, __abort_lock); - static int unmask_done; static unsigned long handler_set[_NSIG/(8*sizeof(long))]; @@ -26,7 +20,6 @@ volatile int __eintr_valid_flag; int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old) { struct k_sigaction ksa, ksa_old; - unsigned long set[_NSIG/(8*sizeof(long))]; if (sa) { if ((uintptr_t)sa->sa_handler > 1UL) { a_or_l(handler_set+(sig-1)/(8*sizeof(long)), @@ -50,24 +43,12 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact a_store(&__eintr_valid_flag, 1); } } - /* Changing the disposition of SIGABRT to anything but - * SIG_DFL requires a lock, so that it cannot be changed - * while abort is terminating the process after simply - * calling raise(SIGABRT) failed to do so. */ - if (sa->sa_handler != SIG_DFL && sig == SIGABRT) { - __block_all_sigs(&set); - LOCK(__abort_lock); - } ksa.handler = sa->sa_handler; ksa.flags = sa->sa_flags | SA_RESTORER; ksa.restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore; memcpy(&ksa.mask, &sa->sa_mask, _NSIG/8); } int r = __syscall(SYS_rt_sigaction, sig, sa?&ksa:0, old?&ksa_old:0, _NSIG/8); - if (sig == SIGABRT && sa && sa->sa_handler != SIG_DFL) { - UNLOCK(__abort_lock); - __restore_sigs(&set); - } if (old && !r) { old->sa_handler = ksa_old.handler; old->sa_flags = ksa_old.flags; @@ -78,11 +59,26 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact int __sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old) { + unsigned long set[_NSIG/(8*sizeof(long))]; + if (sig-32U < 3 || sig-1U >= _NSIG-1) { errno = EINVAL; return -1; } - return __libc_sigaction(sig, sa, old); + + /* Doing anything with the disposition of SIGABRT requires a lock, + * so that it cannot be changed while abort is terminating the + * process and so any change made by abort can't be observed. */ + if (sig == SIGABRT) { + __block_all_sigs(&set); + LOCK(__abort_lock); + } + int r = __libc_sigaction(sig, sa, old); + if (sig == SIGABRT) { + UNLOCK(__abort_lock); + __restore_sigs(&set); + } + return r; } weak_alias(__sigaction, sigaction); diff --git a/libc-top-half/musl/src/stdio/__stdio_close.c b/libc-top-half/musl/src/stdio/__stdio_close.c index 21a678c..0d7c91e 100644 --- a/libc-top-half/musl/src/stdio/__stdio_close.c +++ b/libc-top-half/musl/src/stdio/__stdio_close.c @@ -3,6 +3,7 @@ #include #endif #include "stdio_impl.h" +#include "aio_impl.h" #if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) static int dummy(int fd) diff --git a/libc-top-half/musl/src/stdio/ofl.c b/libc-top-half/musl/src/stdio/ofl.c index f2d3215..33a8aa5 100644 --- a/libc-top-half/musl/src/stdio/ofl.c +++ b/libc-top-half/musl/src/stdio/ofl.c @@ -1,8 +1,12 @@ #include "stdio_impl.h" #include "lock.h" +#include "fork_impl.h" static FILE *ofl_head; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) static volatile int ofl_lock[1]; +volatile int *const __stdio_ofl_lockptr = ofl_lock; +#endif FILE **__ofl_lock() { diff --git a/libc-top-half/musl/src/string/strstr.c b/libc-top-half/musl/src/string/strstr.c index 43a0207..96657bc 100644 --- a/libc-top-half/musl/src/string/strstr.c +++ b/libc-top-half/musl/src/string/strstr.c @@ -96,7 +96,7 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n) for (;;) { /* Update incremental end-of-haystack pointer */ if (z-h < l) { - /* Fast estimate for MIN(l,63) */ + /* Fast estimate for MAX(l,63) */ size_t grow = l | 63; const unsigned char *z2 = memchr(z, 0, grow); if (z2) { diff --git a/libc-top-half/musl/src/termios/tcgetwinsize.c b/libc-top-half/musl/src/termios/tcgetwinsize.c new file mode 100644 index 0000000..9b3a65a --- /dev/null +++ b/libc-top-half/musl/src/termios/tcgetwinsize.c @@ -0,0 +1,8 @@ +#include +#include +#include "syscall.h" + +int tcgetwinsize(int fd, struct winsize *wsz) +{ + return syscall(SYS_ioctl, fd, TIOCGWINSZ, wsz); +} diff --git a/libc-top-half/musl/src/termios/tcsetwinsize.c b/libc-top-half/musl/src/termios/tcsetwinsize.c new file mode 100644 index 0000000..e01d0e2 --- /dev/null +++ b/libc-top-half/musl/src/termios/tcsetwinsize.c @@ -0,0 +1,8 @@ +#include +#include +#include "syscall.h" + +int tcsetwinsize(int fd, const struct winsize *wsz) +{ + return syscall(SYS_ioctl, fd, TIOCSWINSZ, wsz); +} diff --git a/libc-top-half/musl/src/thread/i386/__set_thread_area.s b/libc-top-half/musl/src/thread/i386/__set_thread_area.s index c2c21dd..aa6852b 100644 --- a/libc-top-half/musl/src/thread/i386/__set_thread_area.s +++ b/libc-top-half/musl/src/thread/i386/__set_thread_area.s @@ -28,6 +28,7 @@ __set_thread_area: ret 2: mov %ebx,%ecx + xor %eax,%eax xor %ebx,%ebx xor %edx,%edx mov %ebx,(%esp) diff --git a/libc-top-half/musl/src/thread/pthread_attr_get.c b/libc-top-half/musl/src/thread/pthread_attr_get.c index 4aa5afd..f12ff44 100644 --- a/libc-top-half/musl/src/thread/pthread_attr_get.c +++ b/libc-top-half/musl/src/thread/pthread_attr_get.c @@ -70,7 +70,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restr int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict protocol) { - *protocol = PTHREAD_PRIO_NONE; + *protocol = a->__attr / 8U % 2; return 0; } int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict pshared) diff --git a/libc-top-half/musl/src/thread/pthread_cond_timedwait.c b/libc-top-half/musl/src/thread/pthread_cond_timedwait.c index d150124..6b76145 100644 --- a/libc-top-half/musl/src/thread/pthread_cond_timedwait.c +++ b/libc-top-half/musl/src/thread/pthread_cond_timedwait.c @@ -146,14 +146,18 @@ relock: if (oldstate == WAITING) goto done; - if (!node.next) a_inc(&m->_m_waiters); + if (!node.next && !(m->_m_type & 8)) + a_inc(&m->_m_waiters); /* Unlock the barrier that's holding back the next waiter, and * either wake it or requeue it to the mutex. */ - if (node.prev) - unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & 128); - else - a_dec(&m->_m_waiters); + if (node.prev) { + int val = m->_m_lock; + if (val>0) a_cas(&m->_m_lock, val, val|0x80000000); + unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128)); + } else if (!(m->_m_type & 8)) { + a_dec(&m->_m_waiters); + } /* Since a signal was consumed, cancellation is not permitted. */ if (e == ECANCELED) e = 0; diff --git a/libc-top-half/musl/src/thread/pthread_create.c b/libc-top-half/musl/src/thread/pthread_create.c index 10f1b7d..6f187ee 100644 --- a/libc-top-half/musl/src/thread/pthread_create.c +++ b/libc-top-half/musl/src/thread/pthread_create.c @@ -69,12 +69,25 @@ _Noreturn void __pthread_exit(void *result) __pthread_tsd_run_dtors(); + __block_app_sigs(&set); + + /* This atomic potentially competes with a concurrent pthread_detach + * call; the loser is responsible for freeing thread resources. */ + int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); + + if (state==DT_DETACHED && self->map_base) { + /* Since __unmapself bypasses the normal munmap code path, + * explicitly wait for vmlock holders first. This must be + * done before any locks are taken, to avoid lock ordering + * issues that could lead to deadlock. */ + __vm_wait(); + } + /* Access to target the exiting thread with syscalls that use * its kernel tid is controlled by killlock. For detached threads, * any use past this point would have undefined behavior, but for * joinable threads it's a valid usage that must be handled. * Signals must be blocked since pthread_kill must be AS-safe. */ - __block_app_sigs(&set); LOCK(self->killlock); /* The thread list lock must be AS-safe, and thus depends on @@ -87,6 +100,7 @@ _Noreturn void __pthread_exit(void *result) if (self->next == self) { __tl_unlock(); UNLOCK(self->killlock); + self->detach_state = state; __restore_sigs(&set); exit(0); } @@ -125,10 +139,6 @@ _Noreturn void __pthread_exit(void *result) self->prev->next = self->next; self->prev = self->next = self; - /* This atomic potentially competes with a concurrent pthread_detach - * call; the loser is responsible for freeing thread resources. */ - int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); - if (state==DT_DETACHED && self->map_base) { /* Detached threads must block even implementation-internal * signals, since they will not have a stack in their last @@ -140,16 +150,13 @@ _Noreturn void __pthread_exit(void *result) if (self->robust_list.off) __syscall(SYS_set_robust_list, 0, 3*sizeof(long)); - /* Since __unmapself bypasses the normal munmap code path, - * explicitly wait for vmlock holders first. */ - __vm_wait(); - /* The following call unmaps the thread's stack mapping * and then exits without touching the stack. */ __unmapself(self->map_base, self->map_size); } /* Wake any joiner. */ + a_store(&self->detach_state, DT_EXITED); __wake(&self->detach_state, 1, 1); /* After the kernel thread exits, its tid may be reused. Clear it @@ -314,7 +321,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att new->detach_state = DT_JOINABLE; } new->robust_list.head = &new->robust_list.head; - new->CANARY = self->CANARY; + new->canary = self->canary; new->sysinfo = self->sysinfo; /* Setup argument structure for the new thread on its stack. diff --git a/libc-top-half/musl/src/thread/pthread_mutex_destroy.c b/libc-top-half/musl/src/thread/pthread_mutex_destroy.c index 6d49e68..8d1bf77 100644 --- a/libc-top-half/musl/src/thread/pthread_mutex_destroy.c +++ b/libc-top-half/musl/src/thread/pthread_mutex_destroy.c @@ -1,6 +1,10 @@ -#include +#include "pthread_impl.h" int pthread_mutex_destroy(pthread_mutex_t *mutex) { + /* If the mutex being destroyed is process-shared and has nontrivial + * type (tracking ownership), it might be in the pending slot of a + * robust_list; wait for quiescence. */ + if (mutex->_m_type > 128) __vm_wait(); return 0; } diff --git a/libc-top-half/musl/src/thread/pthread_mutexattr_setprotocol.c b/libc-top-half/musl/src/thread/pthread_mutexattr_setprotocol.c index 511cc32..8b80c1c 100644 --- a/libc-top-half/musl/src/thread/pthread_mutexattr_setprotocol.c +++ b/libc-top-half/musl/src/thread/pthread_mutexattr_setprotocol.c @@ -1,24 +1,23 @@ #include "pthread_impl.h" #include "syscall.h" -static pthread_once_t check_pi_once; -static int check_pi_result; - -static void check_pi() -{ - volatile int lk = 0; - check_pi_result = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0); -} +static volatile int check_pi_result = -1; int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int protocol) { + int r; switch (protocol) { case PTHREAD_PRIO_NONE: a->__attr &= ~8; return 0; case PTHREAD_PRIO_INHERIT: - pthread_once(&check_pi_once, check_pi); - if (check_pi_result) return check_pi_result; + r = check_pi_result; + if (r < 0) { + volatile int lk = 0; + r = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0); + a_store(&check_pi_result, r); + } + if (r) return r; a->__attr |= 8; return 0; case PTHREAD_PRIO_PROTECT: diff --git a/libc-top-half/musl/src/thread/pthread_mutexattr_setrobust.c b/libc-top-half/musl/src/thread/pthread_mutexattr_setrobust.c index 04db92a..30a9ac3 100644 --- a/libc-top-half/musl/src/thread/pthread_mutexattr_setrobust.c +++ b/libc-top-half/musl/src/thread/pthread_mutexattr_setrobust.c @@ -1,22 +1,20 @@ #include "pthread_impl.h" #include "syscall.h" -static pthread_once_t check_robust_once; -static int check_robust_result; - -static void check_robust() -{ - void *p; - size_t l; - check_robust_result = -__syscall(SYS_get_robust_list, 0, &p, &l); -} +static volatile int check_robust_result = -1; int pthread_mutexattr_setrobust(pthread_mutexattr_t *a, int robust) { if (robust > 1U) return EINVAL; if (robust) { - pthread_once(&check_robust_once, check_robust); - if (check_robust_result) return check_robust_result; + int r = check_robust_result; + if (r < 0) { + void *p; + size_t l; + r = -__syscall(SYS_get_robust_list, 0, &p, &l); + a_store(&check_robust_result, r); + } + if (r) return r; a->__attr |= 4; return 0; } diff --git a/libc-top-half/musl/src/thread/s390x/clone.s b/libc-top-half/musl/src/thread/s390x/clone.s index 577748e..2125f20 100644 --- a/libc-top-half/musl/src/thread/s390x/clone.s +++ b/libc-top-half/musl/src/thread/s390x/clone.s @@ -17,6 +17,9 @@ __clone: # if (!tid) syscall(SYS_exit, a(d)); # return tid; + # preserve call-saved register used as syscall arg + stg %r6, 48(%r15) + # create initial stack frame for new thread nill %r3, 0xfff8 aghi %r3, -160 @@ -35,6 +38,9 @@ __clone: lg %r6, 160(%r15) svc 120 + # restore call-saved register + lg %r6, 48(%r15) + # if error or if we're the parent, return ltgr %r2, %r2 bnzr %r14 diff --git a/libc-top-half/musl/src/thread/s390x/syscall_cp.s b/libc-top-half/musl/src/thread/s390x/syscall_cp.s index c1da40d..d094cbf 100644 --- a/libc-top-half/musl/src/thread/s390x/syscall_cp.s +++ b/libc-top-half/musl/src/thread/s390x/syscall_cp.s @@ -14,6 +14,7 @@ __cp_begin: icm %r2, 15, 0(%r2) jne __cp_cancel + stg %r6, 48(%r15) stg %r7, 56(%r15) lgr %r1, %r3 lgr %r2, %r4 @@ -26,6 +27,7 @@ __cp_begin: __cp_end: lg %r7, 56(%r15) + lg %r6, 48(%r15) br %r14 __cp_cancel: diff --git a/libc-top-half/musl/src/thread/sem_open.c b/libc-top-half/musl/src/thread/sem_open.c index de8555c..0ad29de 100644 --- a/libc-top-half/musl/src/thread/sem_open.c +++ b/libc-top-half/musl/src/thread/sem_open.c @@ -12,6 +12,12 @@ #include #include #include "lock.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc undef +#define free undef static struct { ino_t ino; @@ -19,6 +25,7 @@ static struct { int refcnt; } *semtab; static volatile int lock[1]; +volatile int *const __sem_open_lockptr = lock; #define FLAGS (O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK) @@ -163,10 +170,12 @@ int sem_close(sem_t *sem) int i; LOCK(lock); for (i=0; itid) + goto single_threaded; callback = func; context = ctx; diff --git a/libc-top-half/musl/src/thread/vmlock.c b/libc-top-half/musl/src/thread/vmlock.c index 75f3cb7..fa0a8e3 100644 --- a/libc-top-half/musl/src/thread/vmlock.c +++ b/libc-top-half/musl/src/thread/vmlock.c @@ -1,6 +1,8 @@ #include "pthread_impl.h" +#include "fork_impl.h" static volatile int vmlock[2]; +volatile int *const __vmlock_lockptr = vmlock; void __vm_wait() { diff --git a/libc-top-half/musl/src/time/__tz.c b/libc-top-half/musl/src/time/__tz.c index 383d05e..092d343 100644 --- a/libc-top-half/musl/src/time/__tz.c +++ b/libc-top-half/musl/src/time/__tz.c @@ -8,6 +8,12 @@ #endif #include "libc.h" #include "lock.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef #ifdef __wasilibc_unmodified_upstream // timezone data long __timezone = 0; @@ -35,6 +41,7 @@ static char *old_tz = old_tz_buf; static size_t old_tz_size = sizeof old_tz_buf; static volatile int lock[1]; +volatile int *const __timezone_lockptr = lock; static int getint(const char **p) { @@ -183,7 +190,7 @@ static void do_tzset() zi = map; if (map) { int scale = 2; - if (sizeof(time_t) > 4 && map[4]=='2') { + if (map[4]!='1') { size_t skip = zi_dotprod(zi+20, VEC(1,1,8,5,6,1), 6); trans = zi+skip+44+44; scale++; diff --git a/libc-top-half/musl/src/time/timer_create.c b/libc-top-half/musl/src/time/timer_create.c index 455d49f..4bef239 100644 --- a/libc-top-half/musl/src/time/timer_create.c +++ b/libc-top-half/musl/src/time/timer_create.c @@ -2,6 +2,7 @@ #include #include #include "pthread_impl.h" +#include "atomic.h" struct ksigevent { union sigval sigev_value; @@ -32,19 +33,6 @@ static void cleanup_fromsig(void *p) longjmp(p, 1); } -static void timer_handler(int sig, siginfo_t *si, void *ctx) -{ -} - -static void install_handler() -{ - struct sigaction sa = { - .sa_sigaction = timer_handler, - .sa_flags = SA_SIGINFO | SA_RESTART - }; - __libc_sigaction(SIGTIMER, &sa, 0); -} - static void *start(void *arg) { pthread_t self = __pthread_self(); @@ -71,7 +59,7 @@ static void *start(void *arg) int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict res) { - static pthread_once_t once = PTHREAD_ONCE_INIT; + volatile static int init = 0; pthread_t td; pthread_attr_t attr; int r; @@ -83,11 +71,15 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict switch (evp ? evp->sigev_notify : SIGEV_SIGNAL) { case SIGEV_NONE: case SIGEV_SIGNAL: + case SIGEV_THREAD_ID: if (evp) { ksev.sigev_value = evp->sigev_value; ksev.sigev_signo = evp->sigev_signo; ksev.sigev_notify = evp->sigev_notify; - ksev.sigev_tid = 0; + if (evp->sigev_notify == SIGEV_THREAD_ID) + ksev.sigev_tid = evp->sigev_notify_thread_id; + else + ksev.sigev_tid = 0; ksevp = &ksev; } if (syscall(SYS_timer_create, clk, ksevp, &timerid) < 0) @@ -95,7 +87,11 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict *res = (void *)(intptr_t)timerid; break; case SIGEV_THREAD: - pthread_once(&once, install_handler); + if (!init) { + struct sigaction sa = { .sa_handler = SIG_DFL }; + __libc_sigaction(SIGTIMER, &sa, 0); + a_store(&init, 1); + } if (evp->sigev_notify_attributes) attr = *evp->sigev_notify_attributes; else @@ -115,7 +111,7 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict ksev.sigev_value.sival_ptr = 0; ksev.sigev_signo = SIGTIMER; - ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */ + ksev.sigev_notify = SIGEV_THREAD_ID; ksev.sigev_tid = td->tid; if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) timerid = -1; diff --git a/libc-top-half/musl/src/unistd/close.c b/libc-top-half/musl/src/unistd/close.c index 5b38e01..a2105f5 100644 --- a/libc-top-half/musl/src/unistd/close.c +++ b/libc-top-half/musl/src/unistd/close.c @@ -1,5 +1,6 @@ #include #include +#include "aio_impl.h" #include "syscall.h" static int dummy(int fd) diff --git a/libc-top-half/musl/src/unistd/faccessat.c b/libc-top-half/musl/src/unistd/faccessat.c index 76bbd4c..557503e 100644 --- a/libc-top-half/musl/src/unistd/faccessat.c +++ b/libc-top-half/musl/src/unistd/faccessat.c @@ -25,12 +25,17 @@ static int checker(void *p) int faccessat(int fd, const char *filename, int amode, int flag) { - if (!flag || (flag==AT_EACCESS && getuid()==geteuid() && getgid()==getegid())) - return syscall(SYS_faccessat, fd, filename, amode, flag); + if (flag) { + int ret = __syscall(SYS_faccessat2, fd, filename, amode, flag); + if (ret != -ENOSYS) return __syscall_ret(ret); + } - if (flag != AT_EACCESS) + if (flag & ~AT_EACCESS) return __syscall_ret(-EINVAL); + if (!flag || (getuid()==geteuid() && getgid()==getegid())) + return syscall(SYS_faccessat, fd, filename, amode); + char stack[1024]; sigset_t set; pid_t pid; diff --git a/libc-top-half/musl/src/unistd/readlink.c b/libc-top-half/musl/src/unistd/readlink.c index a152d52..32f4537 100644 --- a/libc-top-half/musl/src/unistd/readlink.c +++ b/libc-top-half/musl/src/unistd/readlink.c @@ -4,9 +4,16 @@ ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize) { + char dummy[1]; + if (!bufsize) { + buf = dummy; + bufsize = 1; + } #ifdef SYS_readlink - return syscall(SYS_readlink, path, buf, bufsize); + int r = __syscall(SYS_readlink, path, buf, bufsize); #else - return syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize); + int r = __syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize); #endif + if (buf == dummy && r > 0) r = 0; + return __syscall_ret(r); } diff --git a/libc-top-half/musl/src/unistd/readlinkat.c b/libc-top-half/musl/src/unistd/readlinkat.c index 9af45cd..f79d3d1 100644 --- a/libc-top-half/musl/src/unistd/readlinkat.c +++ b/libc-top-half/musl/src/unistd/readlinkat.c @@ -3,5 +3,12 @@ ssize_t readlinkat(int fd, const char *restrict path, char *restrict buf, size_t bufsize) { - return syscall(SYS_readlinkat, fd, path, buf, bufsize); + char dummy[1]; + if (!bufsize) { + buf = dummy; + bufsize = 1; + } + int r = __syscall(SYS_readlinkat, fd, path, buf, bufsize); + if (buf == dummy && r > 0) r = 0; + return __syscall_ret(r); } diff --git a/libc-top-half/musl/src/unistd/setxid.c b/libc-top-half/musl/src/unistd/setxid.c index 0239f8a..487c1a1 100644 --- a/libc-top-half/musl/src/unistd/setxid.c +++ b/libc-top-half/musl/src/unistd/setxid.c @@ -1,20 +1,19 @@ #include -#include +#include #include "syscall.h" #include "libc.h" -#include "pthread_impl.h" struct ctx { int id, eid, sid; - int nr, err; + int nr, ret; }; static void do_setxid(void *p) { struct ctx *c = p; - if (c->err>0) return; - int ret = -__syscall(c->nr, c->id, c->eid, c->sid); - if (ret && !c->err) { + if (c->ret<0) return; + int ret = __syscall(c->nr, c->id, c->eid, c->sid); + if (ret && !c->ret) { /* If one thread fails to set ids after another has already * succeeded, forcibly killing the process is the only safe * thing to do. State is inconsistent and dangerous. Use @@ -22,18 +21,14 @@ static void do_setxid(void *p) __block_all_sigs(0); __syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL); } - c->err = ret; + c->ret = ret; } int __setxid(int nr, int id, int eid, int sid) { - /* err is initially nonzero so that failure of the first thread does not + /* ret is initially nonzero so that failure of the first thread does not * trigger the safety kill above. */ - struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid, .err = -1 }; + struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid, .ret = 1 }; __synccall(do_setxid, &c); - if (c.err) { - if (c.err>0) errno = c.err; - return -1; - } - return 0; + return __syscall_ret(c.ret); } diff --git a/tools/wasi-headers/src/c_header.rs b/tools/wasi-headers/src/c_header.rs index 4035f19..15b64ee 100644 --- a/tools/wasi-headers/src/c_header.rs +++ b/tools/wasi-headers/src/c_header.rs @@ -1,14 +1,28 @@ use heck::ShoutySnakeCase; +use std::collections::HashMap; +use std::mem; use witx::*; -pub fn to_c_header(doc: &Document, inputs_str: &str) -> String { - let mut ret = String::new(); +pub struct Generated { + pub header: String, + pub source: String, +} - ret.push_str(&format!( +pub fn to_c(doc: &Document, inputs_str: &str) -> Generated { + let mut header = String::new(); + + header.push_str(&format!( r#"/** * THIS FILE IS AUTO-GENERATED from the following files: * {} * + * To regenerate this file execute: + * + * cargo run --manifest-path tools/wasi-headers/Cargo.toml generate-libc + * + * Modifications to this file will cause CI to fail, the code generator tool + * must be modified to change this file. + * * @file * This file describes the [WASI] interface, consisting of functions, types, * and defined values (macros). @@ -54,15 +68,47 @@ extern "C" {{ inputs_str, )); + let mut source = String::new(); + source.push_str(&format!( + r#"/** + * THIS FILE IS AUTO-GENERATED from the following files: + * {} + * + * To regenerate this file execute: + * + * cargo run --manifest-path tools/wasi-headers/Cargo.toml generate-libc + * + * Modifications to this file will cause CI to fail, the code generator tool + * must be modified to change this file. + */ + +#include +#include + +"#, + inputs_str, + )); + + let mut type_constants = HashMap::new(); + for c in doc.constants() { + type_constants.entry(&c.ty).or_insert(Vec::new()).push(c); + } + for nt in doc.typenames() { - print_datatype(&mut ret, &*nt); + print_datatype(&mut header, &*nt); + + if let Some(constants) = type_constants.remove(&nt.name) { + for constant in constants { + print_constant(&mut header, &constant); + } + } } for m in doc.modules() { - print_module(&mut ret, &m); + print_module(&mut header, &mut source, &m); } - ret.push_str( + header.push_str( r#"#ifdef __cplusplus } #endif @@ -71,7 +117,7 @@ extern "C" {{ "#, ); - ret + Generated { header, source } } fn print_datatype(ret: &mut String, nt: &NamedType) { @@ -85,14 +131,11 @@ fn print_datatype(ret: &mut String, nt: &NamedType) { match &nt.tref { TypeRef::Value(v) => match &**v { - Type::Enum(e) => print_enum(ret, &nt.name, e), - Type::Int(i) => print_int(ret, &nt.name, i), - Type::Flags(f) => print_flags(ret, &nt.name, f), - Type::Struct(s) => print_struct(ret, &nt.name, s), - Type::Union(u) => print_union(ret, &nt.name, u), + Type::Record(s) => print_record(ret, &nt.name, s), + Type::Variant(v) => print_variant(ret, &nt.name, v), Type::Handle(h) => print_handle(ret, &nt.name, h), Type::Builtin { .. } - | Type::Array { .. } + | Type::List { .. } | Type::Pointer { .. } | Type::ConstPointer { .. } => print_alias(ret, &nt.name, &nt.tref), }, @@ -101,8 +144,8 @@ fn print_datatype(ret: &mut String, nt: &NamedType) { } fn print_alias(ret: &mut String, name: &Id, dest: &TypeRef) { - match &*dest.type_() { - Type::Array(_) => { + match &**dest.type_() { + Type::List(_) => { // Don't emit arrays as top-level types; instead we special-case // them in places like parameter lists so that we can pass them // as pointer and length pairs. @@ -139,18 +182,18 @@ fn print_alias(ret: &mut String, name: &Id, dest: &TypeRef) { } } -fn print_enum(ret: &mut String, name: &Id, e: &EnumDatatype) { +fn print_enum(ret: &mut String, name: &Id, v: &Variant) { ret.push_str(&format!( "typedef {} __wasi_{}_t;\n", - intrepr_name(e.repr), + intrepr_name(v.tag_repr), ident_name(name) )); ret.push_str("\n"); - for (index, variant) in e.variants.iter().enumerate() { - if !variant.docs.is_empty() { + for (index, case) in v.cases.iter().enumerate() { + if !case.docs.is_empty() { ret.push_str("/**\n"); - for line in variant.docs.lines() { + for line in case.docs.lines() { ret.push_str(&format!(" * {}\n", line)); } ret.push_str(" */\n"); @@ -158,8 +201,8 @@ fn print_enum(ret: &mut String, name: &Id, e: &EnumDatatype) { ret.push_str(&format!( "#define __WASI_{}_{} ({}({}))\n", ident_name(&name).to_shouty_snake_case(), - ident_name(&variant.name).to_shouty_snake_case(), - intrepr_const(e.repr), + ident_name(&case.name).to_shouty_snake_case(), + intrepr_const(v.tag_repr), index )); ret.push_str("\n"); @@ -168,98 +211,61 @@ fn print_enum(ret: &mut String, name: &Id, e: &EnumDatatype) { ret.push_str(&format!( "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", ident_name(name), - e.repr.mem_size() + v.tag_repr.mem_size() )); ret.push_str(&format!( "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", ident_name(name), - e.repr.mem_align() + v.tag_repr.mem_align() )); ret.push_str("\n"); } -fn print_int(ret: &mut String, name: &Id, i: &IntDatatype) { - ret.push_str(&format!( - "typedef {} __wasi_{}_t;\n", - intrepr_name(i.repr), - ident_name(name) - )); - ret.push_str("\n"); - - for (index, const_) in i.consts.iter().enumerate() { - if !const_.docs.is_empty() { - ret.push_str("/**\n"); - for line in const_.docs.lines() { - ret.push_str(&format!(" * {}\n", line)); - } - ret.push_str(" */\n"); +fn print_constant(ret: &mut String, const_: &Constant) { + if !const_.docs.is_empty() { + ret.push_str("/**\n"); + for line in const_.docs.lines() { + ret.push_str(&format!(" * {}\n", line)); } - ret.push_str(&format!( - "#define __WASI_{}_{} ({}({}))\n", - ident_name(&name).to_shouty_snake_case(), - ident_name(&const_.name).to_shouty_snake_case(), - intrepr_const(i.repr), - index - )); - ret.push_str("\n"); + ret.push_str(" */\n"); } - ret.push_str(&format!( - "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", - ident_name(name), - i.repr.mem_size() + "#define __WASI_{}_{} ((__wasi_{}_t){})\n", + ident_name(&const_.ty).to_shouty_snake_case(), + ident_name(&const_.name).to_shouty_snake_case(), + ident_name(&const_.ty), + const_.value, )); - ret.push_str(&format!( - "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", - ident_name(name), - i.repr.mem_align() - )); - ret.push_str("\n"); } -fn print_flags(ret: &mut String, name: &Id, f: &FlagsDatatype) { - ret.push_str(&format!( - "typedef {} __wasi_{}_t;\n", - intrepr_name(f.repr), - ident_name(name) - )); - ret.push_str("\n"); - - for (index, flag) in f.flags.iter().enumerate() { - if !flag.docs.is_empty() { - ret.push_str("/**\n"); - for line in flag.docs.lines() { - ret.push_str(&format!(" * {}\n", line)); +fn print_record(ret: &mut String, name: &Id, s: &RecordDatatype) { + if let Some(repr) = s.bitflags_repr() { + ret.push_str(&format!( + "typedef {} __wasi_{}_t;\n\n", + intrepr_name(repr), + ident_name(name) + )); + for (i, member) in s.members.iter().enumerate() { + if !member.docs.is_empty() { + ret.push_str("/**\n"); + for line in member.docs.lines() { + ret.push_str(&format!(" * {}\n", line)); + } + ret.push_str(" */\n"); } - ret.push_str(" */\n"); + ret.push_str(&format!( + "#define __WASI_{}_{} ((__wasi_{}_t)(1 << {}))\n", + ident_name(name).to_shouty_snake_case(), + ident_name(&member.name).to_shouty_snake_case(), + ident_name(name), + i, + )); + ret.push_str("\n"); } - ret.push_str(&format!( - "#define __WASI_{}_{} ({}({}))\n", - ident_name(name).to_shouty_snake_case(), - ident_name(&flag.name).to_shouty_snake_case(), - intrepr_const(f.repr), - 1u128 << index - )); - ret.push_str("\n"); + return; } - - ret.push_str(&format!( - "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", - ident_name(name), - f.repr.mem_size(), - )); - ret.push_str(&format!( - "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", - ident_name(name), - f.repr.mem_align(), - )); - - ret.push_str("\n"); -} - -fn print_struct(ret: &mut String, name: &Id, s: &StructDatatype) { ret.push_str(&format!( "typedef struct __wasi_{}_t {{\n", ident_name(name) @@ -307,17 +313,20 @@ fn print_struct(ret: &mut String, name: &Id, s: &StructDatatype) { ret.push_str("\n"); } -fn print_union(ret: &mut String, name: &Id, u: &UnionDatatype) { +fn print_variant(ret: &mut String, name: &Id, v: &Variant) { + if v.cases.iter().all(|v| v.tref.is_none()) { + return print_enum(ret, name, v); + } ret.push_str(&format!( "typedef union __wasi_{}_u_t {{\n", ident_name(name) )); - for variant in &u.variants { - if let Some(ref tref) = variant.tref { - if !variant.docs.is_empty() { + for case in &v.cases { + if let Some(tref) = &case.tref { + if !case.docs.is_empty() { ret.push_str(" /**\n"); - for line in variant.docs.lines() { + for line in case.docs.lines() { ret.push_str(&format!(" * {}\n", line)); } ret.push_str(" */\n"); @@ -325,7 +334,7 @@ fn print_union(ret: &mut String, name: &Id, u: &UnionDatatype) { ret.push_str(&format!( " {} {};\n", typeref_name(tref), - ident_name(&variant.name) + ident_name(&case.name) )); } } @@ -336,7 +345,7 @@ fn print_union(ret: &mut String, name: &Id, u: &UnionDatatype) { ident_name(name) )); - ret.push_str(&format!(" {} tag;\n", namedtype_name(&u.tag))); + ret.push_str(&format!(" {} tag;\n", intrepr_name(v.tag_repr))); ret.push_str(&format!(" __wasi_{}_u_t u;\n", ident_name(name))); ret.push_str(&format!("}} __wasi_{}_t;\n", ident_name(name))); @@ -345,29 +354,12 @@ fn print_union(ret: &mut String, name: &Id, u: &UnionDatatype) { ret.push_str(&format!( "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", ident_name(name), - u.mem_size() + v.mem_size() )); ret.push_str(&format!( "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", ident_name(name), - u.mem_align() - )); - - let l = u.union_layout(); - ret.push_str(&format!( - "_Static_assert(offsetof(__wasi_{}_t, u) == {}, \"witx calculated union offset\");\n", - ident_name(name), - l.contents_offset, - )); - ret.push_str(&format!( - "_Static_assert(sizeof(__wasi_{}_u_t) == {}, \"witx calculated union size\");\n", - ident_name(name), - l.contents_size, - )); - ret.push_str(&format!( - "_Static_assert(_Alignof(__wasi_{}_u_t) == {}, \"witx calculated union align\");\n", - ident_name(name), - l.contents_align, + v.mem_align() )); ret.push_str("\n"); @@ -390,25 +382,26 @@ fn print_handle(ret: &mut String, name: &Id, h: &HandleDatatype) { ret.push_str("\n"); } -fn print_module(ret: &mut String, m: &Module) { - ret.push_str("/**\n"); - ret.push_str(&format!(" * @defgroup {}\n", ident_name(&m.name),)); +fn print_module(header: &mut String, source: &mut String, m: &Module) { + header.push_str("/**\n"); + header.push_str(&format!(" * @defgroup {}\n", ident_name(&m.name),)); for line in m.docs.lines() { - ret.push_str(&format!(" * {}\n", line)); + header.push_str(&format!(" * {}\n", line)); } - ret.push_str(" * @{\n"); - ret.push_str(" */\n"); - ret.push_str("\n"); + header.push_str(" * @{\n"); + header.push_str(" */\n"); + header.push_str("\n"); for func in m.funcs() { - print_func(ret, &func, &m.name); + print_func_header(header, &func); + print_func_source(source, &func, &m.name); } - ret.push_str("/** @} */\n"); - ret.push_str("\n"); + header.push_str("/** @} */\n"); + header.push_str("\n"); } -fn print_func(ret: &mut String, func: &InterfaceFunc, module_name: &Id) { +fn print_func_header(ret: &mut String, func: &InterfaceFunc) { if !func.docs.is_empty() { ret.push_str("/**\n"); for line in func.docs.lines() { @@ -419,117 +412,377 @@ fn print_func(ret: &mut String, func: &InterfaceFunc, module_name: &Id) { if !first_result.docs.is_empty() { ret.push_str(" * @return\n"); for line in first_result.docs.lines() { - ret.push_str(&format!(" * {}", line)); + ret.push_str(&format!(" * {}\n", line)); } } } ret.push_str(" */\n"); } - if func.results.is_empty() { - // Special-case "proc_exit" as _Noreturn -- TODO: Encode this in witx. - if func.name.as_str() == "proc_exit" { - ret.push_str("_Noreturn "); + + print_func_signature(ret, func, true); + + if func.results.len() > 0 { + ret.push_str(" __attribute__((__warn_unused_result__))"); + } + + ret.push_str(";\n"); +} + +fn print_func_signature(ret: &mut String, func: &InterfaceFunc, header: bool) { + let mut params = Vec::new(); + for param in func.params.iter() { + add_params( + &mut params, + &ident_name(¶m.name), + ¶m.tref, + ¶m.docs, + ); + } + match func.results.len() { + 0 => { + if func.noreturn { + ret.push_str("_Noreturn "); + } + ret.push_str("void "); } - ret.push_str("void "); - } else { - let first_result = &func.results[0]; - ret.push_str(&format!("{} ", typeref_name(&first_result.tref))); + 1 => { + assert!(!func.noreturn); + push_return_type(ret, &mut params, &func.results[0].tref); + } + _ => panic!("unsupported number of return values"), } ret.push_str(&format!("__wasi_{}(\n", ident_name(&func.name))); - - if func.params.is_empty() && func.results.len() <= 1 { + if params.len() == 0 { ret.push_str(" void\n"); - } - for (index, param) in func.params.iter().enumerate() { - if !param.docs.is_empty() { - ret.push_str(" /**\n"); - for line in param.docs.lines() { - ret.push_str(&format!(" * {}\n", line)); + } else { + for (i, (docs, param)) in params.iter().enumerate() { + if header { + if let Some(docs) = docs { + ret.push_str(" /**\n"); + for line in docs.lines() { + ret.push_str(&format!(" * {}\n", line)); + } + ret.push_str(" */\n"); + } } - ret.push_str(" */\n"); + ret.push_str(" "); + ret.push_str(¶m); + if i != params.len() - 1 { + ret.push_str(","); + } + ret.push_str("\n"); } - add_params(ret, &ident_name(¶m.name), ¶m.tref); - ret.push_str(&format!( - "{}\n", - if index + 1 < func.params.len() || func.results.len() > 1 { - ",\n" - } else { - "" - } - )); + } + ret.push_str(")"); +} + +fn print_func_source(ret: &mut String, func: &InterfaceFunc, module_name: &Id) { + let (params, results) = func.wasm_signature(); + + if func.noreturn { + ret.push_str("_Noreturn "); + } + match results.len() { + 0 => ret.push_str("void "), + 1 => { + ret.push_str(wasm_type(&results[0])); + ret.push_str(" "); + } + _ => unimplemented!(), } - for (index, result) in func.results.iter().enumerate() { - if index == 0 { - // The first result is returned by value above. - continue; + ret.push_str("__imported_"); + ret.push_str(&ident_name(module_name)); + ret.push_str("_"); + ret.push_str(&ident_name(&func.name)); + ret.push_str("("); + for (i, param) in params.iter().enumerate() { + if i > 0 { + ret.push_str(", "); } - if !result.docs.is_empty() { - ret.push_str(" /**\n"); - for line in result.docs.lines() { - ret.push_str(&format!(" * {}\n", line)); - } - ret.push_str(" */\n"); - } - ret.push_str(&format!( - " {} *{}{}\n", - typeref_name(&result.tref), - ident_name(&result.name), - if index + 1 < func.results.len() { - "," - } else { - "" - } - )); + ret.push_str(wasm_type(param)); + ret.push_str(&format!(" arg{}", i)); } - ret.push_str(") __attribute__((\n"); ret.push_str(&format!( " __import_module__(\"{}\"),\n", ident_name(module_name) )); ret.push_str(&format!( - " __import_name__(\"{}\")", + " __import_name__(\"{}\")\n", ident_name(&func.name) )); - if !func.results.is_empty() { - ret.push_str(",\n __warn_unused_result__\n"); + ret.push_str("));\n\n"); + print_func_signature(ret, func, false); + ret.push_str("{\n"); + + // Any string arguments will have their length passed to the raw wasi API, + // but we only took a `char*` as a parameter. Get the length of all string + // arguments here for it to get passed along later. + for param in func.params.iter() { + if let Type::List(ty) = &**param.tref.type_() { + if let Type::Builtin(BuiltinType::Char) = &**ty.type_() { + ret.push_str(&format!( + " size_t {}_len = strlen({0});\n", + ident_name(¶m.name) + )); + } + } + } + + func.call_wasm( + module_name, + &mut C { + src: ret, + params: &func.params, + block_storage: Vec::new(), + blocks: Vec::new(), + }, + ); + + ret.push_str("}\n\n"); + + /// This is a structure which implements the glue necessary to translate + /// between the C API of a function and the desired WASI ABI we're being + /// told it has. + /// + /// It's worth nothing that this will, in the long run, get much fancier. + /// For now this is extremely simple and entirely assumes that the WASI ABI + /// matches our C ABI. This means it will only really generate valid code + /// as-is *today* and won't work for any updates to the WASI ABI in the + /// future. + /// + /// It's hoped that this situation will improve as interface types and witx + /// continue to evolve and there's a more clear path forward for how to + /// translate an interface types signature to a C API. + struct C<'a> { + src: &'a mut String, + params: &'a [InterfaceFuncParam], + block_storage: Vec, + blocks: Vec, + } + + impl Bindgen for C<'_> { + type Operand = String; + + fn push_block(&mut self) { + let prev = mem::replace(self.src, String::new()); + self.block_storage.push(prev); + } + + fn finish_block(&mut self, operand: Option) { + let to_restore = self.block_storage.pop().unwrap(); + let src = mem::replace(self.src, to_restore); + assert!(src.is_empty()); + match operand { + None => self.blocks.push(String::new()), + Some(s) => self.blocks.push(s), + } + } + + fn allocate_space(&mut self, _: usize, _: &NamedType) { + // not necessary due to us taking parameters as pointers + } + + fn emit( + &mut self, + inst: &Instruction<'_>, + operands: &mut Vec, + results: &mut Vec, + ) { + let mut top_as = |cvt: &str| { + let s = operands.pop().unwrap(); + results.push(format!("({}) {}", cvt, s)); + }; + + match inst { + Instruction::GetArg { nth } => { + results.push(ident_name(&self.params[*nth].name)); + } + // For the C bindings right now any parameter which needs its + // address taken is already taken as a pointer, so we can just + // forward the operand to the result. + Instruction::AddrOf => results.push(operands.pop().unwrap()), + + Instruction::I64FromU64 => top_as("int64_t"), + Instruction::I32FromPointer + | Instruction::I32FromConstPointer + | Instruction::I32FromHandle { .. } + | Instruction::I32FromUsize + | Instruction::I32FromChar + | Instruction::I32FromU8 + | Instruction::I32FromS8 + | Instruction::I32FromChar8 + | Instruction::I32FromU16 + | Instruction::I32FromS16 + | Instruction::I32FromU32 => top_as("int32_t"), + + Instruction::I32FromBitflags { .. } | Instruction::I64FromBitflags { .. } => { + // Rely on C's casting for this + results.push(operands.pop().unwrap()); + } + + // No conversion necessary + Instruction::F32FromIf32 + | Instruction::F64FromIf64 + | Instruction::If32FromF32 + | Instruction::If64FromF64 + | Instruction::I64FromS64 + | Instruction::I32FromS32 => results.push(operands.pop().unwrap()), + + Instruction::ListPointerLength => { + let list = operands.pop().unwrap(); + results.push(format!("(int32_t) {}", list)); + results.push(format!("(int32_t) {}_len", list)); + } + Instruction::ReturnPointerGet { n } => { + // We currently match the wasi ABI with the actual + // function's API signature in C, this means when a return + // pointer is asked for we can simply forward our parameter + // that's a return pointer. + results.push(format!("(int32_t) retptr{}", n)); + } + + Instruction::Load { .. } => { + // this is currently skipped because return pointers are + // already evident in parameters and so we don't need to + // load/store from them again + results.push("dummy".to_string()); + } + + Instruction::ReuseReturn => { + results.push("ret".to_string()); + } + + Instruction::TupleLift { .. } => { + // this is currently skipped because tuples are only used + // as return values and those are always returned through + // out-ptrs, so the values have already been passed through + // at this point. + results.push("dummy".to_string()); + } + + Instruction::ResultLift => { + let err = self.blocks.pop().unwrap(); + + // Our ok block should either have done nothing (meaning + // there's no "ok" payload) or it loaded a return pointer + // and/or tuple some values. In all these cases we discard + // the results since out pointers have already been written + // to and we only return the discriminant from the + // function. + let ok = self.blocks.pop().unwrap(); + assert!(ok == "dummy" || ok == ""); + + // Note that we just push the result of the error block. + // Our block management asserts that it's an expression, + // which in this case will basically always be casting the + // error code to an error code variant, which we return. + results.push(err); + } + + // Enums are represented in C simply as the integral tag type + Instruction::EnumLift { ty } => match &**ty.type_() { + Type::Variant(v) => top_as(intrepr_name(v.tag_repr)), + _ => unreachable!(), + }, + Instruction::EnumLower { .. } => top_as("int32_t"), + + Instruction::CallWasm { + module, + name, + params: _, + results: func_results, + } => { + assert!(func_results.len() < 2); + self.src.push_str(" "); + if func_results.len() > 0 { + self.src.push_str(wasm_type(&func_results[0])); + self.src.push_str(" ret = "); + results.push("ret".to_string()); + } + self.src.push_str("__imported_"); + self.src.push_str(module); + self.src.push_str("_"); + self.src.push_str(name); + self.src.push_str("("); + self.src.push_str(&operands.join(", ")); + self.src.push_str(");\n"); + } + + Instruction::Return { amt: 0 } => {} + Instruction::Return { amt: 1 } => { + self.src.push_str(" return "); + self.src.push_str(&operands[0]); + self.src.push_str(";\n"); + } + + other => panic!("unimplemented instruction {:?}", other), + } + } } - ret.push_str("));\n"); - ret.push_str("\n"); } -fn add_params(ret: &mut String, name: &str, tref: &TypeRef) { - match &*tref.type_() { - Type::Builtin(BuiltinType::String) => { - ret.push_str(&format!(" const char *{},\n", name)); - ret.push_str("\n"); - ret.push_str(" /**\n"); - ret.push_str(&format!( - " * The length of the buffer pointed to by `{}`.\n", - name, - )); - ret.push_str(" */\n"); - ret.push_str(&format!(" size_t {}_len", name)); - } - Type::Array(element) => { - ret.push_str(&format!( - " const {} *{},\n", - typeref_name(&element), - name - )); - ret.push_str("\n"); - ret.push_str(" /**\n"); - ret.push_str(&format!( - " * The length of the array pointed to by `{}`.\n", - name, - )); - ret.push_str(" */\n"); - ret.push_str(&format!(" size_t {}_len", name)); +fn push_return_type(ret: &mut String, params: &mut Vec<(Option, String)>, tref: &TypeRef) { + match &**tref.type_() { + Type::Variant(v) => { + assert_eq!(v.cases.len(), 2, "unsupported type as a return value"); + assert!( + v.cases[0].name == "ok", + "unsupported type as a return value" + ); + assert!( + v.cases[1].name == "err", + "unsupported type as a return value" + ); + let err = match &v.cases[1].tref { + Some(ty) => ty, + None => panic!("unsupported type as a return value"), + }; + ret.push_str(&typeref_name(&err)); + ret.push_str(" "); + + let ok = match &v.cases[0].tref { + Some(ty) => ty, + None => return, + }; + match &**ok.type_() { + Type::Record(r) if r.is_tuple() => { + for (i, member) in r.members.iter().enumerate() { + params.push((None, format!("{} *retptr{}", typeref_name(&member.tref), i))); + } + } + _ => { + params.push((None, format!("{} *retptr0", typeref_name(ok)))); + } + } } + _ => panic!("unsupported type as a return value"), + } +} + +fn add_params(params: &mut Vec<(Option, String)>, name: &str, tref: &TypeRef, docs: &str) { + let docs = if docs.is_empty() { + None + } else { + Some(docs.to_string()) + }; + match &**tref.type_() { + Type::List(element) => match &**element.type_() { + Type::Builtin(BuiltinType::Char) => { + params.push((docs, format!("const char *{}", name))); + } + _ => { + params.push((docs, format!("const {} *{}", typeref_name(&element), name))); + params.push(( + Some(format!("The length of the array pointed to by `{}`.", name,)), + format!("size_t {}_len", name), + )); + } + }, _ => { - ret.push_str(&format!(" {} {}", typeref_name(tref), name)); + params.push((docs, format!("{} {}", typeref_name(tref), name))); } } } @@ -540,13 +793,17 @@ fn ident_name(i: &Id) -> String { fn builtin_type_name(b: BuiltinType) -> &'static str { match b { - BuiltinType::String | BuiltinType::Char8 => { + BuiltinType::U8 { lang_c_char: true } => { panic!("no type name for string or char8 builtins") } - BuiltinType::USize => "size_t", - BuiltinType::U8 => "uint8_t", + BuiltinType::U8 { lang_c_char: false } => "uint8_t", BuiltinType::U16 => "uint16_t", - BuiltinType::U32 => "uint32_t", + BuiltinType::U32 { + lang_ptr_size: true, + } => "size_t", + BuiltinType::U32 { + lang_ptr_size: false, + } => "uint32_t", BuiltinType::U64 => "uint64_t", BuiltinType::S8 => "int8_t", BuiltinType::S16 => "int16_t", @@ -554,12 +811,13 @@ fn builtin_type_name(b: BuiltinType) -> &'static str { BuiltinType::S64 => "int64_t", BuiltinType::F32 => "float", BuiltinType::F64 => "double", + BuiltinType::Char => "char32_t", } } fn typeref_name(tref: &TypeRef) -> String { - match &*tref.type_() { - Type::Builtin(BuiltinType::String) | Type::Builtin(BuiltinType::Char8) | Type::Array(_) => { + match &**tref.type_() { + Type::Builtin(BuiltinType::U8 { lang_c_char: true }) | Type::List(_) => { panic!("unsupported grammar: cannot construct name of string or array",) } _ => {} @@ -568,16 +826,11 @@ fn typeref_name(tref: &TypeRef) -> String { match tref { TypeRef::Name(named_type) => namedtype_name(&named_type), TypeRef::Value(anon_type) => match &**anon_type { - Type::Array(_) => unreachable!("arrays excluded above"), + Type::List(_) => unreachable!("arrays excluded above"), Type::Builtin(b) => builtin_type_name(*b).to_string(), Type::Pointer(p) => format!("{} *", typeref_name(&*p)), Type::ConstPointer(p) => format!("const {} *", typeref_name(&*p)), - Type::Int(i) => format!("{}", intrepr_name(i.repr)), - Type::Struct { .. } - | Type::Union { .. } - | Type::Enum { .. } - | Type::Flags { .. } - | Type::Handle { .. } => unreachable!( + Type::Record { .. } | Type::Variant { .. } | Type::Handle { .. } => unreachable!( "wasi should not have anonymous structs, unions, enums, flags, handles" ), }, @@ -585,10 +838,10 @@ fn typeref_name(tref: &TypeRef) -> String { } fn namedtype_name(named_type: &NamedType) -> String { - match &*named_type.type_() { + match &**named_type.type_() { Type::Pointer(p) => format!("{} *", typeref_name(&*p)), Type::ConstPointer(p) => format!("const {} *", typeref_name(&*p)), - Type::Array(_) => unreachable!("arrays excluded above"), + Type::List(_) => unreachable!("arrays excluded above"), _ => format!("__wasi_{}_t", named_type.name.as_str()), } } @@ -610,3 +863,12 @@ fn intrepr_const(i: IntRepr) -> &'static str { IntRepr::U64 => "UINT64_C", } } + +fn wasm_type(wasm: &WasmType) -> &'static str { + match wasm { + WasmType::I32 => "int32_t", + WasmType::I64 => "int64_t", + WasmType::F32 => "float", + WasmType::F64 => "double", + } +} diff --git a/tools/wasi-headers/src/lib.rs b/tools/wasi-headers/src/lib.rs index 09450df..8844c49 100644 --- a/tools/wasi-headers/src/lib.rs +++ b/tools/wasi-headers/src/lib.rs @@ -1,15 +1,12 @@ mod c_header; -use anyhow::{anyhow, Result}; -pub use c_header::to_c_header; -use std::fs; -use std::io; +use anyhow::Result; +pub use c_header::{to_c, Generated}; use std::path::{Path, PathBuf}; use witx::load; -pub fn generate>(inputs: &[P]) -> Result { - // TODO: drop the anyhow! part once witx switches to anyhow. - let doc = load(&inputs).map_err(|e| anyhow!(e.to_string()))?; +pub fn generate>(inputs: &[P]) -> Result { + let doc = load(&inputs)?; let inputs_str = &inputs .iter() @@ -24,20 +21,19 @@ pub fn generate>(inputs: &[P]) -> Result { .collect::>() .join(", "); - Ok(to_c_header(&doc, &inputs_str)) + Ok(to_c(&doc, &inputs_str)) } pub fn snapshot_witx_files() -> Result> { - let snapshot_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("WASI/phases/snapshot/witx"); - let mut inputs = fs::read_dir(snapshot_dir)? - .map(|res| res.map(|e| e.path())) - .collect::, io::Error>>()?; - - inputs.sort(); - Ok(inputs) + witx::phases::snapshot() } pub fn libc_wasi_api_header() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../../libc-bottom-half/headers/public/wasi/api.h") } + +pub fn libc_wasi_api_source() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../libc-bottom-half/sources/__wasilibc_real.c") +} diff --git a/tools/wasi-headers/src/main.rs b/tools/wasi-headers/src/main.rs index 1ec5087..867c31d 100644 --- a/tools/wasi-headers/src/main.rs +++ b/tools/wasi-headers/src/main.rs @@ -3,15 +3,18 @@ extern crate clap; use anyhow::Result; use clap::{Arg, SubCommand}; -use std::fs::File; -use std::io::Write; +use std::fs; use std::path::Path; -use wasi_headers::{generate, libc_wasi_api_header, snapshot_witx_files}; +use wasi_headers::{generate, libc_wasi_api_header, libc_wasi_api_source, snapshot_witx_files}; -pub fn run, Q: AsRef>(inputs: &[P], output: Q) -> Result<()> { +pub fn run( + inputs: &[impl AsRef], + header_output: impl AsRef, + source_output: impl AsRef, +) -> Result<()> { let c_header = generate(inputs)?; - let mut file = File::create(output)?; - file.write_all(c_header.as_bytes())?; + fs::write(header_output, c_header.header)?; + fs::write(source_output, c_header.source)?; Ok(()) } @@ -37,15 +40,19 @@ fn main() -> Result<()> { if matches.subcommand_matches("generate-libc").is_some() { let inputs = snapshot_witx_files()?; - let output = libc_wasi_api_header(); - run(&inputs, &output)?; + run(&inputs, libc_wasi_api_header(), libc_wasi_api_source())?; } else if let Some(generate) = matches.subcommand_matches("generate") { let inputs = generate .values_of("inputs") .expect("required inputs arg") .collect::>(); let output = generate.value_of("output").expect("required output arg"); - run(&inputs, output)?; + let output = Path::new(&output); + run( + &inputs, + output.with_extension("h"), + output.with_extension("c"), + )?; } else { unreachable!("a subcommand must be provided") }; diff --git a/tools/wasi-headers/tests/verify.rs b/tools/wasi-headers/tests/verify.rs index 5ff8327..faae763 100644 --- a/tools/wasi-headers/tests/verify.rs +++ b/tools/wasi-headers/tests/verify.rs @@ -1,17 +1,37 @@ use std::fs; +use std::path::Path; #[test] fn assert_same_as_src() { - let actual = + let actual_header = fs::read_to_string(wasi_headers::libc_wasi_api_header()).expect("read libc wasi/api.h"); + let actual_source = + fs::read_to_string(wasi_headers::libc_wasi_api_source()).expect("read libc wasi/api.h"); let witx_files = wasi_headers::snapshot_witx_files().expect("parse snapshot witx files"); let expected = wasi_headers::generate(&witx_files).expect("header generation"); - if actual == expected { + if actual_header == expected.header && actual_source == expected.source { return; } - eprintln!("The following diff was found between the generated and the"); - eprintln!("source in the tree:"); + if actual_header != expected.header { + diff( + &wasi_headers::libc_wasi_api_header(), + &actual_header, + &expected.header, + ); + } + if actual_header != expected.header { + diff( + &wasi_headers::libc_wasi_api_source(), + &actual_header, + &expected.header, + ); + } +} + +fn diff(path: &Path, actual: &str, expected: &str) { + eprintln!("The following diff was found between the generated copy and the"); + eprintln!("source copy of {:?} in the tree:", path); eprintln!(); let mut expected_line = 1;