]> git.proxmox.com Git - wasi-libc.git/commitdiff
New upstream version 0.0~git20200731.215adc8
authorXimin Luo <infinity0@debian.org>
Fri, 4 Sep 2020 16:27:57 +0000 (17:27 +0100)
committerXimin Luo <infinity0@debian.org>
Fri, 4 Sep 2020 16:27:57 +0000 (17:27 +0100)
98 files changed:
.github/workflows/main.yml
LICENSE
Makefile
basics/crt/crt1.c [deleted file]
basics/include/__errno.h [deleted file]
basics/include/__functions_malloc.h [deleted file]
basics/include/__functions_memcpy.h [deleted file]
basics/include/__header_inttypes.h [deleted file]
basics/include/__macro_PAGESIZE.h [deleted file]
basics/include/__struct_stat.h [deleted file]
basics/include/__struct_timespec.h [deleted file]
basics/include/__typedef_blkcnt_t.h [deleted file]
basics/include/__typedef_blksize_t.h [deleted file]
basics/include/__typedef_clock_t.h [deleted file]
basics/include/__typedef_dev_t.h [deleted file]
basics/include/__typedef_gid_t.h [deleted file]
basics/include/__typedef_ino_t.h [deleted file]
basics/include/__typedef_mode_t.h [deleted file]
basics/include/__typedef_nlink_t.h [deleted file]
basics/include/__typedef_off_t.h [deleted file]
basics/include/__typedef_ssize_t.h [deleted file]
basics/include/__typedef_suseconds_t.h [deleted file]
basics/include/__typedef_time_t.h [deleted file]
basics/include/__typedef_uid_t.h [deleted file]
basics/include/errno.h [deleted file]
basics/include/inttypes.h [deleted file]
basics/include/stdlib.h [deleted file]
basics/include/string.h [deleted file]
basics/include/sys/stat.h [deleted file]
basics/include/sys/types.h [deleted file]
basics/include/time.h [deleted file]
basics/include/wchar.h [deleted file]
basics/sources/abort.c [deleted file]
basics/sources/complex-builtins.c [deleted file]
basics/sources/math/fmin-fmax.c [deleted file]
basics/sources/math/math-builtins.c [deleted file]
basics/sources/reallocarray.c [deleted file]
basics/sources/string.c [deleted file]
expected/wasm32-wasi/defined-symbols.txt
expected/wasm32-wasi/include-all.c
expected/wasm32-wasi/predefined-macros.txt
libc-bottom-half/README.md
libc-bottom-half/cloudlibc/src/libc/poll/poll.c
libc-bottom-half/cloudlibc/src/libc/stdlib/qsort.c [deleted file]
libc-bottom-half/cloudlibc/src/libc/sys/select/pselect.c
libc-bottom-half/crt/crt1-reactor.c [new file with mode: 0644]
libc-bottom-half/crt/crt1.c
libc-bottom-half/headers/public/__errno.h [new file with mode: 0644]
libc-bottom-half/headers/public/__functions_malloc.h [new file with mode: 0644]
libc-bottom-half/headers/public/__functions_memcpy.h [new file with mode: 0644]
libc-bottom-half/headers/public/__header_bits_signal.h [deleted file]
libc-bottom-half/headers/public/__header_inttypes.h [new file with mode: 0644]
libc-bottom-half/headers/public/__header_unistd.h
libc-bottom-half/headers/public/__macro_PAGESIZE.h [new file with mode: 0644]
libc-bottom-half/headers/public/__struct_stat.h [new file with mode: 0644]
libc-bottom-half/headers/public/__struct_timespec.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_blkcnt_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_blksize_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_clock_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_dev_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_gid_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_ino_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_mode_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_nlink_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_off_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_ssize_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_suseconds_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_time_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/__typedef_uid_t.h [new file with mode: 0644]
libc-bottom-half/headers/public/inttypes.h [new file with mode: 0644]
libc-bottom-half/headers/public/stdlib.h
libc-bottom-half/headers/public/wasi/api.h
libc-bottom-half/headers/public/wasi/libc-find-relpath.h
libc-bottom-half/headers/public/wasi/libc.h
libc-bottom-half/headers/public/wchar.h [new file with mode: 0644]
libc-bottom-half/libpreopen/libpreopen.c [deleted file]
libc-bottom-half/mman/mman.c
libc-bottom-half/signal/signal.c [new file with mode: 0644]
libc-bottom-half/sources/abort.c [new file with mode: 0644]
libc-bottom-half/sources/complex-builtins.c [new file with mode: 0644]
libc-bottom-half/sources/errno.c
libc-bottom-half/sources/math/fmin-fmax.c [new file with mode: 0644]
libc-bottom-half/sources/math/math-builtins.c [new file with mode: 0644]
libc-bottom-half/sources/pause.c [deleted file]
libc-bottom-half/sources/posix.c [new file with mode: 0644]
libc-bottom-half/sources/preopens.c [new file with mode: 0644]
libc-bottom-half/sources/reallocarray.c [new file with mode: 0644]
libc-bottom-half/sources/string.c [deleted file]
libc-top-half/README.md
libc-top-half/musl/README
libc-top-half/musl/arch/wasm32/bits/signal.h
libc-top-half/musl/include/signal.h
libc-top-half/musl/include/unistd.h
libc-top-half/musl/src/conf/sysconf.c
libc-top-half/musl/src/exit/exit.c
libc-top-half/musl/src/include/signal.h
libc-top-half/musl/src/internal/stdio_impl.h
tools/wasi-headers/src/c_header.rs

index bcf4f3e57963b01e5557b22eb8f76b1e463b04ed..0270af6c8c94b06258925dbad40c70cb514e06cc 100644 (file)
@@ -16,8 +16,8 @@ jobs:
     - name: Install clang (Windows)
       shell: bash
       run: |
-          curl -fsSLO https://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe
-          7z x LLVM-9.0.0-win64.exe -y -o"llvm"
+          curl -fsSLO https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe
+          7z x LLVM-10.0.0-win64.exe -y -o"llvm"
           echo "::add-path::$(pwd)/llvm/bin"
           echo "::set-env name=WASM_AR::$(pwd)/llvm/bin/llvm-ar.exe"
       if: matrix.os == 'windows-latest'
@@ -34,8 +34,8 @@ jobs:
     - name: Install clang (MacOS)
       shell: bash
       run: |
-        curl -sSf http://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-darwin-apple.tar.xz | tar xJf -
-        export CLANG_DIR=`pwd`/clang+llvm-9.0.0-x86_64-darwin-apple/bin
+        curl -sSfL https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz | tar xJf -
+        export CLANG_DIR=`pwd`/clang+llvm-10.0.0-x86_64-apple-darwin/bin
         echo "::add-path::$CLANG_DIR"
         echo "::set-env name=WASM_CC::$CLANG_DIR/clang"
       if: matrix.os == 'macos-latest'
@@ -43,8 +43,8 @@ jobs:
     - name: Install clang (Linux)
       shell: bash
       run: |
-        curl -sSf https://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz | tar xJf -
-        export CLANG_DIR=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04/bin
+        curl -sSfL https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | tar xJf -
+        export CLANG_DIR=`pwd`/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04/bin
         echo "::add-path::$CLANG_DIR"
         echo "::set-env name=WASM_CC::$CLANG_DIR/clang"
       if: matrix.os == 'ubuntu-latest'
diff --git a/LICENSE b/LICENSE
index bdc0911793b5d12e330fc252cfb6e0292ce97b41..edf56c0db1ede19244940c9b31fcd070cc5d184b 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -8,7 +8,6 @@ their own licenses:
 
 dlmalloc/                     - CC0; see the notice in malloc.c for details
 libc-bottom-half/cloudlibc/   - BSD-2-Clause; see the LICENSE file for details
-libc-bottom-half/libpreopen/  - BSD-2-Clause; see the notice in libpreopen.c for details
 libc-top-half/musl/           - MIT; see the COPYRIGHT file for details
 
 wasi-libc's changes to these files are multi-licensed under the
index f723e55b8c7e2360df5a8a74d0ec139fb5538352..a1d0a315bdc5a5ecc1efc1df896e1fdbd903be1d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-# These variables are specifically meant to be overridable via
-# the make command-line.
+# 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))
@@ -9,34 +9,28 @@ SYSROOT ?= $(CURDIR)/sysroot
 # A directory to install to for "make install".
 INSTALL_DIR ?= /usr/local
 # single or posix
-THREAD_MODEL = single
+THREAD_MODEL ?= single
 # yes or no
-BUILD_DLMALLOC = yes
-BUILD_LIBC_BOTTOM_HALF = yes
-BUILD_LIBC_TOP_HALF = yes
+BUILD_DLMALLOC ?= yes
+BUILD_LIBC_TOP_HALF ?= yes
 # The directory where we're store intermediate artifacts.
-OBJDIR = $(CURDIR)/build
+OBJDIR ?= $(CURDIR)/build
 
 # Check dependencies.
-ifeq ($(BUILD_LIBC_TOP_HALF),yes)
-ifneq ($(BUILD_LIBC_BOTTOM_HALF),yes)
-$(error BUILD_LIBC_TOP_HALF=yes depends on BUILD_LIBC_BOTTOM_HALF=yes)
-endif
-endif
-ifeq ($(BUILD_LIBC_BOTTOM_HALF),yes)
 ifneq ($(BUILD_DLMALLOC),yes)
-$(error BUILD_LIBC_BOTTOM_HALF=yes depends on BUILD_DLMALLOC=yes)
-endif
+$(error build currently depends on BUILD_DLMALLOC=yes)
 endif
 
-# These variables describe the locations of various files and
-# directories in the source tree.
-BASICS_DIR = $(CURDIR)/basics
-BASICS_INC = $(BASICS_DIR)/include
-BASICS_CRT_SOURCES = $(wildcard $(BASICS_DIR)/crt/*.c)
-BASICS_SOURCES = \
-    $(wildcard $(BASICS_DIR)/sources/*.c) \
-    $(wildcard $(BASICS_DIR)/sources/math/*.c)
+# Variables from this point on are not meant to be overridable via the
+# make command-line.
+
+# Set the target variables. Multiarch triples notably omit the vendor field,
+# which happens to be what we do for the main target triple too.
+TARGET_TRIPLE = wasm32-wasi
+MULTIARCH_TRIPLE = wasm32-wasi
+
+# These variables describe the locations of various files and directories in
+# the source tree.
 DLMALLOC_DIR = $(CURDIR)/dlmalloc
 DLMALLOC_SRC_DIR = $(DLMALLOC_DIR)/src
 DLMALLOC_SOURCES = $(DLMALLOC_SRC_DIR)/dlmalloc.c
@@ -46,86 +40,91 @@ LIBC_BOTTOM_HALF_CLOUDLIBC_SRC = $(LIBC_BOTTOM_HALF_DIR)/cloudlibc/src
 LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC = $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/include
 LIBC_BOTTOM_HALF_HEADERS_PUBLIC = $(LIBC_BOTTOM_HALF_DIR)/headers/public
 LIBC_BOTTOM_HALF_HEADERS_PRIVATE = $(LIBC_BOTTOM_HALF_DIR)/headers/private
-LIBC_BOTTOM_HALF_LIBPREOPEN_DIR = $(LIBC_BOTTOM_HALF_DIR)/libpreopen
 LIBC_BOTTOM_HALF_SOURCES = $(LIBC_BOTTOM_HALF_DIR)/sources
 LIBC_BOTTOM_HALF_ALL_SOURCES = \
     $(shell find $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) -name \*.c) \
-    $(LIBC_BOTTOM_HALF_LIBPREOPEN_DIR)/libpreopen.c \
     $(shell find $(LIBC_BOTTOM_HALF_SOURCES) -name \*.c)
 LIBWASI_EMULATED_MMAN_SOURCES = \
     $(shell find $(LIBC_BOTTOM_HALF_DIR)/mman -name \*.c)
+LIBWASI_EMULATED_SIGNAL_SOURCES = \
+    $(shell find $(LIBC_BOTTOM_HALF_DIR)/signal -name \*.c)
+LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \
+    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/signal/psignal.c \
+    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/strsignal.c
 LIBC_BOTTOM_HALF_CRT_SOURCES = $(wildcard $(LIBC_BOTTOM_HALF_DIR)/crt/*.c)
 LIBC_TOP_HALF_DIR = $(CURDIR)/libc-top-half
 LIBC_TOP_HALF_MUSL_DIR = $(LIBC_TOP_HALF_DIR)/musl
 LIBC_TOP_HALF_MUSL_SRC_DIR = $(LIBC_TOP_HALF_MUSL_DIR)/src
 LIBC_TOP_HALF_MUSL_INC = $(LIBC_TOP_HALF_MUSL_DIR)/include
 LIBC_TOP_HALF_MUSL_SOURCES = \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/a64l.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/basename.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/dirname.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/ffs.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/ffsl.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/ffsll.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/fmtmsg.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/getdomainname.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/gethostid.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/getopt.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/getopt_long.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/getsubopt.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/uname.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/nftw.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/errno/strerror.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/htonl.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/htons.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/ntohl.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/ntohs.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/inet_ntop.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/inet_pton.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/inet_aton.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/in6addr_any.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/network/in6addr_loopback.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/fenv/fenv.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/fenv/fesetround.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/fenv/feupdateenv.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/fenv/fesetexceptflag.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/fenv/fegetexceptflag.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/fenv/feholdexcept.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/exit/exit.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/exit/atexit.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/exit/assert.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/exit/quick_exit.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/exit/at_quick_exit.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/strftime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/asctime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/asctime_r.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/ctime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/ctime_r.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/wcsftime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/strptime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/difftime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/timegm.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/ftime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/gmtime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/gmtime_r.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/timespec_get.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/getdate.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/localtime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/localtime_r.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/mktime.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/__tm_to_secs.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/__month_to_secs.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/__secs_to_tm.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/__year_to_secs.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/time/__tz.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/fcntl/creat.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/dirent/alphasort.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/dirent/versionsort.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/env/clearenv.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/env/getenv.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/env/putenv.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/env/setenv.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/env/unsetenv.c \
-    $(LIBC_TOP_HALF_MUSL_SRC_DIR)/unistd/posix_close.c \
+    $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
+        misc/a64l.c \
+        misc/basename.c \
+        misc/dirname.c \
+        misc/ffs.c \
+        misc/ffsl.c \
+        misc/ffsll.c \
+        misc/fmtmsg.c \
+        misc/getdomainname.c \
+        misc/gethostid.c \
+        misc/getopt.c \
+        misc/getopt_long.c \
+        misc/getsubopt.c \
+        misc/uname.c \
+        misc/nftw.c \
+        errno/strerror.c \
+        network/htonl.c \
+        network/htons.c \
+        network/ntohl.c \
+        network/ntohs.c \
+        network/inet_ntop.c \
+        network/inet_pton.c \
+        network/inet_aton.c \
+        network/in6addr_any.c \
+        network/in6addr_loopback.c \
+        fenv/fenv.c \
+        fenv/fesetround.c \
+        fenv/feupdateenv.c \
+        fenv/fesetexceptflag.c \
+        fenv/fegetexceptflag.c \
+        fenv/feholdexcept.c \
+        exit/exit.c \
+        exit/atexit.c \
+        exit/assert.c \
+        exit/quick_exit.c \
+        exit/at_quick_exit.c \
+        time/strftime.c \
+        time/asctime.c \
+        time/asctime_r.c \
+        time/ctime.c \
+        time/ctime_r.c \
+        time/wcsftime.c \
+        time/strptime.c \
+        time/difftime.c \
+        time/timegm.c \
+        time/ftime.c \
+        time/gmtime.c \
+        time/gmtime_r.c \
+        time/timespec_get.c \
+        time/getdate.c \
+        time/localtime.c \
+        time/localtime_r.c \
+        time/mktime.c \
+        time/__tm_to_secs.c \
+        time/__month_to_secs.c \
+        time/__secs_to_tm.c \
+        time/__year_to_secs.c \
+        time/__tz.c \
+        fcntl/creat.c \
+        dirent/alphasort.c \
+        dirent/versionsort.c \
+        env/clearenv.c \
+        env/getenv.c \
+        env/putenv.c \
+        env/setenv.c \
+        env/unsetenv.c \
+        unistd/posix_close.c \
+    ) \
     $(filter-out %/procfdname.c %/syscall.c %/syscall_ret.c %/vdso.c %/version.c, \
                  $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/*.c)) \
     $(filter-out %/flockfile.c %/funlockfile.c %/__lockfile.c %/ftrylockfile.c \
@@ -176,83 +175,72 @@ LIBC_TOP_HALF_ALL_SOURCES = \
     $(LIBC_TOP_HALF_MUSL_SOURCES) \
     $(shell find $(LIBC_TOP_HALF_SOURCES) -name \*.c)
 
-# Set the target variables. Multiarch triples notably omit the vendor
-# field, which happens to be what we do for the main target triple too.
-TARGET_TRIPLE = wasm32-wasi
-MULTIARCH_TRIPLE = wasm32-wasi
-
-# These variables describe the locations of various files and
-# directories in the generated sysroot tree.
-SYSROOT_LIB = $(SYSROOT)/lib/$(MULTIARCH_TRIPLE)
-SYSROOT_INC = $(SYSROOT)/include
-SYSROOT_SHARE = $(SYSROOT)/share/$(MULTIARCH_TRIPLE)
-
 # Set the target.
-override WASM_CFLAGS += --target=$(TARGET_TRIPLE)
+WASM_CFLAGS += --target=$(TARGET_TRIPLE)
 # WebAssembly floating-point match doesn't trap.
 # TODO: Add -fno-signaling-nans when the compiler supports it.
-override WASM_CFLAGS += -fno-trapping-math
+WASM_CFLAGS += -fno-trapping-math
 
 # Configure support for threads.
 ifeq ($(THREAD_MODEL), single)
-override WASM_CFLAGS += -mthread-model single
+WASM_CFLAGS += -mthread-model single
 endif
 ifeq ($(THREAD_MODEL), posix)
-override WASM_CFLAGS += -mthread-model posix -pthread
+WASM_CFLAGS += -mthread-model posix -pthread
 endif
 
 # Set the sysroot.
-override WASM_CFLAGS += --sysroot="$(SYSROOT)"
+WASM_CFLAGS += --sysroot="$(SYSROOT)"
 
+# These variables describe the locations of various files and directories in
+# the build tree.
 objs = $(patsubst $(CURDIR)/%.c,$(OBJDIR)/%.o,$(1))
-override BASICS_OBJS = $(call objs,$(BASICS_SOURCES))
-override DLMALLOC_OBJS = $(call objs,$(DLMALLOC_SOURCES))
-override LIBC_BOTTOM_HALF_ALL_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_ALL_SOURCES))
-override LIBC_TOP_HALF_ALL_OBJS = $(call objs,$(LIBC_TOP_HALF_ALL_SOURCES))
-override LIBC_OBJS := $(BASICS_OBJS)
+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)
-override LIBC_OBJS += $(DLMALLOC_OBJS)
+LIBC_OBJS += $(DLMALLOC_OBJS)
 endif
-ifeq ($(BUILD_LIBC_BOTTOM_HALF),yes)
-# Override basics' string.o with libc-bottom-half's.
-override LIBC_OBJS := $(filter-out %/string.o,$(LIBC_OBJS))
 # Add libc-bottom-half's objects.
-override LIBC_OBJS += $(LIBC_BOTTOM_HALF_ALL_OBJS)
-endif
+LIBC_OBJS += $(LIBC_BOTTOM_HALF_ALL_OBJS)
 ifeq ($(BUILD_LIBC_TOP_HALF),yes)
-# Override libc-bottom-half's string.o with libc-top-half's.
-override LIBC_OBJS := $(filter-out %/string.o,$(LIBC_OBJS))
-# Override libc-bottom-half's qsort.o with libc-top-half's.
-override LIBC_OBJS := $(filter-out %/qsort.o,$(LIBC_OBJS))
 # libc-top-half is musl.
-override LIBC_OBJS += $(LIBC_TOP_HALF_ALL_OBJS)
+LIBC_OBJS += $(LIBC_TOP_HALF_ALL_OBJS)
 endif
-override MUSL_PRINTSCAN_OBJS = $(call objs,$(MUSL_PRINTSCAN_SOURCES))
-override MUSL_PRINTSCAN_LONG_DOUBLE_OBJS = $(patsubst %.o,%.long-double.o,$(MUSL_PRINTSCAN_OBJS))
-override MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS = $(patsubst %.o,%.no-floating-point.o,$(MUSL_PRINTSCAN_OBJS))
-override LIBWASI_EMULATED_MMAN_OBJS = $(call objs,$(LIBWASI_EMULATED_MMAN_SOURCES))
+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_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES))
+LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES))
+
+# These variables describe the locations of various files and
+# directories in the generated sysroot tree.
+SYSROOT_LIB := $(SYSROOT)/lib/$(MULTIARCH_TRIPLE)
+SYSROOT_INC = $(SYSROOT)/include
+SYSROOT_SHARE = $(SYSROOT)/share/$(MULTIARCH_TRIPLE)
 
 # Files from musl's include directory that we don't want to install in the
 # sysroot's include directory.
-override MUSL_OMIT_HEADERS :=
+MUSL_OMIT_HEADERS :=
 
 # Remove files which aren't headers (we generate alltypes.h below).
-override MUSL_OMIT_HEADERS += \
+MUSL_OMIT_HEADERS += \
     "bits/syscall.h.in" \
     "bits/alltypes.h.in" \
     "alltypes.h.in"
 
 # Use the compiler's version of these headers.
-override MUSL_OMIT_HEADERS += \
+MUSL_OMIT_HEADERS += \
     "stdarg.h" \
     "stddef.h"
 
 # Use the WASI errno definitions.
-override MUSL_OMIT_HEADERS += \
+MUSL_OMIT_HEADERS += \
     "bits/errno.h"
 
 # Remove headers that aren't supported yet or that aren't relevant for WASI.
-override MUSL_OMIT_HEADERS += \
+MUSL_OMIT_HEADERS += \
     "sys/procfs.h" \
     "sys/user.h" \
     "sys/kd.h" "sys/vt.h" "sys/soundcard.h" "sys/sem.h" \
@@ -309,15 +297,14 @@ override MUSL_OMIT_HEADERS += \
     "netinet/ether.h" \
     "sys/timerfd.h" \
     "libintl.h" \
-    "sys/sysmacros.h" \
-    "utime.h"
+    "sys/sysmacros.h"
 
 ifeq ($(THREAD_MODEL), single)
 # Remove headers not supported in single-threaded mode.
-override MUSL_OMIT_HEADERS += "aio.h" "pthread.h"
+MUSL_OMIT_HEADERS += "aio.h" "pthread.h"
 endif
 
-default: check
+default: finish
 
 $(SYSROOT_LIB)/libc.a: $(LIBC_OBJS)
 
@@ -327,6 +314,8 @@ $(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-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS)
+
 %.a:
        @mkdir -p "$(@D)"
        # On Windows, the commandline for the ar invocation got too long, so it needs to be split up.
@@ -338,14 +327,17 @@ $(SYSROOT_LIB)/libwasi-emulated-mman.a: $(LIBWASI_EMULATED_MMAN_OBJS)
        # silently dropping the tail.
        $(WASM_AR) crs $@ $(wordlist 800, 100000, $^)
 
-$(MUSL_PRINTSCAN_OBJS): override WASM_CFLAGS += \
+$(MUSL_PRINTSCAN_OBJS): WASM_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): override WASM_CFLAGS += \
+$(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS): WASM_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 += \
+           -D_WASI_EMULATED_SIGNAL
+
 $(OBJDIR)/%.long-double.o: $(CURDIR)/%.c include_dirs
        @mkdir -p "$(@D)"
        "$(WASM_CC)" $(WASM_CFLAGS) -MD -MP -o $@ -c $<
@@ -360,15 +352,15 @@ $(OBJDIR)/%.o: $(CURDIR)/%.c include_dirs
 
 -include $(shell find $(OBJDIR) -name \*.d)
 
-$(DLMALLOC_OBJS): override WASM_CFLAGS += \
+$(DLMALLOC_OBJS): WASM_CFLAGS += \
     -I$(DLMALLOC_INC)
 
-startup_files $(LIBC_BOTTOM_HALF_ALL_OBJS): override WASM_CFLAGS += \
+startup_files $(LIBC_BOTTOM_HALF_ALL_OBJS): WASM_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): override WASM_CFLAGS += \
+$(LIBC_TOP_HALF_ALL_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS): WASM_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 \
@@ -389,7 +381,6 @@ include_dirs:
        # Install the include files.
        #
        mkdir -p "$(SYSROOT_INC)"
-       cp -r "$(BASICS_INC)" "$(SYSROOT)"
        cp -r "$(LIBC_BOTTOM_HALF_HEADERS_PUBLIC)"/* "$(SYSROOT_INC)"
 
        # Generate musl's bits/alltypes.h header.
@@ -408,19 +399,13 @@ include_dirs:
        # Remove selected header files.
        $(RM) $(patsubst %,$(SYSROOT_INC)/%,$(MUSL_OMIT_HEADERS))
 
-ifeq ($(BUILD_LIBC_BOTTOM_HALF),no)
-override CRT_SOURCES = $(BASICS_CRT_SOURCES)
-else
-override CRT_SOURCES = $(LIBC_BOTTOM_HALF_CRT_SOURCES)
-endif
-
 startup_files: include_dirs
        #
        # Build the startup files.
        #
        @mkdir -p "$(OBJDIR)"
        cd "$(OBJDIR)" && \
-       "$(WASM_CC)" $(WASM_CFLAGS) -c $(CRT_SOURCES) -MD -MP && \
+       "$(WASM_CC)" $(WASM_CFLAGS) -c $(LIBC_BOTTOM_HALF_CRT_SOURCES) -MD -MP && \
        mkdir -p "$(SYSROOT_LIB)" && \
        mv *.o "$(SYSROOT_LIB)"
 
@@ -428,7 +413,8 @@ libc: include_dirs \
     $(SYSROOT_LIB)/libc.a \
     $(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-mman.a \
+    $(SYSROOT_LIB)/libwasi-emulated-signal.a
 
 finish: startup_files libc
        #
@@ -443,41 +429,50 @@ finish: startup_files libc
        #
        mkdir -p "$(SYSROOT_SHARE)"
 
+       #
        # Collect symbol information.
-       # TODO: Use llvm-nm --extern-only instead of grep. This is blocked on
-       # 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.
+       #
+       @# TODO: Use llvm-nm --extern-only instead of grep. This is blocked on
+       @# 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 \
            |grep ' [[:upper:]] ' |sed 's/.* [[:upper:]] //' |LC_ALL=C sort > "$(SYSROOT_SHARE)/defined-symbols.txt"
-       for undef_sym in $$("$(WASM_NM)" --undefined-only "$(SYSROOT_LIB)"/*.a "$(SYSROOT_LIB)"/*.o \
+       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" \
            > "$(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 |grep -v /bits/); do \
-           echo '#include <'$$header'>' | sed 's/include\///' ; \
+         for header in $$(find include -type f -not -name mman.h -not -name signal.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
 
+       #
        # Test that it compiles.
+       #
        "$(WASM_CC)" $(WASM_CFLAGS) -fsyntax-only "$(SYSROOT_SHARE)/include-all.c" -Wno-\#warnings
 
-       # Collect all the predefined macros, except for compiler version macros
-       # which we don't need to track here. For the __*_ATOMIC_*_LOCK_FREE
-       # macros, squash individual compiler names to attempt, toward keeping
-       # these files compiler-independent.
        #
-       # We have to add `-isystem $(SYSROOT_INC)` because otherwise clang puts
-       # its builtin include path first, which produces compiler-specific
-       # output.
+       # Collect all the predefined macros, except for compiler version macros
+       # which we don't need to track here.
        #
-       # 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.
+       @#
+       @# For the __*_ATOMIC_*_LOCK_FREE macros, squash individual compiler names
+       @# to attempt, toward keeping these files compiler-independent.
+       @#
+       @# We have to add `-isystem $(SYSROOT_INC)` because otherwise clang puts
+       @# its builtin include path first, which produces compiler-specific
+       @# output.
+       @#
+       @# 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" \
            -isystem $(SYSROOT_INC) \
            -std=gnu17 \
@@ -498,17 +493,16 @@ finish: startup_files libc
            | grep -v '^#define __FLT16_' \
            > "$(SYSROOT_SHARE)/predefined-macros.txt"
 
-       #
-       # The build succeeded! The generated sysroot is in $(SYSROOT).
-       #
-
-check: finish
        # Check that the computed metadata matches the expected metadata.
        # 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)"
 
-.PHONY: default startup_files libc finish check install include_dirs
+.PHONY: default startup_files libc finish install include_dirs
diff --git a/basics/crt/crt1.c b/basics/crt/crt1.c
deleted file mode 100644 (file)
index 744baab..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-extern void __wasm_call_ctors(void);
-extern int __original_main(void);
-extern void __prepare_for_exit(void);
-void _Exit(int) __attribute__((noreturn));
-
-void _start(void) {
-    // The linker synthesizes this to call constructors.
-    __wasm_call_ctors();
-
-    // Call `__original_main` which will either be the application's zero-argument
-    // `__original_main` function or a libc routine which calls `__main_void`.
-    // TODO: Call `main` directly once we no longer have to support old compilers.
-    int r = __original_main();
-
-    // Call atexit functions, destructors, stdio cleanup, etc.
-    __prepare_for_exit();
-
-    // If main exited successfully, just return, otherwise call _Exit.
-    if (r != 0) {
-        _Exit(r);
-    }
-}
diff --git a/basics/include/__errno.h b/basics/include/__errno.h
deleted file mode 100644 (file)
index 5e90f29..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __wasm_basics___errno_h
-#define __wasm_basics___errno_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-extern thread_local int errno;
-#else
-extern _Thread_local int errno;
-#endif
-
-#define errno errno
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/basics/include/__functions_malloc.h b/basics/include/__functions_malloc.h
deleted file mode 100644 (file)
index 2b01669..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __wasm_basics___functions_malloc_h
-#define __wasm_basics___functions_malloc_h
-
-#define __need_size_t
-#define __need_wchar_t
-#define __need_NULL
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void *malloc(size_t __size) __attribute__((__malloc__, __warn_unused_result__));
-void free(void *__ptr);
-void *calloc(size_t __nmemb, size_t __size) __attribute__((__malloc__, __warn_unused_result__));
-void *realloc(void *__ptr, size_t __size) __attribute__((__warn_unused_result__));
-
-#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-void *reallocarray(void *__ptr, size_t __nmemb, size_t __size) __attribute__((__warn_unused_result__));
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/basics/include/__functions_memcpy.h b/basics/include/__functions_memcpy.h
deleted file mode 100644 (file)
index ed3df0f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __wasm_basics___functions_memcpy_h
-#define __wasm_basics___functions_memcpy_h
-
-#define __need_size_t
-#define __need_NULL
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void *memcpy(void *__restrict__ __dst, const void *__restrict__ __src, size_t __n) __attribute__((__nothrow__, __leaf__, __nonnull__(1, 2)));
-void *memmove(void *__dst, const void *__src, size_t __n) __attribute__((__nothrow__, __leaf__, __nonnull__(1, 2)));
-void *memset(void *__dst, int __c, size_t __n) __attribute__((__nothrow__, __leaf__, __nonnull__(1)));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/basics/include/__header_inttypes.h b/basics/include/__header_inttypes.h
deleted file mode 100644 (file)
index b64e2f2..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-#ifndef __wasm_basics___include_inttypes_h
-#define __wasm_basics___include_inttypes_h
-
-#include <stdint.h>
-
-#define __need_wchar_t
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct { intmax_t quot, rem; } imaxdiv_t;
-
-intmax_t  imaxabs(intmax_t);
-imaxdiv_t imaxdiv(intmax_t, intmax_t);
-intmax_t  strtoimax(const char *__restrict, char **__restrict, int);
-uintmax_t strtoumax(const char *__restrict, char **__restrict, int);
-intmax_t  wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int);
-uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int);
-
-#define PRId16 __INT16_FMTd__
-#define PRIi16 __INT16_FMTi__
-#define PRId32 __INT32_FMTd__
-#define PRIi32 __INT32_FMTi__
-#define PRId64 __INT64_FMTd__
-#define PRIi64 __INT64_FMTi__
-#define PRId8 __INT8_FMTd__
-#define PRIi8 __INT8_FMTi__
-#define PRIdMAX __INTMAX_FMTd__
-#define PRIiMAX __INTMAX_FMTi__
-#define PRIdPTR __INTPTR_FMTd__
-#define PRIiPTR __INTPTR_FMTi__
-#define PRIdFAST16 __INT_FAST16_FMTd__
-#define PRIiFAST16 __INT_FAST16_FMTi__
-#define PRIdFAST32 __INT_FAST32_FMTd__
-#define PRIiFAST32 __INT_FAST32_FMTi__
-#define PRIdFAST64 __INT_FAST64_FMTd__
-#define PRIiFAST64 __INT_FAST64_FMTi__
-#define PRIdFAST8 __INT_FAST8_FMTd__
-#define PRIiFAST8 __INT_FAST8_FMTi__
-#define PRIdLEAST16 __INT_LEAST16_FMTd__
-#define PRIiLEAST16 __INT_LEAST16_FMTi__
-#define PRIdLEAST32 __INT_LEAST32_FMTd__
-#define PRIiLEAST32 __INT_LEAST32_FMTi__
-#define PRIdLEAST64 __INT_LEAST64_FMTd__
-#define PRIiLEAST64 __INT_LEAST64_FMTi__
-#define PRIdLEAST8 __INT_LEAST8_FMTd__
-#define PRIiLEAST8 __INT_LEAST8_FMTi__
-#define PRIX16 __UINT16_FMTX__
-#define PRIo16 __UINT16_FMTo__
-#define PRIu16 __UINT16_FMTu__
-#define PRIx16 __UINT16_FMTx__
-#define PRIX32 __UINT32_FMTX__
-#define PRIo32 __UINT32_FMTo__
-#define PRIu32 __UINT32_FMTu__
-#define PRIx32 __UINT32_FMTx__
-#define PRIX64 __UINT64_FMTX__
-#define PRIo64 __UINT64_FMTo__
-#define PRIu64 __UINT64_FMTu__
-#define PRIx64 __UINT64_FMTx__
-#define PRIX8 __UINT8_FMTX__
-#define PRIo8 __UINT8_FMTo__
-#define PRIu8 __UINT8_FMTu__
-#define PRIx8 __UINT8_FMTx__
-#define PRIXMAX __UINTMAX_FMTX__
-#define PRIoMAX __UINTMAX_FMTo__
-#define PRIuMAX __UINTMAX_FMTu__
-#define PRIxMAX __UINTMAX_FMTx__
-#define PRIXPTR __UINTPTR_FMTX__
-#define PRIoPTR __UINTPTR_FMTo__
-#define PRIuPTR __UINTPTR_FMTu__
-#define PRIxPTR __UINTPTR_FMTx__
-#define PRIXFAST16 __UINT_FAST16_FMTX__
-#define PRIoFAST16 __UINT_FAST16_FMTo__
-#define PRIuFAST16 __UINT_FAST16_FMTu__
-#define PRIxFAST16 __UINT_FAST16_FMTx__
-#define PRIXFAST32 __UINT_FAST32_FMTX__
-#define PRIoFAST32 __UINT_FAST32_FMTo__
-#define PRIuFAST32 __UINT_FAST32_FMTu__
-#define PRIxFAST32 __UINT_FAST32_FMTx__
-#define PRIXFAST64 __UINT_FAST64_FMTX__
-#define PRIoFAST64 __UINT_FAST64_FMTo__
-#define PRIuFAST64 __UINT_FAST64_FMTu__
-#define PRIxFAST64 __UINT_FAST64_FMTx__
-#define PRIXFAST8 __UINT_FAST8_FMTX__
-#define PRIoFAST8 __UINT_FAST8_FMTo__
-#define PRIuFAST8 __UINT_FAST8_FMTu__
-#define PRIxFAST8 __UINT_FAST8_FMTx__
-#define PRIXLEAST16 __UINT_LEAST16_FMTX__
-#define PRIoLEAST16 __UINT_LEAST16_FMTo__
-#define PRIuLEAST16 __UINT_LEAST16_FMTu__
-#define PRIxLEAST16 __UINT_LEAST16_FMTx__
-#define PRIXLEAST32 __UINT_LEAST32_FMTX__
-#define PRIoLEAST32 __UINT_LEAST32_FMTo__
-#define PRIuLEAST32 __UINT_LEAST32_FMTu__
-#define PRIxLEAST32 __UINT_LEAST32_FMTx__
-#define PRIXLEAST64 __UINT_LEAST64_FMTX__
-#define PRIoLEAST64 __UINT_LEAST64_FMTo__
-#define PRIuLEAST64 __UINT_LEAST64_FMTu__
-#define PRIxLEAST64 __UINT_LEAST64_FMTx__
-#define PRIXLEAST8 __UINT_LEAST8_FMTX__
-#define PRIoLEAST8 __UINT_LEAST8_FMTo__
-#define PRIuLEAST8 __UINT_LEAST8_FMTu__
-#define PRIxLEAST8 __UINT_LEAST8_FMTx__
-
-#define SCNd16 __INT16_FMTd__
-#define SCNi16 __INT16_FMTi__
-#define SCNd32 __INT32_FMTd__
-#define SCNi32 __INT32_FMTi__
-#define SCNd64 __INT64_FMTd__
-#define SCNi64 __INT64_FMTi__
-#define SCNd8 __INT8_FMTd__
-#define SCNi8 __INT8_FMTi__
-#define SCNdMAX __INTMAX_FMTd__
-#define SCNiMAX __INTMAX_FMTi__
-#define SCNdPTR __INTPTR_FMTd__
-#define SCNiPTR __INTPTR_FMTi__
-#define SCNdFAST16 __INT_FAST16_FMTd__
-#define SCNiFAST16 __INT_FAST16_FMTi__
-#define SCNdFAST32 __INT_FAST32_FMTd__
-#define SCNiFAST32 __INT_FAST32_FMTi__
-#define SCNdFAST64 __INT_FAST64_FMTd__
-#define SCNiFAST64 __INT_FAST64_FMTi__
-#define SCNdFAST8 __INT_FAST8_FMTd__
-#define SCNiFAST8 __INT_FAST8_FMTi__
-#define SCNdLEAST16 __INT_LEAST16_FMTd__
-#define SCNiLEAST16 __INT_LEAST16_FMTi__
-#define SCNdLEAST32 __INT_LEAST32_FMTd__
-#define SCNiLEAST32 __INT_LEAST32_FMTi__
-#define SCNdLEAST64 __INT_LEAST64_FMTd__
-#define SCNiLEAST64 __INT_LEAST64_FMTi__
-#define SCNdLEAST8 __INT_LEAST8_FMTd__
-#define SCNiLEAST8 __INT_LEAST8_FMTi__
-#define SCNo16 __UINT16_FMTo__
-#define SCNu16 __UINT16_FMTu__
-#define SCNx16 __UINT16_FMTx__
-#define SCNo32 __UINT32_FMTo__
-#define SCNu32 __UINT32_FMTu__
-#define SCNx32 __UINT32_FMTx__
-#define SCNo64 __UINT64_FMTo__
-#define SCNu64 __UINT64_FMTu__
-#define SCNx64 __UINT64_FMTx__
-#define SCNo8 __UINT8_FMTo__
-#define SCNu8 __UINT8_FMTu__
-#define SCNx8 __UINT8_FMTx__
-#define SCNoMAX __UINTMAX_FMTo__
-#define SCNuMAX __UINTMAX_FMTu__
-#define SCNxMAX __UINTMAX_FMTx__
-#define SCNoPTR __UINTPTR_FMTo__
-#define SCNuPTR __UINTPTR_FMTu__
-#define SCNxPTR __UINTPTR_FMTx__
-#define SCNoFAST16 __UINT_FAST16_FMTo__
-#define SCNuFAST16 __UINT_FAST16_FMTu__
-#define SCNxFAST16 __UINT_FAST16_FMTx__
-#define SCNoFAST32 __UINT_FAST32_FMTo__
-#define SCNuFAST32 __UINT_FAST32_FMTu__
-#define SCNxFAST32 __UINT_FAST32_FMTx__
-#define SCNoFAST64 __UINT_FAST64_FMTo__
-#define SCNuFAST64 __UINT_FAST64_FMTu__
-#define SCNxFAST64 __UINT_FAST64_FMTx__
-#define SCNoFAST8 __UINT_FAST8_FMTo__
-#define SCNuFAST8 __UINT_FAST8_FMTu__
-#define SCNxFAST8 __UINT_FAST8_FMTx__
-#define SCNoLEAST16 __UINT_LEAST16_FMTo__
-#define SCNuLEAST16 __UINT_LEAST16_FMTu__
-#define SCNxLEAST16 __UINT_LEAST16_FMTx__
-#define SCNoLEAST32 __UINT_LEAST32_FMTo__
-#define SCNuLEAST32 __UINT_LEAST32_FMTu__
-#define SCNxLEAST32 __UINT_LEAST32_FMTx__
-#define SCNoLEAST64 __UINT_LEAST64_FMTo__
-#define SCNuLEAST64 __UINT_LEAST64_FMTu__
-#define SCNxLEAST64 __UINT_LEAST64_FMTx__
-#define SCNoLEAST8 __UINT_LEAST8_FMTo__
-#define SCNuLEAST8 __UINT_LEAST8_FMTu__
-#define SCNxLEAST8 __UINT_LEAST8_FMTx__
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/basics/include/__macro_PAGESIZE.h b/basics/include/__macro_PAGESIZE.h
deleted file mode 100644 (file)
index efd7b3a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __wasm_basics___macro_PAGESIZE_h
-#define __wasm_basics___macro_PAGESIZE_h
-
-/*
- * The page size in WebAssembly is fixed at 64 KiB. If this ever changes,
- * it's expected that applications will need to opt in, so we can change
- * this.
- */
-#define PAGESIZE (0x10000)
-
-#endif
diff --git a/basics/include/__struct_stat.h b/basics/include/__struct_stat.h
deleted file mode 100644 (file)
index 204387a..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __wasm_basics___struct_stat_h
-#define __wasm_basics___struct_stat_h
-
-#include <__typedef_dev_t.h>
-#include <__typedef_ino_t.h>
-#include <__typedef_nlink_t.h>
-#include <__typedef_mode_t.h>
-#include <__typedef_uid_t.h>
-#include <__typedef_gid_t.h>
-#include <__typedef_off_t.h>
-#include <__typedef_blksize_t.h>
-#include <__typedef_blkcnt_t.h>
-#include <__struct_timespec.h>
-
-struct stat {
-    dev_t st_dev;
-    ino_t st_ino;
-    nlink_t st_nlink;
-
-    mode_t st_mode;
-    uid_t st_uid;
-    gid_t st_gid;
-    unsigned int __pad0;
-    dev_t st_rdev;
-    off_t st_size;
-    blksize_t st_blksize;
-    blkcnt_t st_blocks;
-
-    struct timespec st_atim;
-    struct timespec st_mtim;
-    struct timespec st_ctim;
-    long long __reserved[3];
-};
-
-#endif
diff --git a/basics/include/__struct_timespec.h b/basics/include/__struct_timespec.h
deleted file mode 100644 (file)
index 695d89a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __wasm_basics___struct_timespec_h
-#define __wasm_basics___struct_timespec_h
-
-#include <__typedef_time_t.h>
-
-/* As specified in POSIX. */
-struct timespec {
-    time_t tv_sec;
-    long tv_nsec;
-};
-
-#endif
diff --git a/basics/include/__typedef_blkcnt_t.h b/basics/include/__typedef_blkcnt_t.h
deleted file mode 100644 (file)
index 12807e6..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __wasm_basics___typedef_blkcnt_t_h
-#define __wasm_basics___typedef_blkcnt_t_h
-
-/* Define these as 64-bit signed integers to support files larger than 2 GiB. */
-typedef long long blkcnt_t;
-
-#endif
diff --git a/basics/include/__typedef_blksize_t.h b/basics/include/__typedef_blksize_t.h
deleted file mode 100644 (file)
index 958fe4a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __wasm_basics___typedef_blksize_t_h
-#define __wasm_basics___typedef_blksize_t_h
-
-typedef long blksize_t;
-
-#endif
diff --git a/basics/include/__typedef_clock_t.h b/basics/include/__typedef_clock_t.h
deleted file mode 100644 (file)
index cb2ce36..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __wasm_basics___typedef_clock_t_h
-#define __wasm_basics___typedef_clock_t_h
-
-/* Define this as a 64-bit signed integer to avoid wraparounds. */
-typedef long long clock_t;
-
-#endif
diff --git a/basics/include/__typedef_dev_t.h b/basics/include/__typedef_dev_t.h
deleted file mode 100644 (file)
index a1b2f6f..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __wasm_basics___typedef_dev_t_h
-#define __wasm_basics___typedef_dev_t_h
-
-/* Define these as 64-bit integers to support billions of devices. */
-typedef unsigned long long dev_t;
-
-#endif
diff --git a/basics/include/__typedef_gid_t.h b/basics/include/__typedef_gid_t.h
deleted file mode 100644 (file)
index 84dff90..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __wasm_basics___typedef_gid_t_h
-#define __wasm_basics___typedef_gid_t_h
-
-typedef unsigned gid_t;
-
-#endif
diff --git a/basics/include/__typedef_ino_t.h b/basics/include/__typedef_ino_t.h
deleted file mode 100644 (file)
index 1b3ed4c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __wasm_basics___typedef_ino_t_h
-#define __wasm_basics___typedef_ino_t_h
-
-/* Define these as 64-bit integers to support billions of inodes. */
-typedef unsigned long long ino_t;
-
-#endif
diff --git a/basics/include/__typedef_mode_t.h b/basics/include/__typedef_mode_t.h
deleted file mode 100644 (file)
index 398f64c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __wasm_basics___typedef_mode_t_h
-#define __wasm_basics___typedef_mode_t_h
-
-typedef unsigned mode_t;
-
-#endif
diff --git a/basics/include/__typedef_nlink_t.h b/basics/include/__typedef_nlink_t.h
deleted file mode 100644 (file)
index b31ac62..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __wasm_basics___typedef_nlink_t_h
-#define __wasm_basics___typedef_nlink_t_h
-
-/* Define these as 64-bit unsigned integers to support billions of links. */
-typedef unsigned long long nlink_t;
-
-#endif
diff --git a/basics/include/__typedef_off_t.h b/basics/include/__typedef_off_t.h
deleted file mode 100644 (file)
index 49fe7d4..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __wasm_basics___typedef_off_t_h
-#define __wasm_basics___typedef_off_t_h
-
-/* Define these as 64-bit signed integers to support files larger than 2 GiB. */
-typedef long long off_t;
-
-#endif
diff --git a/basics/include/__typedef_ssize_t.h b/basics/include/__typedef_ssize_t.h
deleted file mode 100644 (file)
index c53de91..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __wasm_basics___typedef_ssize_t_h
-#define __wasm_basics___typedef_ssize_t_h
-
-/* This is defined to be the same size as size_t. */
-typedef long ssize_t;
-
-#endif
diff --git a/basics/include/__typedef_suseconds_t.h b/basics/include/__typedef_suseconds_t.h
deleted file mode 100644 (file)
index 0531fbe..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __wasm_basics___typedef_suseconds_t_h
-#define __wasm_basics___typedef_suseconds_t_h
-
-/* Define this to be 64-bit as its main use is in struct timeval where the
-   extra space would otherwise be padding. */
-typedef long long suseconds_t;
-
-#endif
diff --git a/basics/include/__typedef_time_t.h b/basics/include/__typedef_time_t.h
deleted file mode 100644 (file)
index b6725d2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __wasm_basics___typedef_time_t_h
-#define __wasm_basics___typedef_time_t_h
-
-/* Define this as a 64-bit signed integer to avoid the 2038 bug. */
-typedef long long time_t;
-
-#endif
diff --git a/basics/include/__typedef_uid_t.h b/basics/include/__typedef_uid_t.h
deleted file mode 100644 (file)
index 89583f9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __wasm_basics___typedef_uid_t_h
-#define __wasm_basics___typedef_uid_t_h
-
-typedef unsigned uid_t;
-
-#endif
diff --git a/basics/include/errno.h b/basics/include/errno.h
deleted file mode 100644 (file)
index 2d1b29a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __wasm_basics_errno_h
-#define __wasm_basics_errno_h
-
-#include <__errno.h>
-
-#endif
diff --git a/basics/include/inttypes.h b/basics/include/inttypes.h
deleted file mode 100644 (file)
index 1c8a19d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __wasm_basics_inttypes_h
-#define __wasm_basics_inttypes_h
-
-/*
- * Include the real implementation, which is factored into a separate file so
- * that it can be reused by other libc stdlib implementations.
- */
-#include <__header_inttypes.h>
-
-#endif
diff --git a/basics/include/stdlib.h b/basics/include/stdlib.h
deleted file mode 100644 (file)
index 170efe9..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __wasm_basics_stdlib_h
-#define __wasm_basics_stdlib_h
-
-/*
- * Include the real implementation, which is factored into a separate file so
- * that it can be reused by other libc stdlib implementations.
- */
-#include <__functions_malloc.h>
-
-#endif
diff --git a/basics/include/string.h b/basics/include/string.h
deleted file mode 100644 (file)
index 54dd841..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __wasm_basics_string_h
-#define __wasm_basics_string_h
-
-/*
- * Include the real implementation, which is factored into a separate file so
- * that it can be reused by other libc string implementations.
- */
-#include <__functions_memcpy.h>
-
-#endif
diff --git a/basics/include/sys/stat.h b/basics/include/sys/stat.h
deleted file mode 100644 (file)
index dac5b86..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __wasm_basics_sys_stat_h
-#define __wasm_basics_sys_stat_h
-
-#include <__struct_stat.h>
-
-#define st_atime st_atim.tv_sec
-#define st_mtime st_mtim.tv_sec
-#define st_ctime st_ctim.tv_sec
-
-#endif
diff --git a/basics/include/sys/types.h b/basics/include/sys/types.h
deleted file mode 100644 (file)
index a7ce945..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __wasm_basics_sys_types_h
-#define __wasm_basics_sys_types_h
-
-#define __need_size_t
-#include <stddef.h>
-
-#include <__typedef_clock_t.h>
-#include <__typedef_time_t.h>
-#include <__typedef_blksize_t.h>
-#include <__typedef_off_t.h>
-#include <__typedef_ssize_t.h>
-#include <__typedef_suseconds_t.h>
-#include <__typedef_nlink_t.h>
-
-#endif
diff --git a/basics/include/time.h b/basics/include/time.h
deleted file mode 100644 (file)
index 0341a4e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __wasm_basics_time_h
-#define __wasm_basics_time_h
-
-#define __need_size_t
-#define __need_NULL
-#include <stddef.h>
-
-#include <__typedef_time_t.h>
-#include <__struct_timespec.h>
-
-#endif
diff --git a/basics/include/wchar.h b/basics/include/wchar.h
deleted file mode 100644 (file)
index b8220c8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __wasm_basics_wchar_h
-#define __wasm_basics_wchar_h
-
-#define __need_size_t
-#define __need_wchar_t
-#define __need_NULL
-#include <stddef.h>
-
-#endif
diff --git a/basics/sources/abort.c b/basics/sources/abort.c
deleted file mode 100644 (file)
index bb1c7dd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdlib.h>
-
-void abort(void) {
-    // WASI doesn't yet support signals, so just trap to halt the program.
-    __builtin_trap();
-}
diff --git a/basics/sources/complex-builtins.c b/basics/sources/complex-builtins.c
deleted file mode 100644 (file)
index b6588f7..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Each of the following complex functions can be implemented with a single
-// wasm instruction, so use that implementation rather than the portable
-// one in libm.
-
-#include <complex.h>
-
-float crealf(float _Complex x) {
-    return __real__ x;
-}
-
-double creal(double _Complex x) {
-    return __real__ x;
-}
-
-float cimagf(float _Complex x) {
-    return __imag__ x;
-}
-
-double cimag(double _Complex x) {
-    return __imag__ x;
-}
diff --git a/basics/sources/math/fmin-fmax.c b/basics/sources/math/fmin-fmax.c
deleted file mode 100644 (file)
index 9293798..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Wasm's `min` and `max` operators implement the IEEE 754-2019
-// `minimum` and `maximum` operations, meaning that given a choice
-// between NaN and a number, they return NaN. This differs from
-// the C standard library's `fmin` and `fmax` functions, which
-// return the number. However, we can still use wasm's builtins
-// by handling the NaN cases explicitly, and it still turns out
-// to be faster than doing the whole operation in
-// target-independent C. And, it's smaller.
-
-#include <math.h>
-
-float fminf(float x, float y) {
-    if (isnan(x)) return y;
-    if (isnan(y)) return x;
-    return __builtin_wasm_min_f32(x, y);
-}
-
-float fmaxf(float x, float y) {
-    if (isnan(x)) return y;
-    if (isnan(y)) return x;
-    return __builtin_wasm_max_f32(x, y);
-}
-
-double fmin(double x, double y) {
-    if (isnan(x)) return y;
-    if (isnan(y)) return x;
-    return __builtin_wasm_min_f64(x, y);
-}
-
-double fmax(double x, double y) {
-    if (isnan(x)) return y;
-    if (isnan(y)) return x;
-    return __builtin_wasm_max_f64(x, y);
-}
diff --git a/basics/sources/math/math-builtins.c b/basics/sources/math/math-builtins.c
deleted file mode 100644 (file)
index a5eb7cd..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-// Each of the following math functions can be implemented with a single
-// wasm instruction, so use that implementation rather than the portable
-// one in libm.
-
-#include <math.h>
-
-float fabsf(float x) {
-    return __builtin_fabsf(x);
-}
-
-double fabs(double x) {
-    return __builtin_fabs(x);
-}
-
-float sqrtf(float x) {
-    return __builtin_sqrtf(x);
-}
-
-double sqrt(double x) {
-    return __builtin_sqrt(x);
-}
-
-float copysignf(float x, float y) {
-    return __builtin_copysignf(x, y);
-}
-
-double copysign(double x, double y) {
-    return __builtin_copysign(x, y);
-}
-
-float ceilf(float x) {
-    return __builtin_ceilf(x);
-}
-
-double ceil(double x) {
-    return __builtin_ceil(x);
-}
-
-float floorf(float x) {
-    return __builtin_floorf(x);
-}
-
-double floor(double x) {
-    return __builtin_floor(x);
-}
-
-float truncf(float x) {
-    return __builtin_truncf(x);
-}
-
-double trunc(double x) {
-    return __builtin_trunc(x);
-}
-
-float nearbyintf(float x) {
-    return __builtin_nearbyintf(x);
-}
-
-double nearbyint(double x) {
-    return __builtin_nearbyint(x);
-}
-
-float rintf(float x) {
-    return __builtin_rintf(x);
-}
-
-double rint(double x) {
-    return __builtin_rint(x);
-}
diff --git a/basics/sources/reallocarray.c b/basics/sources/reallocarray.c
deleted file mode 100644 (file)
index 3e828cc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdlib.h>
-#include <errno.h>
-
-void *__reallocarray(void *ptr, size_t nmemb, size_t size) {
-    size_t bytes;
-    if (__builtin_umull_overflow(nmemb, size, &bytes)) {
-        errno = ENOMEM;
-        return NULL;
-    }
-    return realloc(ptr, bytes);
-}
-
-void *reallocarray(void *ptr, size_t nmemb, size_t size)
-    __attribute__((__weak__, __alias__("__reallocarray")));
diff --git a/basics/sources/string.c b/basics/sources/string.c
deleted file mode 100644 (file)
index 77d7201..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <string.h>
-#include <stdint.h>
-
-static void *copy_forward(void *restrict dst, const void *restrict src, size_t n) {
-    char *d = (char *)dst;
-    const char *s = (const char *)src;
-    while (n-- != 0) {
-        *d++ = *s++;
-    }
-    return dst;
-}
-
-static void *copy_backward(void *restrict dst, const void *restrict src, size_t n) {
-    char *d = (char *)dst;
-    const char *s = (const char *)src;
-    d += n;
-    s += n;
-    while (n-- != 0) {
-        *--d = *--s;
-    }
-    return dst;
-}
-
-void *memcpy(void *restrict dst, const void *restrict src, size_t n) {
-    return copy_forward(dst, src, n);
-}
-
-void *memmove(void *dst, const void *src, size_t n) {
-    if ((uintptr_t)dst - (uintptr_t)src >= n) {
-        return copy_forward(dst, src, n);
-    }
-    return copy_backward(dst, src, n);
-}
-
-void *memset(void *restrict dst, int c, size_t n) {
-    char *d = (char *)dst;
-    while (n-- != 0) {
-        *d++ = c;
-    }
-    return dst;
-}
index dc20ddf72f4ec280d57207b59dcc72bca3d98b9f..7cab06cb86defe23557af5a4745ebaef6507ebee 100644 (file)
@@ -172,7 +172,6 @@ __polevll
 __posix_getopt
 __pow_log_data
 __powf_log2_data
-__prepare_for_exit
 __progname
 __progname_full
 __putenv
@@ -263,6 +262,7 @@ __wasilibc_register_preopened_fd
 __wasilibc_rmdirat
 __wasilibc_tell
 __wasilibc_unlinkat
+__wasm_call_dtors
 __wcscoll_l
 __wcsftime_l
 __wcsxfrm_l
@@ -273,8 +273,8 @@ __xpg_strerror_r
 __year_to_secs
 _environ
 _exit
-_fini
 _flushlbf
+_initialize
 _start
 a64l
 abort
@@ -805,7 +805,6 @@ optind
 optopt
 optreset
 pathconf
-pause
 perror
 poll
 posix_close
@@ -1028,6 +1027,7 @@ unlinkat
 unsetenv
 uselocale
 usleep
+utime
 utimensat
 vasprintf
 vdprintf
index 71665bc966a72c2f325083f736a3268febca418f..f6ecbce4d35d863f4538505b3796d68ae6cc1ad7 100644 (file)
@@ -4,7 +4,6 @@
 #include <__function___isatty.h>
 #include <__functions_malloc.h>
 #include <__functions_memcpy.h>
-#include <__header_bits_signal.h>
 #include <__header_dirent.h>
 #include <__header_fcntl.h>
 #include <__header_inttypes.h>
 #include <sched.h>
 #include <search.h>
 #include <semaphore.h>
-#include <signal.h>
 #include <stdalign.h>
 #include <stdbool.h>
 #include <stdc-predef.h>
 #include <sys/reg.h>
 #include <sys/resource.h>
 #include <sys/select.h>
-#include <sys/signal.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/stropts.h>
 #include <time.h>
 #include <uchar.h>
 #include <unistd.h>
+#include <utime.h>
 #include <values.h>
 #include <wasi/api.h>
 #include <wasi/libc-environ.h>
index db4ae4dac28666c4a0bf88bd353b91ddc07f5e5a..1c8283a073f68b3e20d075f2af05ae305181ef45 100644 (file)
 #define BLK_RESTART 0x10
 #define BREAK 243
 #define BUFSIZ 1024
-#define BUS_ADRALN 1
-#define BUS_ADRERR 2
-#define BUS_MCEERR_AO 5
-#define BUS_MCEERR_AR 4
-#define BUS_OBJERR 3
 #define BYTE_ORDER __BYTE_ORDER
 #define CANBSIZ 255
 #define CBRK CEOL
 #define CHRTYPE '3'
 #define CINTR CTRL('c')
 #define CKILL CTRL('u')
-#define CLD_CONTINUED 6
-#define CLD_DUMPED 3
-#define CLD_EXITED 1
-#define CLD_KILLED 2
-#define CLD_STOPPED 5
-#define CLD_TRAPPED 4
 #define CLNEXT CTRL('v')
 #define CLOCKS_PER_SEC ((clock_t)1000000000)
 #define CLOCK_MONOTONIC (&_CLOCK_MONOTONIC)
 #define FORM_C 3
 #define FORM_N 1
 #define FORM_T 2
-#define FPE_FLTDIV 3
-#define FPE_FLTINV 7
-#define FPE_FLTOVF 4
-#define FPE_FLTRES 6
-#define FPE_FLTSUB 8
-#define FPE_FLTUND 5
-#define FPE_INTDIV 1
-#define FPE_INTOVF 2
 #define FP_ILOGB0 FP_ILOGBNAN
 #define FP_ILOGBNAN (-1-0x7fffffff)
 #define FP_INFINITE 1
 #define F_GETFD (1)
 #define F_GETFL (3)
 #define F_LOCK 1
-#define F_OK 0
+#define F_OK (0)
 #define F_SETFD (2)
 #define F_SETFL (4)
 #define F_TEST 3
 #define IGMP_V2_MEMBERSHIP_REPORT 0x16
 #define IGMP_v1_ROUTER 1
 #define IGMP_v2_ROUTER 2
-#define ILL_BADSTK 8
-#define ILL_COPROC 7
-#define ILL_ILLADR 3
-#define ILL_ILLOPC 1
-#define ILL_ILLOPN 2
-#define ILL_ILLTRP 4
-#define ILL_PRVOPC 5
-#define ILL_PRVREG 6
 #define IN6ADDRSZ NS_IN6ADDRSZ
 #define IN6ADDR_ANY_INIT { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
 #define IN6ADDR_LOOPBACK_INIT { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
 #define RS_HIPRI 0x01
 #define RUSAGE_CHILDREN 2
 #define RUSAGE_SELF 1
-#define R_OK 1
+#define R_OK (4)
 #define SARMAG 8
 #define SB 250
 #define SCHAR_MAX 127
 #define SEEK_END __WASI_WHENCE_END
 #define SEEK_SET __WASI_WHENCE_SET
 #define SEGSIZE 512
-#define SEGV_ACCERR 2
-#define SEGV_BNDERR 3
-#define SEGV_MAPERR 1
-#define SEGV_PKUERR 4
 #define SEM_FAILED ((sem_t *)0)
 #define SERVFAIL ns_r_servfail
 #define SHORTBITS (sizeof(short) * 8)
 #define SHUT_RD __WASI_SDFLAGS_RD
 #define SHUT_RDWR (SHUT_RD | SHUT_WR)
 #define SHUT_WR __WASI_SDFLAGS_WR
-#define SIGABRT __WASI_SIGNAL_ABRT
-#define SIGALRM __WASI_SIGNAL_ALRM
-#define SIGBUS __WASI_SIGNAL_BUS
-#define SIGCHLD __WASI_SIGNAL_CHLD
-#define SIGCONT __WASI_SIGNAL_CONT
-#define SIGEV_NONE 1
-#define SIGEV_SIGNAL 0
-#define SIGEV_THREAD 2
-#define SIGFPE __WASI_SIGNAL_FPE
-#define SIGHUP __WASI_SIGNAL_HUP
-#define SIGILL __WASI_SIGNAL_ILL
-#define SIGINT __WASI_SIGNAL_INT
-#define SIGIO SIGPOLL
-#define SIGIOT SIGABRT
-#define SIGKILL __WASI_SIGNAL_KILL
-#define SIGPIPE __WASI_SIGNAL_PIPE
-#define SIGPOLL __WASI_SIGNAL_POLL
-#define SIGPROF __WASI_SIGNAL_PROF
-#define SIGPWR __WASI_SIGNAL_PWR
-#define SIGQUIT __WASI_SIGNAL_QUIT
-#define SIGSEGV __WASI_SIGNAL_SEGV
-#define SIGSTOP __WASI_SIGNAL_STOP
-#define SIGSYS __WASI_SIGNAL_SYS
-#define SIGTERM __WASI_SIGNAL_TERM
-#define SIGTRAP __WASI_SIGNAL_TRAP
-#define SIGTSTP __WASI_SIGNAL_TSTP
-#define SIGTTIN __WASI_SIGNAL_TTIN
-#define SIGTTOU __WASI_SIGNAL_TTOU
-#define SIGUNUSED SIGSYS
-#define SIGURG __WASI_SIGNAL_URG
-#define SIGUSR1 __WASI_SIGNAL_USR1
-#define SIGUSR2 __WASI_SIGNAL_USR2
-#define SIGVTALRM __WASI_SIGNAL_VTALRM
-#define SIGWINCH __WASI_SIGNAL_WINCH
-#define SIGXCPU __WASI_SIGNAL_XCPU
-#define SIGXFSZ __WASI_SIGNAL_XFSZ
 #define SIG_ATOMIC_MAX INT32_MAX
 #define SIG_ATOMIC_MIN INT32_MIN
-#define SIG_BLOCK 0
-#define SIG_HOLD ((void (*)(int)) 2)
-#define SIG_SETMASK 2
-#define SIG_UNBLOCK 1
 #define SIZE_MAX UINT32_MAX
-#define SI_ASYNCIO (-4)
-#define SI_ASYNCNL (-60)
-#define SI_KERNEL 128
 #define SI_LOAD_SHIFT 16
-#define SI_MESGQ (-3)
-#define SI_QUEUE (-1)
-#define SI_SIGIO (-5)
-#define SI_TIMER (-2)
-#define SI_TKILL (-6)
-#define SI_USER 0
 #define SLC_ABORT 7
 #define SLC_ACK 0x80
 #define SLC_AO 4
 #define WONT 252
 #define WORD_BIT 32
 #define WRQ 02
-#define W_OK 2
-#define X_OK 4
+#define W_OK (2)
+#define X_OK (1)
 #define YESEXPR 0x50000
 #define YESSTR 0x50002
 #define YXDOMAIN ns_r_yxdomain
 #define _SC_XOPEN_XPG4 100
 #define _SEARCH_H 
 #define _SEMAPHORE_H 
-#define _SIGNAL_H 
 #define _SIZE_T 
 #define _STDALIGN_H 
 #define _STDBOOL_H 
 #define _TIME_H 
 #define _UCHAR_H 
 #define _UNISTD_H 
+#define _UTIME_H 
 #define _VALUES_H 
 #define _VA_LIST 
 #define _WCHAR_H 
 #define __wasi_libc_environ_h 
 #define __wasi_libc_find_relpath_h 
 #define __wasi_libc_h 
+#define __wasilibc___errno_h 
 #define __wasilibc___errno_values_h 
 #define __wasilibc___fd_set_h 
 #define __wasilibc___function___isatty_h 
-#define __wasilibc___header_bits_signal_h 
+#define __wasilibc___functions_malloc_h 
+#define __wasilibc___functions_memcpy_h 
 #define __wasilibc___header_dirent_h 
 #define __wasilibc___header_fcntl_h 
 #define __wasilibc___header_netinet_in_h 
 #define __wasilibc___header_sys_stat_h 
 #define __wasilibc___header_time_h 
 #define __wasilibc___header_unistd_h 
+#define __wasilibc___include_inttypes_h 
 #define __wasilibc___macro_FD_SETSIZE_h 
+#define __wasilibc___macro_PAGESIZE_h 
 #define __wasilibc___mode_t_h 
 #define __wasilibc___seek_h 
 #define __wasilibc___struct_dirent_h 
 #define __wasilibc___struct_sockaddr_in_h 
 #define __wasilibc___struct_sockaddr_storage_h 
 #define __wasilibc___struct_sockaddr_un_h 
+#define __wasilibc___struct_stat_h 
+#define __wasilibc___struct_timespec_h 
 #define __wasilibc___struct_timeval_h 
 #define __wasilibc___struct_tm_h 
 #define __wasilibc___struct_tms_h 
 #define __wasilibc___typedef_DIR_h 
+#define __wasilibc___typedef_blkcnt_t_h 
+#define __wasilibc___typedef_blksize_t_h 
+#define __wasilibc___typedef_clock_t_h 
 #define __wasilibc___typedef_clockid_t_h 
+#define __wasilibc___typedef_dev_t_h 
 #define __wasilibc___typedef_fd_set_h 
+#define __wasilibc___typedef_gid_t_h 
 #define __wasilibc___typedef_in_addr_t_h 
 #define __wasilibc___typedef_in_port_t_h 
+#define __wasilibc___typedef_ino_t_h 
+#define __wasilibc___typedef_mode_t_h 
 #define __wasilibc___typedef_nfds_t_h 
+#define __wasilibc___typedef_nlink_t_h 
+#define __wasilibc___typedef_off_t_h 
 #define __wasilibc___typedef_sa_family_t_h 
 #define __wasilibc___typedef_sigset_t_h 
 #define __wasilibc___typedef_socklen_t_h 
+#define __wasilibc___typedef_ssize_t_h 
+#define __wasilibc___typedef_suseconds_t_h 
+#define __wasilibc___typedef_time_t_h 
+#define __wasilibc___typedef_uid_t_h 
 #define __wasm 1
 #define __wasm32 1
 #define __wasm32__ 1
 #define __wasm__ 1
-#define __wasm_basics___errno_h 
-#define __wasm_basics___functions_malloc_h 
-#define __wasm_basics___functions_memcpy_h 
-#define __wasm_basics___include_inttypes_h 
-#define __wasm_basics___macro_PAGESIZE_h 
-#define __wasm_basics___struct_stat_h 
-#define __wasm_basics___struct_timespec_h 
-#define __wasm_basics___typedef_blkcnt_t_h 
-#define __wasm_basics___typedef_blksize_t_h 
-#define __wasm_basics___typedef_clock_t_h 
-#define __wasm_basics___typedef_dev_t_h 
-#define __wasm_basics___typedef_gid_t_h 
-#define __wasm_basics___typedef_ino_t_h 
-#define __wasm_basics___typedef_mode_t_h 
-#define __wasm_basics___typedef_nlink_t_h 
-#define __wasm_basics___typedef_off_t_h 
-#define __wasm_basics___typedef_ssize_t_h 
-#define __wasm_basics___typedef_suseconds_t_h 
-#define __wasm_basics___typedef_time_t_h 
-#define __wasm_basics___typedef_uid_t_h 
 #define _tolower(a) ((a)|0x20)
 #define _toupper(a) ((a)&0x5f)
 #define acos(x) __tg_real_complex(acos, (x))
 #define rr_code rr_hdr.icmp6_code
 #define rr_seqnum rr_hdr.icmp6_data32[0]
 #define rr_type rr_hdr.icmp6_type
-#define sa_handler __sa_handler.sa_handler
-#define sa_sigaction __sa_handler.sa_sigaction
 #define scalbln(x,y) __tg_real_2_1(scalbln, (x), (y))
 #define scalbn(x,y) __tg_real_2_1(scalbn, (x), (y))
 #define scandir64 scandir
 #define setbit(x,i) __bitop(x,i,|=)
-#define si_addr __si_fields.__sigfault.si_addr
-#define si_addr_lsb __si_fields.__sigfault.si_addr_lsb
-#define si_arch __si_fields.__sigsys.si_arch
-#define si_band __si_fields.__sigpoll.si_band
-#define si_call_addr __si_fields.__sigsys.si_call_addr
-#define si_fd __si_fields.__sigpoll.si_fd
-#define si_int si_value.sival_int
-#define si_lower __si_fields.__sigfault.__first.__addr_bnd.si_lower
-#define si_overrun __si_fields.__si_common.__first.__timer.si_overrun
-#define si_pid __si_fields.__si_common.__first.__piduid.si_pid
-#define si_pkey __si_fields.__sigfault.__first.si_pkey
-#define si_ptr si_value.sival_ptr
-#define si_status __si_fields.__si_common.__second.__sigchld.si_status
-#define si_stime __si_fields.__si_common.__second.__sigchld.si_stime
-#define si_syscall __si_fields.__sigsys.si_syscall
-#define si_timerid __si_fields.__si_common.__first.__timer.si_timerid
-#define si_uid __si_fields.__si_common.__first.__piduid.si_uid
-#define si_upper __si_fields.__sigfault.__first.__addr_bnd.si_upper
-#define si_utime __si_fields.__si_common.__second.__sigchld.si_utime
-#define si_value __si_fields.__si_common.__second.si_value
 #define signbit(x) (__builtin_signbit(x))
 #define sin(x) __tg_real_complex(sin, (x))
 #define sinh(x) __tg_real_complex(sinh, (x))
index 09cfa9a2f0b4fb4d946965b99e7f81e7f134644b..1e5401cddfbf159180c03d5715958d5711934354 100644 (file)
@@ -1,23 +1,19 @@
-"WASI" the WebAssembly System Interface.
+# WASI libc "bottom half".
 
-WASI libc is conceptually the lower half of a traditional libc implementation.
-It provides C interfaces to the low-level WASI syscalls.
+The WASI libc "bottom half" is conceptually the lower half of a traditional libc
+implementation, consisting of C interfaces to the low-level WASI syscalls.
 
-This is largely based on [CloudABI], [cloudlibc], and [libpreopen], however we
-use just the low-level syscall wrappers rather than all of cloudlibc and
-libpreopen, and we have several customizations for use in a WebAssembly sysroot.
+This implementation is partially derived from the "bottom half" of [cloudlibc],
+revision 8835639f27fc42d32096d59d294a0bbb857dc368.
 
-[CloudABI]: https://github.com/NuxiNL/cloudabi
 [cloudlibc]: https://github.com/NuxiNL/cloudlibc
-[libpreopen]: https://github.com/musec/libpreopen
-
-The upstream repositories and versions used here are:
 
-cloudlibc - https://github.com/NuxiNL/cloudlibc 8835639f27fc42d32096d59d294a0bbb857dc368
-libpreopen - https://github.com/musec/libpreopen b29e9287cc75a7db7291ce3eb468a3d2bad8ceb1
+This implementation includes preopen functionality, which emulates POSIX APIs
+accepting absolute paths by translating them into pre-opened directory handles
+and relative paths that can be opened with `openat`. This technique is inspired
+by [libpreopen], however the implementation here is designed to be built into
+libc rather than to be a layer on top of libc.
 
-Whole files which are unused are omitted. Changes to upstream code are wrapped
-in preprocessor directives controlled by the macro `__wasilibc_unmodified_upstream`,
-except that CloudABI names have also been renamed to WASI names without annotations.
+[libpreopen]: https://github.com/musec/libpreopen
 
-WASI libc currently depends on the basics and dlmalloc components of reference-sysroot.
+The WASI libc lower half currently depends on the dlmalloc component.
index be76ecd7cb306822dfcf5e266244899fce976601..cde4e81c21b78897011c933ec0984a943a00450b 100644 (file)
@@ -11,14 +11,14 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
   // Construct events for poll().
   size_t maxevents = 2 * nfds + 1;
   __wasi_subscription_t subscriptions[maxevents];
-  size_t nevents = 0;
+  size_t nsubscriptions = 0;
   for (size_t i = 0; i < nfds; ++i) {
     struct pollfd *pollfd = &fds[i];
     if (pollfd->fd < 0)
       continue;
     bool created_events = false;
     if ((pollfd->events & POLLRDNORM) != 0) {
-      __wasi_subscription_t *subscription = &subscriptions[nevents++];
+      __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
       *subscription = (__wasi_subscription_t){
           .userdata = (uintptr_t)pollfd,
           .u.tag = __WASI_EVENTTYPE_FD_READ,
@@ -27,7 +27,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
       created_events = true;
     }
     if ((pollfd->events & POLLWRNORM) != 0) {
-      __wasi_subscription_t *subscription = &subscriptions[nevents++];
+      __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
       *subscription = (__wasi_subscription_t){
           .userdata = (uintptr_t)pollfd,
           .u.tag = __WASI_EVENTTYPE_FD_WRITE,
@@ -47,7 +47,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
 
   // Create extra event for the timeout.
   if (timeout >= 0) {
-    __wasi_subscription_t *subscription = &subscriptions[nevents++];
+    __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
     *subscription = (__wasi_subscription_t){
         .u.tag = __WASI_EVENTTYPE_CLOCK,
         .u.u.clock.id = __WASI_CLOCKID_REALTIME,
@@ -56,15 +56,24 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
   }
 
   // Execute poll().
-  __wasi_event_t events[nevents];
+  size_t nevents;
+  __wasi_event_t events[nsubscriptions];
   __wasi_errno_t error =
-#ifdef __wasilibc_unmodified_upstream
-      __wasi_poll(subscriptions, events, nevents, &nevents);
-#else
-      __wasi_poll_oneoff(subscriptions, events, nevents, &nevents);
-#endif
+      __wasi_poll_oneoff(subscriptions, events, nsubscriptions, &nevents);
   if (error != 0) {
-    errno = error;
+    // WASI's poll requires at least one subscription, or else it returns
+    // `EINVAL`. Since a `poll` with nothing to wait for is valid in POSIX,
+    // return `ENOTSUP` to indicate that we don't support that case.
+    //
+    // Wasm has no signal handling, so if none of the user-provided `pollfd`
+    // elements, nor the timeout, led us to producing even one subscription
+    // to wait for, there would be no way for the poll to wake up. WASI
+    // returns `EINVAL` in this case, but for users of `poll`, `ENOTSUP` is
+    // more likely to be understood.
+    if (nsubscriptions == 0)
+      errno = ENOTSUP;
+    else
+      errno = error;
     return -1;
   }
 
@@ -80,18 +89,10 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
     if (event->type == __WASI_EVENTTYPE_FD_READ ||
         event->type == __WASI_EVENTTYPE_FD_WRITE) {
       struct pollfd *pollfd = (struct pollfd *)(uintptr_t)event->userdata;
-#ifdef __wasilibc_unmodified_upstream // generated constant names
-      if (event->error == __WASI_EBADF) {
-#else
       if (event->error == __WASI_ERRNO_BADF) {
-#endif
         // Invalid file descriptor.
         pollfd->revents |= POLLNVAL;
-#ifdef __wasilibc_unmodified_upstream // generated constant names
-      } else if (event->error == __WASI_EPIPE) {
-#else
       } else if (event->error == __WASI_ERRNO_PIPE) {
-#endif
         // Hangup on write side of pipe.
         pollfd->revents |= POLLHUP;
       } else if (event->error != 0) {
diff --git a/libc-bottom-half/cloudlibc/src/libc/stdlib/qsort.c b/libc-bottom-half/cloudlibc/src/libc/stdlib/qsort.c
deleted file mode 100644 (file)
index ec21038..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2015 Nuxi, https://nuxi.nl/
-//
-// SPDX-License-Identifier: BSD-2-Clause
-
-#include <stdlib.h>
-
-#ifndef qsort
-#error "qsort is supposed to be a macro as well"
-#endif
-
-// clang-format off
-void (qsort)(void *base, size_t nel, size_t width,
-             int (*compar)(const void *, const void *)) {
-  return qsort(base, nel, width, compar);
-}
index bd1d2fdc0657ee582b72bae42494364d2a929675..fdc470ea85ae95ee2e284111c36e73a720675d87 100644 (file)
 
 int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
             fd_set *restrict errorfds, const struct timespec *restrict timeout,
-#ifdef __wasilibc_unmodified_upstream
-            ...) {
-#else
             const sigset_t *sigmask) {
-#endif
   // Negative file descriptor upperbound.
   if (nfds < 0) {
     errno = EINVAL;
@@ -40,13 +36,13 @@ int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
   // Determine the maximum number of events.
   size_t maxevents = readfds->__nfds + writefds->__nfds + 1;
   __wasi_subscription_t subscriptions[maxevents];
-  size_t nevents = 0;
+  size_t nsubscriptions = 0;
 
   // Convert the readfds set.
   for (size_t i = 0; i < readfds->__nfds; ++i) {
     int fd = readfds->__fds[i];
     if (fd < nfds) {
-      __wasi_subscription_t *subscription = &subscriptions[nevents++];
+      __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
       *subscription = (__wasi_subscription_t){
           .userdata = fd,
           .u.tag = __WASI_EVENTTYPE_FD_READ,
@@ -59,7 +55,7 @@ int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
   for (size_t i = 0; i < writefds->__nfds; ++i) {
     int fd = writefds->__fds[i];
     if (fd < nfds) {
-      __wasi_subscription_t *subscription = &subscriptions[nevents++];
+      __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
       *subscription = (__wasi_subscription_t){
           .userdata = fd,
           .u.tag = __WASI_EVENTTYPE_FD_WRITE,
@@ -70,7 +66,7 @@ int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
 
   // Create extra event for the timeout.
   if (timeout != NULL) {
-    __wasi_subscription_t *subscription = &subscriptions[nevents++];
+    __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
     *subscription = (__wasi_subscription_t){
         .u.tag = __WASI_EVENTTYPE_CLOCK,
         .u.u.clock.id = __WASI_CLOCKID_REALTIME,
@@ -82,15 +78,24 @@ int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
   }
 
   // Execute poll().
-  __wasi_event_t events[nevents];
+  size_t nevents;
+  __wasi_event_t events[nsubscriptions];
   __wasi_errno_t error =
-#ifdef __wasilibc_unmodified_upstream
-      __wasi_poll(subscriptions, events, nevents, &nevents);
-#else
-      __wasi_poll_oneoff(subscriptions, events, nevents, &nevents);
-#endif
+      __wasi_poll_oneoff(subscriptions, events, nsubscriptions, &nevents);
   if (error != 0) {
-    errno = error;
+    // WASI's poll requires at least one subscription, or else it returns
+    // `EINVAL`. Since a `pselect` with nothing to wait for is valid in POSIX,
+    // return `ENOTSUP` to indicate that we don't support that case.
+    //
+    // Wasm has no signal handling, so if none of the user-provided `pollfd`
+    // elements, nor the timeout, led us to producing even one subscription
+    // to wait for, there would be no way for the poll to wake up. WASI
+    // returns `EINVAL` in this case, but for users of `poll`, `ENOTSUP` is
+    // more likely to be understood.
+    if (nsubscriptions == 0)
+      errno = ENOTSUP;
+    else
+      errno = error;
     return -1;
   }
 
@@ -99,11 +104,7 @@ int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
     const __wasi_event_t *event = &events[i];
     if ((event->type == __WASI_EVENTTYPE_FD_READ ||
          event->type == __WASI_EVENTTYPE_FD_WRITE) &&
-#ifdef __wasilibc_unmodified_upstream // generated constant names
-        event->error == __WASI_EBADF) {
-#else
         event->error == __WASI_ERRNO_BADF) {
-#endif
       errno = EBADF;
       return -1;
     }
diff --git a/libc-bottom-half/crt/crt1-reactor.c b/libc-bottom-half/crt/crt1-reactor.c
new file mode 100644 (file)
index 0000000..f507c9e
--- /dev/null
@@ -0,0 +1,7 @@
+extern void __wasm_call_ctors(void);
+
+__attribute__((export_name("_initialize")))
+void _initialize(void) {
+    // The linker synthesizes this to call constructors.
+    __wasm_call_ctors();
+}
index f70c24a9fd3264294848e19622e3563cb87b66e6..5e164dddba3d3e27cae3513f739e1e9cfec56eec 100644 (file)
@@ -1,8 +1,9 @@
 #include <wasi/api.h>
 extern void __wasm_call_ctors(void);
 extern int __original_main(void);
-extern void __prepare_for_exit(void);
+extern void __wasm_call_dtors(void);
 
+__attribute__((export_name("_start")))
 void _start(void) {
     // The linker synthesizes this to call constructors.
     __wasm_call_ctors();
@@ -13,7 +14,7 @@ void _start(void) {
     int r = __original_main();
 
     // Call atexit functions, destructors, stdio cleanup, etc.
-    __prepare_for_exit();
+    __wasm_call_dtors();
 
     // If main exited successfully, just return, otherwise call
     // `__wasi_proc_exit`.
diff --git a/libc-bottom-half/headers/public/__errno.h b/libc-bottom-half/headers/public/__errno.h
new file mode 100644 (file)
index 0000000..4fd983a
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __wasilibc___errno_h
+#define __wasilibc___errno_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+extern thread_local int errno;
+#else
+extern _Thread_local int errno;
+#endif
+
+#define errno errno
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libc-bottom-half/headers/public/__functions_malloc.h b/libc-bottom-half/headers/public/__functions_malloc.h
new file mode 100644 (file)
index 0000000..d516bc3
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __wasilibc___functions_malloc_h
+#define __wasilibc___functions_malloc_h
+
+#define __need_size_t
+#define __need_wchar_t
+#define __need_NULL
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *malloc(size_t __size) __attribute__((__malloc__, __warn_unused_result__));
+void free(void *__ptr);
+void *calloc(size_t __nmemb, size_t __size) __attribute__((__malloc__, __warn_unused_result__));
+void *realloc(void *__ptr, size_t __size) __attribute__((__warn_unused_result__));
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+void *reallocarray(void *__ptr, size_t __nmemb, size_t __size) __attribute__((__warn_unused_result__));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libc-bottom-half/headers/public/__functions_memcpy.h b/libc-bottom-half/headers/public/__functions_memcpy.h
new file mode 100644 (file)
index 0000000..253b065
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __wasilibc___functions_memcpy_h
+#define __wasilibc___functions_memcpy_h
+
+#define __need_size_t
+#define __need_NULL
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *memcpy(void *__restrict__ __dst, const void *__restrict__ __src, size_t __n) __attribute__((__nothrow__, __leaf__, __nonnull__(1, 2)));
+void *memmove(void *__dst, const void *__src, size_t __n) __attribute__((__nothrow__, __leaf__, __nonnull__(1, 2)));
+void *memset(void *__dst, int __c, size_t __n) __attribute__((__nothrow__, __leaf__, __nonnull__(1)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libc-bottom-half/headers/public/__header_bits_signal.h b/libc-bottom-half/headers/public/__header_bits_signal.h
deleted file mode 100644 (file)
index 4631259..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __wasilibc___header_bits_signal_h
-#define __wasilibc___header_bits_signal_h
-
-#include <wasi/api.h>
-
-#define SIGHUP    __WASI_SIGNAL_HUP
-#define SIGINT    __WASI_SIGNAL_INT
-#define SIGQUIT   __WASI_SIGNAL_QUIT
-#define SIGILL    __WASI_SIGNAL_ILL
-#define SIGTRAP   __WASI_SIGNAL_TRAP
-#define SIGABRT   __WASI_SIGNAL_ABRT
-#define SIGBUS    __WASI_SIGNAL_BUS
-#define SIGFPE    __WASI_SIGNAL_FPE
-#define SIGKILL   __WASI_SIGNAL_KILL
-#define SIGUSR1   __WASI_SIGNAL_USR1
-#define SIGSEGV   __WASI_SIGNAL_SEGV
-#define SIGUSR2   __WASI_SIGNAL_USR2
-#define SIGPIPE   __WASI_SIGNAL_PIPE
-#define SIGALRM   __WASI_SIGNAL_ALRM
-#define SIGTERM   __WASI_SIGNAL_TERM
-#define SIGCHLD   __WASI_SIGNAL_CHLD
-#define SIGCONT   __WASI_SIGNAL_CONT
-#define SIGSTOP   __WASI_SIGNAL_STOP
-#define SIGTSTP   __WASI_SIGNAL_TSTP
-#define SIGTTIN   __WASI_SIGNAL_TTIN
-#define SIGTTOU   __WASI_SIGNAL_TTOU
-#define SIGURG    __WASI_SIGNAL_URG
-#define SIGXCPU   __WASI_SIGNAL_XCPU
-#define SIGXFSZ   __WASI_SIGNAL_XFSZ
-#define SIGVTALRM __WASI_SIGNAL_VTALRM
-#define SIGPROF   __WASI_SIGNAL_PROF
-#define SIGWINCH  __WASI_SIGNAL_WINCH
-#define SIGPOLL   __WASI_SIGNAL_POLL
-#define SIGPWR    __WASI_SIGNAL_PWR
-#define SIGSYS    __WASI_SIGNAL_SYS
-
-#define SIGIOT    SIGABRT
-#define SIGIO     SIGPOLL
-#define SIGUNUSED SIGSYS
-
-#endif
diff --git a/libc-bottom-half/headers/public/__header_inttypes.h b/libc-bottom-half/headers/public/__header_inttypes.h
new file mode 100644 (file)
index 0000000..47c5c9b
--- /dev/null
@@ -0,0 +1,182 @@
+#ifndef __wasilibc___include_inttypes_h
+#define __wasilibc___include_inttypes_h
+
+#include <stdint.h>
+
+#define __need_wchar_t
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct { intmax_t quot, rem; } imaxdiv_t;
+
+intmax_t  imaxabs(intmax_t);
+imaxdiv_t imaxdiv(intmax_t, intmax_t);
+intmax_t  strtoimax(const char *__restrict, char **__restrict, int);
+uintmax_t strtoumax(const char *__restrict, char **__restrict, int);
+intmax_t  wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int);
+uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int);
+
+#define PRId16 __INT16_FMTd__
+#define PRIi16 __INT16_FMTi__
+#define PRId32 __INT32_FMTd__
+#define PRIi32 __INT32_FMTi__
+#define PRId64 __INT64_FMTd__
+#define PRIi64 __INT64_FMTi__
+#define PRId8 __INT8_FMTd__
+#define PRIi8 __INT8_FMTi__
+#define PRIdMAX __INTMAX_FMTd__
+#define PRIiMAX __INTMAX_FMTi__
+#define PRIdPTR __INTPTR_FMTd__
+#define PRIiPTR __INTPTR_FMTi__
+#define PRIdFAST16 __INT_FAST16_FMTd__
+#define PRIiFAST16 __INT_FAST16_FMTi__
+#define PRIdFAST32 __INT_FAST32_FMTd__
+#define PRIiFAST32 __INT_FAST32_FMTi__
+#define PRIdFAST64 __INT_FAST64_FMTd__
+#define PRIiFAST64 __INT_FAST64_FMTi__
+#define PRIdFAST8 __INT_FAST8_FMTd__
+#define PRIiFAST8 __INT_FAST8_FMTi__
+#define PRIdLEAST16 __INT_LEAST16_FMTd__
+#define PRIiLEAST16 __INT_LEAST16_FMTi__
+#define PRIdLEAST32 __INT_LEAST32_FMTd__
+#define PRIiLEAST32 __INT_LEAST32_FMTi__
+#define PRIdLEAST64 __INT_LEAST64_FMTd__
+#define PRIiLEAST64 __INT_LEAST64_FMTi__
+#define PRIdLEAST8 __INT_LEAST8_FMTd__
+#define PRIiLEAST8 __INT_LEAST8_FMTi__
+#define PRIX16 __UINT16_FMTX__
+#define PRIo16 __UINT16_FMTo__
+#define PRIu16 __UINT16_FMTu__
+#define PRIx16 __UINT16_FMTx__
+#define PRIX32 __UINT32_FMTX__
+#define PRIo32 __UINT32_FMTo__
+#define PRIu32 __UINT32_FMTu__
+#define PRIx32 __UINT32_FMTx__
+#define PRIX64 __UINT64_FMTX__
+#define PRIo64 __UINT64_FMTo__
+#define PRIu64 __UINT64_FMTu__
+#define PRIx64 __UINT64_FMTx__
+#define PRIX8 __UINT8_FMTX__
+#define PRIo8 __UINT8_FMTo__
+#define PRIu8 __UINT8_FMTu__
+#define PRIx8 __UINT8_FMTx__
+#define PRIXMAX __UINTMAX_FMTX__
+#define PRIoMAX __UINTMAX_FMTo__
+#define PRIuMAX __UINTMAX_FMTu__
+#define PRIxMAX __UINTMAX_FMTx__
+#define PRIXPTR __UINTPTR_FMTX__
+#define PRIoPTR __UINTPTR_FMTo__
+#define PRIuPTR __UINTPTR_FMTu__
+#define PRIxPTR __UINTPTR_FMTx__
+#define PRIXFAST16 __UINT_FAST16_FMTX__
+#define PRIoFAST16 __UINT_FAST16_FMTo__
+#define PRIuFAST16 __UINT_FAST16_FMTu__
+#define PRIxFAST16 __UINT_FAST16_FMTx__
+#define PRIXFAST32 __UINT_FAST32_FMTX__
+#define PRIoFAST32 __UINT_FAST32_FMTo__
+#define PRIuFAST32 __UINT_FAST32_FMTu__
+#define PRIxFAST32 __UINT_FAST32_FMTx__
+#define PRIXFAST64 __UINT_FAST64_FMTX__
+#define PRIoFAST64 __UINT_FAST64_FMTo__
+#define PRIuFAST64 __UINT_FAST64_FMTu__
+#define PRIxFAST64 __UINT_FAST64_FMTx__
+#define PRIXFAST8 __UINT_FAST8_FMTX__
+#define PRIoFAST8 __UINT_FAST8_FMTo__
+#define PRIuFAST8 __UINT_FAST8_FMTu__
+#define PRIxFAST8 __UINT_FAST8_FMTx__
+#define PRIXLEAST16 __UINT_LEAST16_FMTX__
+#define PRIoLEAST16 __UINT_LEAST16_FMTo__
+#define PRIuLEAST16 __UINT_LEAST16_FMTu__
+#define PRIxLEAST16 __UINT_LEAST16_FMTx__
+#define PRIXLEAST32 __UINT_LEAST32_FMTX__
+#define PRIoLEAST32 __UINT_LEAST32_FMTo__
+#define PRIuLEAST32 __UINT_LEAST32_FMTu__
+#define PRIxLEAST32 __UINT_LEAST32_FMTx__
+#define PRIXLEAST64 __UINT_LEAST64_FMTX__
+#define PRIoLEAST64 __UINT_LEAST64_FMTo__
+#define PRIuLEAST64 __UINT_LEAST64_FMTu__
+#define PRIxLEAST64 __UINT_LEAST64_FMTx__
+#define PRIXLEAST8 __UINT_LEAST8_FMTX__
+#define PRIoLEAST8 __UINT_LEAST8_FMTo__
+#define PRIuLEAST8 __UINT_LEAST8_FMTu__
+#define PRIxLEAST8 __UINT_LEAST8_FMTx__
+
+#define SCNd16 __INT16_FMTd__
+#define SCNi16 __INT16_FMTi__
+#define SCNd32 __INT32_FMTd__
+#define SCNi32 __INT32_FMTi__
+#define SCNd64 __INT64_FMTd__
+#define SCNi64 __INT64_FMTi__
+#define SCNd8 __INT8_FMTd__
+#define SCNi8 __INT8_FMTi__
+#define SCNdMAX __INTMAX_FMTd__
+#define SCNiMAX __INTMAX_FMTi__
+#define SCNdPTR __INTPTR_FMTd__
+#define SCNiPTR __INTPTR_FMTi__
+#define SCNdFAST16 __INT_FAST16_FMTd__
+#define SCNiFAST16 __INT_FAST16_FMTi__
+#define SCNdFAST32 __INT_FAST32_FMTd__
+#define SCNiFAST32 __INT_FAST32_FMTi__
+#define SCNdFAST64 __INT_FAST64_FMTd__
+#define SCNiFAST64 __INT_FAST64_FMTi__
+#define SCNdFAST8 __INT_FAST8_FMTd__
+#define SCNiFAST8 __INT_FAST8_FMTi__
+#define SCNdLEAST16 __INT_LEAST16_FMTd__
+#define SCNiLEAST16 __INT_LEAST16_FMTi__
+#define SCNdLEAST32 __INT_LEAST32_FMTd__
+#define SCNiLEAST32 __INT_LEAST32_FMTi__
+#define SCNdLEAST64 __INT_LEAST64_FMTd__
+#define SCNiLEAST64 __INT_LEAST64_FMTi__
+#define SCNdLEAST8 __INT_LEAST8_FMTd__
+#define SCNiLEAST8 __INT_LEAST8_FMTi__
+#define SCNo16 __UINT16_FMTo__
+#define SCNu16 __UINT16_FMTu__
+#define SCNx16 __UINT16_FMTx__
+#define SCNo32 __UINT32_FMTo__
+#define SCNu32 __UINT32_FMTu__
+#define SCNx32 __UINT32_FMTx__
+#define SCNo64 __UINT64_FMTo__
+#define SCNu64 __UINT64_FMTu__
+#define SCNx64 __UINT64_FMTx__
+#define SCNo8 __UINT8_FMTo__
+#define SCNu8 __UINT8_FMTu__
+#define SCNx8 __UINT8_FMTx__
+#define SCNoMAX __UINTMAX_FMTo__
+#define SCNuMAX __UINTMAX_FMTu__
+#define SCNxMAX __UINTMAX_FMTx__
+#define SCNoPTR __UINTPTR_FMTo__
+#define SCNuPTR __UINTPTR_FMTu__
+#define SCNxPTR __UINTPTR_FMTx__
+#define SCNoFAST16 __UINT_FAST16_FMTo__
+#define SCNuFAST16 __UINT_FAST16_FMTu__
+#define SCNxFAST16 __UINT_FAST16_FMTx__
+#define SCNoFAST32 __UINT_FAST32_FMTo__
+#define SCNuFAST32 __UINT_FAST32_FMTu__
+#define SCNxFAST32 __UINT_FAST32_FMTx__
+#define SCNoFAST64 __UINT_FAST64_FMTo__
+#define SCNuFAST64 __UINT_FAST64_FMTu__
+#define SCNxFAST64 __UINT_FAST64_FMTx__
+#define SCNoFAST8 __UINT_FAST8_FMTo__
+#define SCNuFAST8 __UINT_FAST8_FMTu__
+#define SCNxFAST8 __UINT_FAST8_FMTx__
+#define SCNoLEAST16 __UINT_LEAST16_FMTo__
+#define SCNuLEAST16 __UINT_LEAST16_FMTu__
+#define SCNxLEAST16 __UINT_LEAST16_FMTx__
+#define SCNoLEAST32 __UINT_LEAST32_FMTo__
+#define SCNuLEAST32 __UINT_LEAST32_FMTu__
+#define SCNxLEAST32 __UINT_LEAST32_FMTx__
+#define SCNoLEAST64 __UINT_LEAST64_FMTo__
+#define SCNuLEAST64 __UINT_LEAST64_FMTu__
+#define SCNxLEAST64 __UINT_LEAST64_FMTx__
+#define SCNoLEAST8 __UINT_LEAST8_FMTo__
+#define SCNuLEAST8 __UINT_LEAST8_FMTu__
+#define SCNxLEAST8 __UINT_LEAST8_FMTx__
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index e9eae2b6404e5968c8772f1e7283b3dca21b8346..6b80d63788317fb9d73573cf4b17fe909f937e00 100644 (file)
@@ -5,10 +5,10 @@ struct stat;
 
 #include <__seek.h>
 
-#define F_OK 0
-#define R_OK 1
-#define W_OK 2
-#define X_OK 4
+#define F_OK (0)
+#define X_OK (1)
+#define W_OK (2)
+#define R_OK (4)
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/libc-bottom-half/headers/public/__macro_PAGESIZE.h b/libc-bottom-half/headers/public/__macro_PAGESIZE.h
new file mode 100644 (file)
index 0000000..0243c98
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __wasilibc___macro_PAGESIZE_h
+#define __wasilibc___macro_PAGESIZE_h
+
+/*
+ * The page size in WebAssembly is fixed at 64 KiB. If this ever changes,
+ * it's expected that applications will need to opt in, so we can change
+ * this.
+ */
+#define PAGESIZE (0x10000)
+
+#endif
diff --git a/libc-bottom-half/headers/public/__struct_stat.h b/libc-bottom-half/headers/public/__struct_stat.h
new file mode 100644 (file)
index 0000000..5e345da
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __wasilibc___struct_stat_h
+#define __wasilibc___struct_stat_h
+
+#include <__typedef_dev_t.h>
+#include <__typedef_ino_t.h>
+#include <__typedef_nlink_t.h>
+#include <__typedef_mode_t.h>
+#include <__typedef_uid_t.h>
+#include <__typedef_gid_t.h>
+#include <__typedef_off_t.h>
+#include <__typedef_blksize_t.h>
+#include <__typedef_blkcnt_t.h>
+#include <__struct_timespec.h>
+
+struct stat {
+    dev_t st_dev;
+    ino_t st_ino;
+    nlink_t st_nlink;
+
+    mode_t st_mode;
+    uid_t st_uid;
+    gid_t st_gid;
+    unsigned int __pad0;
+    dev_t st_rdev;
+    off_t st_size;
+    blksize_t st_blksize;
+    blkcnt_t st_blocks;
+
+    struct timespec st_atim;
+    struct timespec st_mtim;
+    struct timespec st_ctim;
+    long long __reserved[3];
+};
+
+#endif
diff --git a/libc-bottom-half/headers/public/__struct_timespec.h b/libc-bottom-half/headers/public/__struct_timespec.h
new file mode 100644 (file)
index 0000000..10d83f9
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __wasilibc___struct_timespec_h
+#define __wasilibc___struct_timespec_h
+
+#include <__typedef_time_t.h>
+
+/* As specified in POSIX. */
+struct timespec {
+    time_t tv_sec;
+    long tv_nsec;
+};
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_blkcnt_t.h b/libc-bottom-half/headers/public/__typedef_blkcnt_t.h
new file mode 100644 (file)
index 0000000..e8d7b3d
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __wasilibc___typedef_blkcnt_t_h
+#define __wasilibc___typedef_blkcnt_t_h
+
+/* Define these as 64-bit signed integers to support files larger than 2 GiB. */
+typedef long long blkcnt_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_blksize_t.h b/libc-bottom-half/headers/public/__typedef_blksize_t.h
new file mode 100644 (file)
index 0000000..8816e0a
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __wasilibc___typedef_blksize_t_h
+#define __wasilibc___typedef_blksize_t_h
+
+typedef long blksize_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_clock_t.h b/libc-bottom-half/headers/public/__typedef_clock_t.h
new file mode 100644 (file)
index 0000000..68cb588
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __wasilibc___typedef_clock_t_h
+#define __wasilibc___typedef_clock_t_h
+
+/* Define this as a 64-bit signed integer to avoid wraparounds. */
+typedef long long clock_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_dev_t.h b/libc-bottom-half/headers/public/__typedef_dev_t.h
new file mode 100644 (file)
index 0000000..353e94f
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __wasilibc___typedef_dev_t_h
+#define __wasilibc___typedef_dev_t_h
+
+/* Define these as 64-bit integers to support billions of devices. */
+typedef unsigned long long dev_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_gid_t.h b/libc-bottom-half/headers/public/__typedef_gid_t.h
new file mode 100644 (file)
index 0000000..6eb82f2
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __wasilibc___typedef_gid_t_h
+#define __wasilibc___typedef_gid_t_h
+
+typedef unsigned gid_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_ino_t.h b/libc-bottom-half/headers/public/__typedef_ino_t.h
new file mode 100644 (file)
index 0000000..f3e11e4
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __wasilibc___typedef_ino_t_h
+#define __wasilibc___typedef_ino_t_h
+
+/* Define these as 64-bit integers to support billions of inodes. */
+typedef unsigned long long ino_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_mode_t.h b/libc-bottom-half/headers/public/__typedef_mode_t.h
new file mode 100644 (file)
index 0000000..51b927d
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __wasilibc___typedef_mode_t_h
+#define __wasilibc___typedef_mode_t_h
+
+typedef unsigned mode_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_nlink_t.h b/libc-bottom-half/headers/public/__typedef_nlink_t.h
new file mode 100644 (file)
index 0000000..ae34c79
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __wasilibc___typedef_nlink_t_h
+#define __wasilibc___typedef_nlink_t_h
+
+/* Define these as 64-bit unsigned integers to support billions of links. */
+typedef unsigned long long nlink_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_off_t.h b/libc-bottom-half/headers/public/__typedef_off_t.h
new file mode 100644 (file)
index 0000000..115ffdd
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __wasilibc___typedef_off_t_h
+#define __wasilibc___typedef_off_t_h
+
+/* Define these as 64-bit signed integers to support files larger than 2 GiB. */
+typedef long long off_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_ssize_t.h b/libc-bottom-half/headers/public/__typedef_ssize_t.h
new file mode 100644 (file)
index 0000000..25dc15a
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __wasilibc___typedef_ssize_t_h
+#define __wasilibc___typedef_ssize_t_h
+
+/* This is defined to be the same size as size_t. */
+typedef long ssize_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_suseconds_t.h b/libc-bottom-half/headers/public/__typedef_suseconds_t.h
new file mode 100644 (file)
index 0000000..92667e2
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __wasilibc___typedef_suseconds_t_h
+#define __wasilibc___typedef_suseconds_t_h
+
+/* Define this to be 64-bit as its main use is in struct timeval where the
+   extra space would otherwise be padding. */
+typedef long long suseconds_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_time_t.h b/libc-bottom-half/headers/public/__typedef_time_t.h
new file mode 100644 (file)
index 0000000..6ee0f86
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __wasilibc___typedef_time_t_h
+#define __wasilibc___typedef_time_t_h
+
+/* Define this as a 64-bit signed integer to avoid the 2038 bug. */
+typedef long long time_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/__typedef_uid_t.h b/libc-bottom-half/headers/public/__typedef_uid_t.h
new file mode 100644 (file)
index 0000000..c9da300
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __wasilibc___typedef_uid_t_h
+#define __wasilibc___typedef_uid_t_h
+
+typedef unsigned uid_t;
+
+#endif
diff --git a/libc-bottom-half/headers/public/inttypes.h b/libc-bottom-half/headers/public/inttypes.h
new file mode 100644 (file)
index 0000000..a237857
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __wasilibc_inttypes_h
+#define __wasilibc_inttypes_h
+
+/*
+ * Include the real implementation, which is factored into a separate file so
+ * that it can be reused by other libc stdlib implementations.
+ */
+#include <__header_inttypes.h>
+
+#endif
index 7ff8236e444a31b0d9ed24725be51b2b3e714bf1..8425cb80a9f0ed551a6f3c44680c0c98b89a56cf 100644 (file)
@@ -5,6 +5,6 @@
  * Include the real implementation, which is factored into a separate file so
  * that it can be reused by other libc stdlib implementations.
  */
-#include <__header_stdlib.h>
+#include <__functions_malloc.h>
 
 #endif
index fe81162f303643c1c427537fd317e136d119f38f..734d21203c52849a132bb4e23dde41c4af62ea57 100644 (file)
@@ -658,9 +658,9 @@ _Static_assert(sizeof(__wasi_rights_t) == 8, "witx calculated size");
 _Static_assert(_Alignof(__wasi_rights_t) == 8, "witx calculated align");
 
 /**
- * A file descriptor index.
+ * A file descriptor handle.
  */
-typedef uint32_t __wasi_fd_t;
+typedef int __wasi_fd_t;
 
 _Static_assert(sizeof(__wasi_fd_t) == 4, "witx calculated size");
 _Static_assert(_Alignof(__wasi_fd_t) == 4, "witx calculated align");
@@ -1219,7 +1219,7 @@ _Static_assert(sizeof(__wasi_subclockflags_t) == 2, "witx calculated size");
 _Static_assert(_Alignof(__wasi_subclockflags_t) == 2, "witx calculated align");
 
 /**
- * The contents of a $subscription when type is `eventtype::clock`.
+ * The contents of a `subscription` when type is `eventtype::clock`.
  */
 typedef struct __wasi_subscription_clock_t {
     /**
@@ -1253,7 +1253,7 @@ _Static_assert(offsetof(__wasi_subscription_clock_t, precision) == 16, "witx cal
 _Static_assert(offsetof(__wasi_subscription_clock_t, flags) == 24, "witx calculated offset");
 
 /**
- * The contents of a $subscription when type is type is
+ * The contents of a `subscription` when type is type is
  * `eventtype::fd_read` or `eventtype::fd_write`.
  */
 typedef struct __wasi_subscription_fd_readwrite_t {
@@ -1269,7 +1269,7 @@ _Static_assert(_Alignof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculat
 _Static_assert(offsetof(__wasi_subscription_fd_readwrite_t, file_descriptor) == 0, "witx calculated offset");
 
 /**
- * The contents of a $subscription.
+ * The contents of a `subscription`.
  */
 typedef union __wasi_subscription_u_u_t {
     __wasi_subscription_clock_t clock;
@@ -1666,17 +1666,17 @@ __wasi_errno_t __wasi_environ_get(
 ));
 
 /**
- * Return command-line argument data sizes.
+ * Return environment variable data sizes.
  */
 __wasi_errno_t __wasi_environ_sizes_get(
     /**
-     * The number of arguments.
+     * The number of environment variable arguments.
      */
-    __wasi_size_t *argc,
+    __wasi_size_t *environc,
     /**
-     * The size of the argument string data.
+     * The size of the environment variable data.
      */
-    __wasi_size_t *argv_buf_size
+    __wasi_size_t *environ_buf_size
 ) __attribute__((
     __import_module__("wasi_snapshot_preview1"),
     __import_name__("environ_sizes_get"),
index a6c336fbec0ad6398d5dca984904617564a56ad9..7395ad6daa7d9b2acf744151fe1dd41862dcb2e0 100644 (file)
@@ -12,7 +12,8 @@ extern "C" {
  *
  * Returns -1 if no directories were suitable.
  */
-int __wasilibc_find_relpath(const char *path, const char **relative_path);
+int __wasilibc_find_relpath(const char *path,
+                            const char **__restrict__ relative_path);
 
 #ifdef __cplusplus
 }
index 4bbc1dc8125229a324a366c61075ed5a83effce8..5997c473640835c9daa4e11ee43e67dbc850d3c3 100644 (file)
@@ -7,12 +7,29 @@
 extern "C" {
 #endif
 
-int __wasilibc_register_preopened_fd(int fd, const char *path);
+/// Register the given pre-opened file descriptor under the given path.
+///
+/// This function does not take ownership of `prefix` (it makes its own copy).
+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);
+
+/// Like `unlinkat`, but without depending on `__wasi_path_remove_directory`.
 int __wasilibc_unlinkat(int fd, const char *path);
+
+/// An `*at` version of rmdir.
 int __wasilibc_rmdirat(int fd, const char *path);
+
+/// Like `open`, but without the varargs in the signature.
 int __wasilibc_open_nomode(const char *path, int oflag);
+
+/// Like `openat`, but without the varargs in the signature.
 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);
 
 #ifdef __cplusplus
diff --git a/libc-bottom-half/headers/public/wchar.h b/libc-bottom-half/headers/public/wchar.h
new file mode 100644 (file)
index 0000000..f43d72f
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __wasilibc_wchar_h
+#define __wasilibc_wchar_h
+
+#define __need_size_t
+#define __need_wchar_t
+#define __need_NULL
+#include <stddef.h>
+
+#endif
diff --git a/libc-bottom-half/libpreopen/libpreopen.c b/libc-bottom-half/libpreopen/libpreopen.c
deleted file mode 100644 (file)
index fd1d6f9..0000000
+++ /dev/null
@@ -1,570 +0,0 @@
-//! Preopen functionality for WASI libc, for emulating support for absolute
-//! path names on top of WASI's OCap-style API.
-//!
-//! This file is derived from code in libpreopen, the upstream for which is:
-//!
-//!     https://github.com/musec/libpreopen
-//!
-//! and which bears the following copyrights and license:
-
-/*-
- * Copyright (c) 2016-2017 Stanley Uche Godfrey
- * Copyright (c) 2016-2018 Jonathan Anderson
- * All rights reserved.
- *
- * This software was developed at Memorial University under the
- * NSERC Discovery program (RGPIN-2015-06048).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef _REENTRANT
-#error "__wasilibc_register_preopened_fd doesn't yet support multiple threads"
-#endif
-
-#define _ALL_SOURCE
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <dirent.h>
-#include <assert.h>
-#include <sysexits.h>
-#include <wasi/libc.h>
-#include <wasi/libc-find-relpath.h>
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// POSIX API compatibility wrappers
-//
-////////////////////////////////////////////////////////////////////////////////
-
-int
-open(const char *path, int flags, ...)
-{
-    // WASI libc's openat ignores the mode argument, so call a special
-    // entrypoint which avoids the varargs calling convention.
-    return __wasilibc_open_nomode(path, flags);
-}
-
-int
-__wasilibc_open_nomode(const char *path, int flags)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(path, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return __wasilibc_openat_nomode(dirfd, relative_path, flags);
-}
-
-int
-access(const char *path, int mode)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(path, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return faccessat(dirfd, relative_path, mode, 0);
-}
-
-int
-lstat(const char *path, struct stat *st)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(path, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return fstatat(dirfd, relative_path, st, AT_SYMLINK_NOFOLLOW);
-}
-
-int
-rename(const char *from, const char *to)
-{
-    const char *from_relative_path;
-    int from_dirfd = __wasilibc_find_relpath(from, &from_relative_path);
-
-    const char *to_relative_path;
-    int to_dirfd = __wasilibc_find_relpath(to, &to_relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (from_dirfd == -1 || to_dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return renameat(from_dirfd, from_relative_path, to_dirfd, to_relative_path);
-}
-
-int
-stat(const char *path, struct stat *st)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(path, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return fstatat(dirfd, relative_path, st, AT_SYMLINK_NOFOLLOW);
-}
-
-int
-unlink(const char *path)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(path, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    // `unlinkat` ends up importing `__wasi_path_remove_directory` even
-    // though we're not passing `AT_REMOVEDIR` here. So instead, use a
-    // specialized function which just imports `__wasi_path_unlink_file`.
-    return __wasilibc_unlinkat(dirfd, relative_path);
-}
-
-int
-rmdir(const char *pathname)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(pathname, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return __wasilibc_rmdirat(dirfd, relative_path);
-}
-
-int
-remove(const char *pathname)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(pathname, &relative_path);
-
-    // If searching for both file and directory rights failed, try searching
-    // for either individually.
-    if (dirfd == -1) {
-        dirfd = __wasilibc_find_relpath(pathname, &relative_path);
-        if (dirfd == -1) {
-            dirfd = __wasilibc_find_relpath(pathname, &relative_path);
-        }
-    }
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    int r = __wasilibc_unlinkat(dirfd, relative_path);
-    if (r != 0 && (errno == EISDIR || errno == ENOTCAPABLE))
-        r = __wasilibc_rmdirat(dirfd, relative_path);
-    return r;
-}
-
-int
-link(const char *oldpath, const char *newpath)
-{
-    const char *old_relative_path;
-    int old_dirfd = __wasilibc_find_relpath(oldpath, &old_relative_path);
-
-    const char *new_relative_path;
-    int new_dirfd = __wasilibc_find_relpath(newpath, &new_relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (old_dirfd == -1 || new_dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return linkat(old_dirfd, old_relative_path, new_dirfd, new_relative_path, 0);
-}
-
-int
-mkdir(const char *pathname, mode_t mode)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(pathname, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return mkdirat(dirfd, relative_path, mode);
-}
-
-DIR *
-opendir(const char *name)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(name, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return NULL;
-    }
-
-    return opendirat(dirfd, relative_path);
-}
-
-ssize_t
-readlink(const char *pathname, char *buf, size_t bufsiz)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(pathname, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return readlinkat(dirfd, relative_path, buf, bufsiz);
-}
-
-int
-scandir(
-    const char *dirp,
-    struct dirent ***namelist,
-    int (*filter)(const struct dirent *),
-    int (*compar)(const struct dirent **, const struct dirent **))
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(dirp, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return scandirat(dirfd, relative_path, namelist, filter, compar);
-}
-
-int
-symlink(const char *target, const char *linkpath)
-{
-    const char *relative_path;
-    int dirfd = __wasilibc_find_relpath(linkpath, &relative_path);
-
-    // If we can't find a preopened directory handle to open this file with,
-    // indicate that the program lacks the capabilities.
-    if (dirfd == -1) {
-        errno = ENOTCAPABLE;
-        return -1;
-    }
-
-    return symlinkat(target, dirfd, relative_path);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Support library
-//
-////////////////////////////////////////////////////////////////////////////////
-
-/// An entry in a po_map.
-struct po_map_entry {
-    /// The name this file or directory is mapped to.
-    ///
-    /// This name should look like a path, but it does not necessarily need
-    /// match to match the path it was originally obtained from.
-    const char *name;
-
-    /// File descriptor (which may be a directory)
-    int fd;
-};
-
-/// A vector of po_map_entry.
-struct po_map {
-    struct po_map_entry *entries;
-    size_t capacity;
-    size_t length;
-};
-
-static struct po_map global_map;
-
-/// Is a directory a prefix of a given path?
-///
-/// @param   dir     a directory path, e.g., `/foo/bar`
-/// @param   dirlen  the length of @b dir
-/// @param   path    a path that may have @b dir as a prefix,
-///                  e.g., `/foo/bar/baz`
-static bool
-po_isprefix(const char *dir, size_t dirlen, const char *path)
-{
-    assert(dir != NULL);
-    assert(path != NULL);
-
-    // Allow an empty string as a prefix of any relative path.
-    if (path[0] != '/' && dirlen == 0)
-        return true;
-
-    size_t i;
-    for (i = 0; i < dirlen; i++)
-    {
-        if (path[i] != dir[i])
-            return false;
-    }
-
-    // Ignore trailing slashes in directory names.
-    while (i > 0 && dir[i - 1] == '/') {
-        --i;
-    }
-
-    return path[i] == '/' || path[i] == '\0';
-}
-
-/// Enlarge a @ref po_map's capacity.
-///
-/// This results in new memory being allocated and existing entries being copied.
-/// If the allocation fails, the function will return -1.
-static int
-po_map_enlarge(void)
-{
-    size_t start_capacity = 4;
-    size_t new_capacity = global_map.capacity == 0 ?
-                          start_capacity :
-                          global_map.capacity * 2;
-
-    struct po_map_entry *enlarged =
-        calloc(sizeof(struct po_map_entry), new_capacity);
-    if (enlarged == NULL) {
-        return -1;
-    }
-    memcpy(enlarged, global_map.entries, global_map.length * sizeof(*enlarged));
-    free(global_map.entries);
-    global_map.entries = enlarged;
-    global_map.capacity = new_capacity;
-    return 0;
-}
-
-/// Assert that the global_map is valid.
-#ifdef NDEBUG
-#define po_map_assertvalid()
-#else
-static void
-po_map_assertvalid(void)
-{
-    const struct po_map_entry *entry;
-    size_t i;
-
-    assert(global_map.length <= global_map.capacity);
-    assert(global_map.entries != NULL || global_map.capacity == 0);
-
-    for (i = 0; i < global_map.length; i++) {
-        entry = &global_map.entries[i];
-
-        assert(entry->name != NULL);
-        assert(entry->fd >= 0);
-    }
-}
-#endif
-
-/// Register the given pre-opened file descriptor under the given path.
-///
-/// This function takes ownership of `name`.
-static int
-internal_register_preopened_fd(int fd, const char *name)
-{
-    po_map_assertvalid();
-
-    assert(fd >= 0);
-    assert(name != NULL);
-
-    if (global_map.length == global_map.capacity) {
-        int n = po_map_enlarge();
-
-        po_map_assertvalid();
-
-        if (n != 0) {
-            return n;
-        }
-    }
-
-    struct po_map_entry *entry = &global_map.entries[global_map.length++];
-
-    entry->name = name;
-    entry->fd = fd;
-
-    po_map_assertvalid();
-
-    return 0;
-}
-
-/// Register the given pre-opened file descriptor under the given path.
-///
-/// This function does not take ownership of `path`.
-int
-__wasilibc_register_preopened_fd(int fd, const char *path)
-{
-    const char *name = strdup(path);
-    return name == NULL ? -1 : internal_register_preopened_fd(fd, name);
-}
-
-int
-__wasilibc_find_relpath(
-    const char *path,
-    const char **relative_path)
-{
-    size_t bestlen = 0;
-    int best = -1;
-
-    po_map_assertvalid();
-
-    assert(path != NULL);
-    assert(relative_path != NULL);
-
-    bool any_matches = false;
-    for (size_t i = 0; i < global_map.length; i++) {
-        const struct po_map_entry *entry = &global_map.entries[i];
-        const char *name = entry->name;
-        size_t len = strlen(name);
-
-        if (path[0] != '/' && (path[0] != '.' || (path[1] != '/' && path[1] != '\0'))) {
-            // We're matching a relative path that doesn't start with "./" and isn't ".".
-            if (len >= 2 && name[0] == '.' && name[1] == '/') {
-                // The entry starts with "./", so skip that prefix.
-                name += 2;
-                len -= 2;
-            } else if (len == 1 && name[0] == '.') {
-                // The entry is ".", so match it as an empty string.
-                name += 1;
-                len -= 1;
-            }
-        }
-
-        if ((any_matches && len <= bestlen) || !po_isprefix(name, len, path)) {
-            continue;
-        }
-
-        best = entry->fd;
-        bestlen = len;
-        any_matches = true;
-    }
-
-    const char *relpath = path + bestlen;
-
-    while (*relpath == '/') {
-        relpath++;
-    }
-
-    if (*relpath == '\0') {
-        relpath = ".";
-    }
-
-    *relative_path = relpath;
-    return best;
-}
-
-/// This is referenced by weak reference from crt1.c and lives in the same source
-/// file as `__wasilibc_find_relpath` so that it's linked in when it's needed.
-// Concerning the 51 -- see the comment by the constructor priority in
-// libc-bottom-half/sources/__wasilibc_environ.c.
-__attribute__((constructor(51)))
-static void
-__wasilibc_populate_libpreopen(void)
-{
-    // Skip stdin, stdout, and stderr, and count up until we reach an invalid
-    // file descriptor.
-    for (__wasi_fd_t fd = 3; fd != 0; ++fd) {
-        __wasi_prestat_t prestat;
-        __wasi_errno_t ret = __wasi_fd_prestat_get(fd, &prestat);
-        if (ret == __WASI_ERRNO_BADF)
-            break;
-        if (ret != __WASI_ERRNO_SUCCESS)
-            goto oserr;
-        switch (prestat.tag) {
-        case __WASI_PREOPENTYPE_DIR: {
-            char *path = malloc(prestat.u.dir.pr_name_len + 1);
-            if (path == NULL)
-                goto software;
-
-            // TODO: Remove the cast on `path` once the witx is updated with char8 support.
-            ret = __wasi_fd_prestat_dir_name(fd, (uint8_t *)path, prestat.u.dir.pr_name_len);
-            if (ret != __WASI_ERRNO_SUCCESS) {
-                goto oserr;
-            }
-            path[prestat.u.dir.pr_name_len] = '\0';
-
-            if (internal_register_preopened_fd(fd, path) != 0) {
-                goto software;
-            }
-
-            break;
-        }
-        default:
-            break;
-        }
-    }
-
-    return;
-oserr:
-    _Exit(EX_OSERR);
-software:
-    _Exit(EX_SOFTWARE);
-}
index 1b806ff8d06b32c69383d40474c4aed72b87d0a5..f02b136cd248582d5f3f628bcffa575b76151ee1 100644 (file)
@@ -17,15 +17,15 @@ struct map {
     int flags;
     off_t offset;
     size_t length;
-    char body[];
 };
 
 void *mmap(void *addr, size_t length, int prot, int flags,
            int fd, off_t offset) {
     // Check for unsupported flags.
-    if ((flags & MAP_FIXED) != 0 ||
+    if ((flags & (MAP_PRIVATE | MAP_SHARED)) == 0 ||
+        (flags & MAP_FIXED) != 0 ||
 #ifdef MAP_SHARED_VALIDATE
-        (flags & MAP_SHARED_VALIDATE) != 0 ||
+        (flags & MAP_SHARED_VALIDATE) == MAP_SHARED_VALIDATE ||
 #endif
 #ifdef MAP_NORESERVE
         (flags & MAP_NORESERVE) != 0 ||
@@ -84,8 +84,9 @@ void *mmap(void *addr, size_t length, int prot, int flags,
 
     // Initialize the main memory buffer, either with the contents of a file,
     // or with zeros.
+    addr = map + 1;
     if ((flags & MAP_ANON) == 0) {
-        char *body = map->body;
+        char *body = (char *)addr;
         while (length > 0) {
             const ssize_t nread = pread(fd, body, length, offset);
             if (nread < 0) {
@@ -100,10 +101,10 @@ void *mmap(void *addr, size_t length, int prot, int flags,
             body += (size_t)nread;
         }
     } else {
-        memset(map->body, 0, length);
+        memset(addr, 0, length);
     }
 
-    return map->body;
+    return addr;
 }
 
 int munmap(void *addr, size_t length) {
diff --git a/libc-bottom-half/signal/signal.c b/libc-bottom-half/signal/signal.c
new file mode 100644 (file)
index 0000000..1c24dfd
--- /dev/null
@@ -0,0 +1,142 @@
+// Userspace emulation of `raise` and `signal`.
+//
+// WebAssembly doesn't support asynchronous signal delivery, so we can't
+// support it in WASI libc. But we can make things like `raise` work.
+
+#define _WASI_EMULATED_SIGNAL
+#define _ALL_SOURCE
+#define _GNU_SOURCE
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+void __SIG_IGN(int sig) {
+    // do nothing
+}
+
+_Noreturn
+void __SIG_ERR(int sig) {
+    __builtin_trap();
+}
+
+_Noreturn
+static void core_handler(int sig) {
+    fprintf(stderr, "Program recieved fatal signal: %s\n", strsignal(sig));
+    abort();
+}
+
+_Noreturn
+static void terminate_handler(int sig) {
+    fprintf(stderr, "Program recieved termination signal: %s\n", strsignal(sig));
+    abort();
+}
+
+_Noreturn
+static void stop_handler(int sig) {
+    fprintf(stderr, "Program recieved stop signal: %s\n", strsignal(sig));
+    abort();
+}
+
+static void continue_handler(int sig) {
+    // do nothing
+}
+
+static const sighandler_t default_handlers[_NSIG] = {
+    // Default behavior: "core".
+    [SIGABRT] = core_handler,
+    [SIGBUS] = core_handler,
+    [SIGFPE] = core_handler,
+    [SIGILL] = core_handler,
+#if SIGIOT != SIGABRT
+    [SIGIOT] = core_handler,
+#endif
+    [SIGQUIT] = core_handler,
+    [SIGSEGV] = core_handler,
+    [SIGSYS] = core_handler,
+    [SIGTRAP] = core_handler,
+    [SIGXCPU] = core_handler,
+    [SIGXFSZ] = core_handler,
+#if defined(SIGUNUSED) && SIGUNUSED != SIGSYS
+    [SIGUNUSED] = core_handler,
+#endif
+
+    // Default behavior: ignore.
+    [SIGCHLD] = SIG_IGN,
+#if defined(SIGCLD) && SIGCLD != SIGCHLD
+    [SIGCLD] = SIG_IGN,
+#endif
+    [SIGURG] = SIG_IGN,
+    [SIGWINCH] = SIG_IGN,
+
+    // Default behavior: "continue".
+    [SIGCONT] = continue_handler,
+
+    // Default behavior: "stop".
+    [SIGSTOP] = stop_handler,
+    [SIGTSTP] = stop_handler,
+    [SIGTTIN] = stop_handler,
+    [SIGTTOU] = stop_handler,
+
+    // Default behavior: "terminate".
+    [SIGHUP] = terminate_handler,
+    [SIGINT] = terminate_handler,
+    [SIGKILL] = terminate_handler,
+    [SIGUSR1] = terminate_handler,
+    [SIGUSR2] = terminate_handler,
+    [SIGPIPE] = terminate_handler,
+    [SIGALRM] = terminate_handler,
+    [SIGTERM] = terminate_handler,
+    [SIGSTKFLT] = terminate_handler,
+    [SIGVTALRM] = terminate_handler,
+    [SIGPROF] = terminate_handler,
+    [SIGIO] = terminate_handler,
+#if SIGPOLL != SIGIO
+    [SIGPOLL] = terminate_handler,
+#endif
+    [SIGPWR] = terminate_handler,
+};
+
+static sighandler_t handlers[_NSIG];
+
+int raise(int sig) {
+    if (sig < 0 || sig >= _NSIG) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    sighandler_t func = handlers[sig];
+
+    if (func == NULL) {
+        default_handlers[sig](sig);
+    } else {
+        func(sig);
+    }
+
+    return 0;
+}
+
+void (*signal(int sig, void (*func)(int)))(int) {
+    assert(SIG_DFL == NULL);
+
+    if (sig < 0 || sig >= _NSIG) {
+        errno = EINVAL;
+        return SIG_ERR;
+    }
+
+    if (sig == SIGKILL || sig == SIGSTOP) {
+        errno = EINVAL;
+        return SIG_ERR;
+    }
+
+    sighandler_t old = handlers[sig];
+
+    handlers[sig] = func;
+
+    return old;
+}
+
+extern __typeof(signal) bsd_signal __attribute__((weak, alias("signal")));
+extern __typeof(signal) __sysv_signal __attribute__((weak, alias("signal")));
diff --git a/libc-bottom-half/sources/abort.c b/libc-bottom-half/sources/abort.c
new file mode 100644 (file)
index 0000000..95fe2be
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+void abort(void) {
+    // wasm doesn't support signals, so just trap to halt the program.
+    __builtin_trap();
+}
diff --git a/libc-bottom-half/sources/complex-builtins.c b/libc-bottom-half/sources/complex-builtins.c
new file mode 100644 (file)
index 0000000..b6588f7
--- /dev/null
@@ -0,0 +1,21 @@
+// Each of the following complex functions can be implemented with a single
+// wasm instruction, so use that implementation rather than the portable
+// one in libm.
+
+#include <complex.h>
+
+float crealf(float _Complex x) {
+    return __real__ x;
+}
+
+double creal(double _Complex x) {
+    return __real__ x;
+}
+
+float cimagf(float _Complex x) {
+    return __imag__ x;
+}
+
+double cimag(double _Complex x) {
+    return __imag__ x;
+}
index 32dadd574109a6355daad1f3c44d72eb6a37556b..4e98a5b84db8ad74507c4c0a74f820bba6acf755 100644 (file)
@@ -1,5 +1,4 @@
 #include <errno.h>
-#include <threads.h>
 
 // These values are used by reference-sysroot's dlmalloc.
 const int __EINVAL = EINVAL;
diff --git a/libc-bottom-half/sources/math/fmin-fmax.c b/libc-bottom-half/sources/math/fmin-fmax.c
new file mode 100644 (file)
index 0000000..9293798
--- /dev/null
@@ -0,0 +1,34 @@
+// Wasm's `min` and `max` operators implement the IEEE 754-2019
+// `minimum` and `maximum` operations, meaning that given a choice
+// between NaN and a number, they return NaN. This differs from
+// the C standard library's `fmin` and `fmax` functions, which
+// return the number. However, we can still use wasm's builtins
+// by handling the NaN cases explicitly, and it still turns out
+// to be faster than doing the whole operation in
+// target-independent C. And, it's smaller.
+
+#include <math.h>
+
+float fminf(float x, float y) {
+    if (isnan(x)) return y;
+    if (isnan(y)) return x;
+    return __builtin_wasm_min_f32(x, y);
+}
+
+float fmaxf(float x, float y) {
+    if (isnan(x)) return y;
+    if (isnan(y)) return x;
+    return __builtin_wasm_max_f32(x, y);
+}
+
+double fmin(double x, double y) {
+    if (isnan(x)) return y;
+    if (isnan(y)) return x;
+    return __builtin_wasm_min_f64(x, y);
+}
+
+double fmax(double x, double y) {
+    if (isnan(x)) return y;
+    if (isnan(y)) return x;
+    return __builtin_wasm_max_f64(x, y);
+}
diff --git a/libc-bottom-half/sources/math/math-builtins.c b/libc-bottom-half/sources/math/math-builtins.c
new file mode 100644 (file)
index 0000000..a5eb7cd
--- /dev/null
@@ -0,0 +1,69 @@
+// Each of the following math functions can be implemented with a single
+// wasm instruction, so use that implementation rather than the portable
+// one in libm.
+
+#include <math.h>
+
+float fabsf(float x) {
+    return __builtin_fabsf(x);
+}
+
+double fabs(double x) {
+    return __builtin_fabs(x);
+}
+
+float sqrtf(float x) {
+    return __builtin_sqrtf(x);
+}
+
+double sqrt(double x) {
+    return __builtin_sqrt(x);
+}
+
+float copysignf(float x, float y) {
+    return __builtin_copysignf(x, y);
+}
+
+double copysign(double x, double y) {
+    return __builtin_copysign(x, y);
+}
+
+float ceilf(float x) {
+    return __builtin_ceilf(x);
+}
+
+double ceil(double x) {
+    return __builtin_ceil(x);
+}
+
+float floorf(float x) {
+    return __builtin_floorf(x);
+}
+
+double floor(double x) {
+    return __builtin_floor(x);
+}
+
+float truncf(float x) {
+    return __builtin_truncf(x);
+}
+
+double trunc(double x) {
+    return __builtin_trunc(x);
+}
+
+float nearbyintf(float x) {
+    return __builtin_nearbyintf(x);
+}
+
+double nearbyint(double x) {
+    return __builtin_nearbyint(x);
+}
+
+float rintf(float x) {
+    return __builtin_rintf(x);
+}
+
+double rint(double x) {
+    return __builtin_rint(x);
+}
diff --git a/libc-bottom-half/sources/pause.c b/libc-bottom-half/sources/pause.c
deleted file mode 100644 (file)
index 0e3e712..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stddef.h>
-#include <errno.h>
-#include <wasi/api.h>
-#include <unistd.h>
-
-int pause(void) {
-    size_t n;
-    __wasi_errno_t error = __wasi_poll_oneoff(0, 0, 0, &n);
-    if (error != 0) {
-        errno = error;
-        return -1;
-    }
-    __builtin_trap();
-}
diff --git a/libc-bottom-half/sources/posix.c b/libc-bottom-half/sources/posix.c
new file mode 100644 (file)
index 0000000..64e6bfa
--- /dev/null
@@ -0,0 +1,251 @@
+//! POSIX-like functions supporting absolute path arguments, implemented in
+//! terms of `__wasilibc_find_relpath` and `*at`-style functions.
+
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <wasi/libc.h>
+#include <wasi/libc-find-relpath.h>
+
+int open(const char *path, int oflag, ...) {
+    // WASI libc's `openat` ignores the mode argument, so call a special
+    // entrypoint which avoids the varargs calling convention.
+    return __wasilibc_open_nomode(path, oflag);
+}
+
+// See the documentation in libc.h
+int __wasilibc_open_nomode(const char *path, int oflag) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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_openat_nomode(dirfd, relative_path, oflag);
+}
+
+int access(const char *path, int amode) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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 faccessat(dirfd, relative_path, amode, 0);
+}
+
+ssize_t readlink(
+    const char *restrict path,
+    char *restrict buf,
+    size_t bufsize)
+{
+    const char *relative_path;
+    int dirfd = __wasilibc_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 readlinkat(dirfd, relative_path, buf, bufsize);
+}
+
+int stat(const char *restrict path, struct stat *restrict buf) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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 fstatat(dirfd, relative_path, buf, 0);
+}
+
+int lstat(const char *restrict path, struct stat *restrict buf) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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 fstatat(dirfd, relative_path, buf, AT_SYMLINK_NOFOLLOW);
+}
+
+int utime(const char *path, const struct utimbuf *times) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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 utimensat(dirfd, relative_path,
+                     times ? ((struct timespec [2]) {
+                                 { .tv_sec = times->actime },
+                                 { .tv_sec = times->modtime }
+                             })
+                           : NULL,
+                     0);
+}
+
+int unlink(const char *path) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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;
+    }
+
+    // `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);
+}
+
+int rmdir(const char *path) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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_rmdirat(dirfd, relative_path);
+}
+
+int remove(const char *path) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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;
+    }
+
+    // First try to remove it as a file.
+    int r = __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);
+
+        // If it isn't a directory, we lack capabilities to remove it as a file.
+        if (errno == ENOTDIR)
+            errno = ENOTCAPABLE;
+    }
+    return r;
+}
+
+int mkdir(const char *path, mode_t mode) {
+    const char *relative_path;
+    int dirfd = __wasilibc_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 mkdirat(dirfd, relative_path, mode);
+}
+
+DIR *opendir(const char *dirname) {
+    const char *relative_path;
+    int dirfd = __wasilibc_find_relpath(dirname, &relative_path);
+
+    // If we can't find a preopen for it, indicate that we lack capabilities.
+    if (dirfd == -1) {
+        errno = ENOTCAPABLE;
+        return NULL;
+    }
+
+    return opendirat(dirfd, relative_path);
+}
+
+int scandir(
+    const char *restrict dir,
+    struct dirent ***restrict namelist,
+    int (*filter)(const struct dirent *),
+    int (*compar)(const struct dirent **, const struct dirent **)
+) {
+    const char *relative_path;
+    int dirfd = __wasilibc_find_relpath(dir, &relative_path);
+
+    // If we can't find a preopen for it, indicate that we lack capabilities.
+    if (dirfd == -1) {
+        errno = ENOTCAPABLE;
+        return -1;
+    }
+
+    return scandirat(dirfd, relative_path, namelist, filter, compar);
+}
+
+int symlink(const char *target, const char *linkpath) {
+    const char *relative_path;
+    int dirfd = __wasilibc_find_relpath(linkpath, &relative_path);
+
+    // If we can't find a preopen for it, indicate that we lack capabilities.
+    if (dirfd == -1) {
+        errno = ENOTCAPABLE;
+        return -1;
+    }
+
+    return symlinkat(target, dirfd, relative_path);
+}
+
+int link(const char *old, const char *new) {
+    const char *old_relative_path;
+    int old_dirfd = __wasilibc_find_relpath(old, &old_relative_path);
+
+    if (old_dirfd != -1) {
+        const char *new_relative_path;
+        int new_dirfd = __wasilibc_find_relpath(new, &new_relative_path);
+
+        if (new_dirfd != -1)
+            return 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.
+    errno = ENOTCAPABLE;
+    return -1;
+}
+
+int rename(const char *old, const char *new) {
+    const char *old_relative_path;
+    int old_dirfd = __wasilibc_find_relpath(old, &old_relative_path);
+
+    if (old_dirfd != -1) {
+        const char *new_relative_path;
+        int new_dirfd = __wasilibc_find_relpath(new, &new_relative_path);
+
+        if (new_dirfd != -1)
+            return 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;
+}
diff --git a/libc-bottom-half/sources/preopens.c b/libc-bottom-half/sources/preopens.c
new file mode 100644 (file)
index 0000000..fa0e12f
--- /dev/null
@@ -0,0 +1,218 @@
+//! Support for "preopens", file descriptors passed into the program from the
+//! environment, with associated path prefixes, which can be used to map
+//! absolute paths to capabilities with relative paths.
+
+#ifdef _REENTRANT
+#error "__wasilibc_register_preopened_fd doesn't yet support multiple threads"
+#endif
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <wasi/api.h>
+#include <wasi/libc.h>
+#include <wasi/libc-find-relpath.h>
+
+/// A name and file descriptor pair.
+typedef struct preopen {
+    /// The path prefix associated with the file descriptor.
+    const char *prefix;
+
+    /// The file descriptor.
+    __wasi_fd_t fd;
+} preopen;
+
+/// A simple growable array of `preopen`.
+static preopen *preopens;
+static size_t num_preopens;
+static size_t preopen_capacity;
+
+#ifdef NDEBUG
+#define assert_invariants() // assertions disabled
+#else
+static void assert_invariants(void) {
+    assert(num_preopens <= preopen_capacity);
+    assert(preopen_capacity == 0 || preopens != NULL);
+    assert(preopen_capacity == 0 ||
+           preopen_capacity * sizeof(preopen) > preopen_capacity);
+
+    for (size_t i = 0; i < num_preopens; ++i) {
+        const preopen *pre = &preopens[i];
+        assert(pre->prefix != NULL);
+        assert(pre->fd != (__wasi_fd_t)-1);
+#ifdef __wasm__
+        assert((uintptr_t)pre->prefix <
+               (__uint128_t)__builtin_wasm_memory_size(0) * PAGESIZE);
+#endif
+    }
+}
+#endif
+
+/// Allocate space for more preopens. Returns 0 on success and -1 on failure.
+static int resize(void) {
+    size_t start_capacity = 4;
+    size_t old_capacity = preopen_capacity;
+    size_t new_capacity = old_capacity == 0 ? start_capacity : old_capacity * 2;
+
+    preopen *old_preopens = preopens;
+    preopen *new_preopens = calloc(sizeof(preopen), new_capacity);
+    if (new_preopens == NULL)
+        return -1;
+
+    memcpy(new_preopens, old_preopens, num_preopens * sizeof(preopen));
+    preopens = new_preopens;
+    preopen_capacity = new_capacity;
+    free(old_preopens);
+
+    assert_invariants();
+    return 0;
+}
+
+/// Register the given preopened file descriptor under the given path.
+///
+/// This function takes ownership of `prefix`.
+static int internal_register_preopened_fd(__wasi_fd_t fd, const char *prefix) {
+    assert_invariants();
+
+    if (num_preopens == preopen_capacity && resize() != 0)
+        return -1;
+
+    preopens[num_preopens++] = (preopen) { prefix, fd, };
+
+    assert_invariants();
+    return 0;
+}
+
+/// Are the `prefix_len` bytes pointed to by `prefix` a prefix of `path`?
+static bool prefix_matches(const char *prefix, size_t prefix_len, const char *path) {
+    // Allow an empty string as a prefix of any relative path.
+    if (path[0] != '/' && prefix_len == 0)
+        return true;
+
+    // Check whether any bytes of the prefix differ.
+    if (memcmp(path, prefix, prefix_len) != 0)
+        return false;
+
+    // Ignore trailing slashes in directory names.
+    size_t i = prefix_len;
+    while (i > 0 && prefix[i - 1] == '/') {
+        --i;
+    }
+
+    // Match only complete path components.
+    char last = path[i];
+    return last == '/' || last == '\0';
+}
+
+// See the documentation in libc.h
+int __wasilibc_register_preopened_fd(int fd, const char *prefix) {
+    prefix = strdup(prefix);
+    return prefix == NULL ? -1 :
+           internal_register_preopened_fd((__wasi_fd_t)fd, prefix);
+}
+
+// See the documentation in libc-find-relpath.h.
+int __wasilibc_find_relpath(const char *path,
+                            const char **restrict relative_path) {
+    assert_invariants();
+
+    // Search through the preopens table. Iterate in reverse so that more
+    // recently added preopens take precedence over less recently addded ones.
+    size_t match_len = 0;
+    int fd = -1;
+    for (size_t i = num_preopens; i > 0; --i) {
+        const preopen *pre = &preopens[i - 1];
+        const char *prefix = pre->prefix;
+        size_t len = strlen(prefix);
+
+        if (path[0] != '/' &&
+            (path[0] != '.' || (path[1] != '/' && path[1] != '\0')))
+        {
+            // We're matching a relative path that doesn't start with "./" and
+            // isn't ".".
+            if (len >= 2 && prefix[0] == '.' && prefix[1] == '/') {
+                // The preopen starts with "./", so skip that prefix.
+                prefix += 2;
+                len -= 2;
+            } else if (len == 1 && prefix[0] == '.') {
+                // The preopen is ".", so match it as an empty string.
+                prefix += 1;
+                len -= 1;
+            }
+        }
+
+        // If we haven't had a match yet, or the candidate path is longer than
+        // our current best match's path, and the candidate path is a prefix of
+        // the requested path, take that as the new best path.
+        if ((fd == -1 || len > match_len) &&
+            prefix_matches(prefix, len, path))
+        {
+            fd = pre->fd;
+            match_len = len;
+        }
+    }
+
+    // The relative path is the substring after the portion that was matched.
+    const char *computed = path + match_len;
+
+    // Omit leading slashes in the relative path.
+    while (*computed == '/')
+        ++computed;
+
+    // *at syscalls don't accept empty relative paths, so use "." instead.
+    if (*computed == '\0')
+        computed = ".";
+
+    *relative_path = computed;
+    return fd;
+}
+
+/// This is referenced by weak reference from crt1.c and lives in the same
+/// source file as `__wasilibc_find_relpath` so that it's linked in when it's
+/// needed.
+// Concerning the 51 -- see the comment by the constructor priority in
+// libc-bottom-half/sources/environ.c.
+__attribute__((constructor(51)))
+static void __wasilibc_populate_preopens(void) {
+    // Skip stdin, stdout, and stderr, and count up until we reach an invalid
+    // file descriptor.
+    for (__wasi_fd_t fd = 3; fd != 0; ++fd) {
+        __wasi_prestat_t prestat;
+        __wasi_errno_t ret = __wasi_fd_prestat_get(fd, &prestat);
+        if (ret == __WASI_ERRNO_BADF)
+            break;
+        if (ret != __WASI_ERRNO_SUCCESS)
+            goto oserr;
+        switch (prestat.tag) {
+        case __WASI_PREOPENTYPE_DIR: {
+            char *prefix = malloc(prestat.u.dir.pr_name_len + 1);
+            if (prefix == NULL)
+                goto software;
+
+            // TODO: Remove the cast on `path` once the witx is updated with
+            // char8 support.
+            ret = __wasi_fd_prestat_dir_name(fd, (uint8_t *)prefix,
+                                             prestat.u.dir.pr_name_len);
+            if (ret != __WASI_ERRNO_SUCCESS)
+                goto oserr;
+            prefix[prestat.u.dir.pr_name_len] = '\0';
+
+            if (internal_register_preopened_fd(fd, prefix) != 0)
+                goto software;
+
+            break;
+        }
+        default:
+            break;
+        }
+    }
+
+    return;
+oserr:
+    _Exit(EX_OSERR);
+software:
+    _Exit(EX_SOFTWARE);
+}
diff --git a/libc-bottom-half/sources/reallocarray.c b/libc-bottom-half/sources/reallocarray.c
new file mode 100644 (file)
index 0000000..3e828cc
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+#include <errno.h>
+
+void *__reallocarray(void *ptr, size_t nmemb, size_t size) {
+    size_t bytes;
+    if (__builtin_umull_overflow(nmemb, size, &bytes)) {
+        errno = ENOMEM;
+        return NULL;
+    }
+    return realloc(ptr, bytes);
+}
+
+void *reallocarray(void *ptr, size_t nmemb, size_t size)
+    __attribute__((__weak__, __alias__("__reallocarray")));
diff --git a/libc-bottom-half/sources/string.c b/libc-bottom-half/sources/string.c
deleted file mode 100644 (file)
index 2055465..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-size_t strlen(const char *str) {
-    const char *s = str;
-    while (*s) {
-        ++s;
-    }
-    return s - str;
-}
-
-char *strdup(const char *str) {
-    size_t buf_len = strlen(str) + 1;
-    void *ptr = malloc(buf_len);
-    if (ptr == NULL) {
-        return NULL;
-    }
-    return memcpy(ptr, str, buf_len);
-}
-
-int strcmp(const char *a, const char *b) {
-    while (*a != '\0' && (*a == *b)) {
-        ++a;
-        ++b;
-    }
-    return *(const unsigned char*)a - *(const unsigned char*)b;
-}
-
-void *memchr(const void *ptr, int c, size_t len) {
-    const unsigned char *p = ptr;
-    while (len != 0 && *p != (unsigned char)c) {
-        ++p;
-        --len;
-    }
-    if (len == 0) {
-        return NULL;
-    }
-    return (void *)p;
-}
index b2dd7c94d93a05383fa127a9b8a0256aaa705176..c4b81b83dc9407f0ba38af76ee3f934b8f0c3447 100644 (file)
@@ -1,5 +1,11 @@
+# WASI libc "top half".
+
+The WASI libc "top half" is conceptually the upper half of a traditional libc
+implementation, consisting of C standard library and other relatively
+higher-level functionality.
+
 Code in the musl directory is based on musl revision
-b07d45eb01e900f0176894fdedab62285f5cb8be, which is v1.1.23, from
+040c1d16b468c50c04fc94edff521f1637708328, which is v1.2.0, from
 git://git.musl-libc.org/musl.
 
 Whole files which are unused are omitted. Changes to upstream code are wrapped
index a30eb112750c1592081bd8a4e8d9409befbe7419..9870f73aa0fd157a2f007ec18d0a95fbc936ccc1 100644 (file)
@@ -20,4 +20,4 @@ Information on full musl-targeted compiler toolchains, system
 bootstrapping, and Linux distributions built on musl can be found on
 the project website:
 
-    http://www.musl-libc.org/
+    https://musl.libc.org/
index 547108772cb9984c535a4213e3114e184f5fbc4a..77e8d8c61e8c31a1104f12625ccf8b0ea17c4bf0 100644 (file)
@@ -1 +1,40 @@
-#include <__header_bits_signal.h>
+#ifdef _WASI_EMULATED_SIGNAL
+
+#define SIGHUP    1
+#define SIGINT    2
+#define SIGQUIT   3
+#define SIGILL    4
+#define SIGTRAP   5
+#define SIGABRT   6
+#define SIGIOT    SIGABRT
+#define SIGBUS    7
+#define SIGFPE    8
+#define SIGKILL   9
+#define SIGUSR1   10
+#define SIGSEGV   11
+#define SIGUSR2   12
+#define SIGPIPE   13
+#define SIGALRM   14
+#define SIGTERM   15
+#define SIGSTKFLT 16
+#define SIGCHLD   17
+#define SIGCONT   18
+#define SIGSTOP   19
+#define SIGTSTP   20
+#define SIGTTIN   21
+#define SIGTTOU   22
+#define SIGURG    23
+#define SIGXCPU   24
+#define SIGXFSZ   25
+#define SIGVTALRM 26
+#define SIGPROF   27
+#define SIGWINCH  28
+#define SIGIO     29
+#define SIGPOLL   29
+#define SIGPWR    30
+#define SIGSYS    31
+#define SIGUNUSED SIGSYS
+
+#define _NSIG 65
+
+#endif
index 068234f4c0238de815998417407455ffdb74a572..a83503294d35604a36c111b1607b0b9ae6e0da20 100644 (file)
@@ -1,3 +1,7 @@
+#ifndef _WASI_EMULATED_SIGNAL
+#error "wasm lacks signal support; to enable minimal signal emulation, \
+compile with -D_WASI_EMULATED_SIGNAL and link with -lwasi-emulated-signal"
+#else
 #ifndef _SIGNAL_H
 #define _SIGNAL_H
 
@@ -15,7 +19,6 @@ extern "C" {
 #ifdef _GNU_SOURCE
 #define __ucontext ucontext
 #endif
-#endif
 
 #define __NEED_size_t
 #define __NEED_pid_t
@@ -44,6 +47,7 @@ extern "C" {
 #define SI_KERNEL 128
 
 typedef struct sigaltstack stack_t;
+#endif
 
 #endif
 
@@ -53,6 +57,7 @@ typedef struct sigaltstack stack_t;
  || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
  || defined(_BSD_SOURCE)
 
+#ifdef __wasilibc_unmodified_upstream /* WASI has no sigaction */
 #define SIG_HOLD ((void (*)(int)) 2)
 
 #define FPE_INTDIV 1
@@ -190,6 +195,7 @@ struct sigevent {
 #define SIGEV_SIGNAL 0
 #define SIGEV_NONE 1
 #define SIGEV_THREAD 2
+#endif
 
 #ifdef __wasilibc_unmodified_upstream /* WASI has no realtime signals */
 int __libc_current_sigrtmin(void);
@@ -218,13 +224,15 @@ int sigtimedwait(const sigset_t *__restrict, siginfo_t *__restrict, const struct
 int sigqueue(pid_t, int, union sigval);
 #endif
 
+#ifdef __wasilibc_unmodified_upstream /* WASI has no threads yet */
 int pthread_sigmask(int, const sigset_t *__restrict, sigset_t *__restrict);
 int pthread_kill(pthread_t, int);
+#endif
 
-#ifdef __wasilibc_unmodified_upstream /* WASI has no signals */
+#ifdef __wasilibc_unmodified_upstream /* WASI has no siginfo */
 void psiginfo(const siginfo_t *, const char *);
-void psignal(int, const char *);
 #endif
+void psignal(int, const char *);
 
 #endif
 
@@ -256,7 +264,6 @@ void (*sigset(int, void (*)(int)))(int);
 #endif
 #endif
 
-#ifdef __wasilibc_unmodified_upstream /* WASI has no signals */
 #if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
 #define NSIG _NSIG
 typedef void (*sig_t)(int);
@@ -265,6 +272,7 @@ typedef void (*sig_t)(int);
 #ifdef _GNU_SOURCE
 typedef void (*sighandler_t)(int);
 void (*bsd_signal(int, void (*)(int)))(int);
+#ifdef __wasilibc_unmodified_upstream /* WASI has no signal sets */
 int sigisemptyset(const sigset_t *);
 int sigorset (sigset_t *, const sigset_t *, const sigset_t *);
 int sigandset(sigset_t *, const sigset_t *, const sigset_t *);
@@ -272,19 +280,30 @@ int sigandset(sigset_t *, const sigset_t *, const sigset_t *);
 #define SA_NOMASK SA_NODEFER
 #define SA_ONESHOT SA_RESETHAND
 #endif
+#endif
 
+#ifdef __wasilibc_unmodified_upstream /* 1 is a valid function pointer on wasm */
 #define SIG_ERR  ((void (*)(int))-1)
 #define SIG_DFL  ((void (*)(int)) 0)
 #define SIG_IGN  ((void (*)(int)) 1)
+#else
+void __SIG_ERR(int);
+void __SIG_IGN(int);
+#define SIG_ERR  (__SIG_ERR)
+#define SIG_DFL  ((void (*)(int)) 0)
+#define SIG_IGN  (__SIG_IGN)
 #endif
 
+#ifdef __wasilibc_unmodified_upstream /* Make sig_atomic_t 64-bit on wasm64 */
 typedef int sig_atomic_t;
+#else
+typedef long sig_atomic_t;
+#endif
 
-#ifdef __wasilibc_unmodified_upstream /* WASI has no signals */
 void (*signal(int, void (*)(int)))(int);
-#endif
 int raise(int);
 
+#ifdef __wasilibc_unmodified_upstream /* WASI has no sigtimedwait */
 #if _REDIR_TIME64
 #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
  || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
@@ -292,9 +311,11 @@ int raise(int);
 __REDIR(sigtimedwait, __sigtimedwait_time64);
 #endif
 #endif
+#endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
+#endif
index c6fe070bbbf3a02a6b22f80c2c3912950e8a3123..e55f638e9e59fce83cd114e8d6e16d149938dd9c 100644 (file)
@@ -128,7 +128,9 @@ char *getcwd(char *, size_t);
 unsigned alarm(unsigned);
 #endif
 unsigned sleep(unsigned);
+#ifdef __wasilibc_unmodified_upstream /* WASI has no pause */
 int pause(void);
+#endif
 
 #ifdef __wasilibc_unmodified_upstream /* WASI has no fork/exec */
 pid_t fork(void);
index 7e3f2906794d1bd1cfd02b24f7f05ea2fdfe41eb..d58da7f14eebbade38bad764be46095e840889f2 100644 (file)
@@ -2,7 +2,9 @@
 #include <limits.h>
 #include <errno.h>
 #include <sys/resource.h>
+#ifdef __wasilibc_unmodified_upstream // WASI has no realtime signals
 #include <signal.h>
+#endif
 #include <sys/sysinfo.h>
 #include "syscall.h"
 #include "libc.h"
index b9359f4525f75e3dbe23930e637db9bffe666c0e..1536d7dc0d90e047e4545026262bfe9f17f0e92b 100644 (file)
@@ -10,9 +10,9 @@ static void dummy()
  * as a consequence of linking either __toread.c or __towrite.c. */
 weak_alias(dummy, __funcs_on_exit);
 weak_alias(dummy, __stdio_exit);
+#ifdef __wasilibc_unmodified_upstream // fini
 weak_alias(dummy, _fini);
 
-#ifdef __wasilibc_unmodified_upstream // fini
 extern weak hidden void (*const __fini_array_start)(void), (*const __fini_array_end)(void);
 
 static void libc_exit_fini(void)
@@ -38,7 +38,7 @@ _Noreturn void exit(int code)
 // Split out the cleanup functions so that we can call them without calling
 // _Exit if we don't need to. This allows _start to just return if main
 // returns 0.
-void __prepare_for_exit(void)
+void __wasm_call_dtors(void)
 {
        __funcs_on_exit();
        __stdio_exit();
@@ -46,7 +46,7 @@ void __prepare_for_exit(void)
 
 _Noreturn void exit(int code)
 {
-       __prepare_for_exit();
+       __wasm_call_dtors();
        _Exit(code);
 }
 #endif
index bb5667841a66009715b7c3687ca73cf28b49616b..46de698d999b9962bb38fe48e8167af347bba66f 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "../../include/signal.h"
 
+#ifdef __wasilibc_unmodified_upstream // WASI has no sigaction
 hidden int __sigaction(int, const struct sigaction *, struct sigaction *);
 
 hidden void __block_all_sigs(void *);
@@ -10,5 +11,6 @@ hidden void __block_app_sigs(void *);
 hidden void __restore_sigs(void *);
 
 hidden void __get_handler_set(sigset_t *);
+#endif
 
 #endif
index 3eb420b4c842acaae7feb023179a5525acea237f..537e7a29e1b0e1d2e77856727644968646400b62 100644 (file)
@@ -89,9 +89,11 @@ hidden int __towrite(FILE *);
 hidden void __stdio_exit(void);
 hidden void __stdio_exit_needed(void);
 
+#ifdef __wasilibc_unmodified_upstream // wasm has no "protected" visibility
 #if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303)
 __attribute__((visibility("protected")))
 #endif
+#endif
 int __overflow(FILE *, int), __uflow(FILE *);
 
 hidden int __fseeko(FILE *, off_t, int);
index 8e87972c95d5e1be32aa81f850902ee5027cf69e..4035f191ee24e92ee2175e78e3eaa7315ca71def 100644 (file)
@@ -374,7 +374,7 @@ fn print_union(ret: &mut String, name: &Id, u: &UnionDatatype) {
 }
 
 fn print_handle(ret: &mut String, name: &Id, h: &HandleDatatype) {
-    ret.push_str(&format!("typedef int __wasi_{}_t;", ident_name(name)));
+    ret.push_str(&format!("typedef int __wasi_{}_t;\n\n", ident_name(name)));
 
     ret.push_str(&format!(
         "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n",