diff --git a/expected/wasm32-wasi/defined-symbols.txt b/expected/wasm32-wasi/defined-symbols.txt index d50f745b8..fda1ec8c4 100644 --- a/expected/wasm32-wasi/defined-symbols.txt +++ b/expected/wasm32-wasi/defined-symbols.txt @@ -254,6 +254,7 @@ __wasilibc_find_relpath __wasilibc_open_nomode __wasilibc_openat_nomode __wasilibc_populate_environ +__wasilibc_populate_libpreopen __wasilibc_register_preopened_fd __wasilibc_rmdirat __wasilibc_tell diff --git a/libc-bottom-half/crt/crt1.c b/libc-bottom-half/crt/crt1.c index ddf352f51..59ca2bf52 100644 --- a/libc-bottom-half/crt/crt1.c +++ b/libc-bottom-half/crt/crt1.c @@ -9,57 +9,21 @@ extern void __wasm_call_ctors(void); extern int __original_main(void); extern void __prepare_for_exit(void); void _Exit(int) __attribute__((noreturn)); - -static __wasi_errno_t 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_EBADF) - break; - if (ret != __WASI_ESUCCESS) - return ret; - switch (prestat.pr_type) { - case __WASI_PREOPENTYPE_DIR: { - char *path = malloc(prestat.u.dir.pr_name_len + 1); - if (path == NULL) - return __WASI_ENOMEM; - - ret = __wasi_fd_prestat_dir_name(fd, path, prestat.u.dir.pr_name_len); - if (ret != __WASI_ESUCCESS) { - free(path); - return ret; - } - path[prestat.u.dir.pr_name_len] = '\0'; - - if (__wasilibc_register_preopened_fd(fd, path) != 0) { - free(path); - return __WASI_ENOMEM; - } - - free(path); - break; - } - default: - break; - } - } - - return __WASI_ESUCCESS; -} +__wasi_errno_t __wasilibc_populate_libpreopen(void) __attribute__((weak)); void _start(void) { - // Record the preopened resources. - if (populate_libpreopen() != __WASI_ESUCCESS) { + // Record the preopened resources, if needed. + if (&__wasilibc_populate_libpreopen != NULL && + __wasilibc_populate_libpreopen() != __WASI_ESUCCESS) + { _Exit(EX_OSERR); } // Fill in the environment from WASI syscalls, if needed. - if (&__wasilibc_populate_environ != NULL) { - if (__wasilibc_populate_environ() != __WASI_ESUCCESS) { - _Exit(EX_OSERR); - } + if (&__wasilibc_populate_environ != NULL && + __wasilibc_populate_environ() != __WASI_ESUCCESS) + { + _Exit(EX_OSERR); } // The linker synthesizes this to call constructors. diff --git a/libc-bottom-half/libpreopen/libpreopen.c b/libc-bottom-half/libpreopen/libpreopen.c index 8a17a4268..5cded23e6 100644 --- a/libc-bottom-half/libpreopen/libpreopen.c +++ b/libc-bottom-half/libpreopen/libpreopen.c @@ -555,3 +555,46 @@ __wasilibc_find_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. +__wasi_errno_t +__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_EBADF) + break; + if (ret != __WASI_ESUCCESS) + return ret; + switch (prestat.pr_type) { + case __WASI_PREOPENTYPE_DIR: { + char *path = malloc(prestat.u.dir.pr_name_len + 1); + if (path == NULL) + return __WASI_ENOMEM; + + ret = __wasi_fd_prestat_dir_name(fd, path, prestat.u.dir.pr_name_len); + if (ret != __WASI_ESUCCESS) { + free(path); + return ret; + } + path[prestat.u.dir.pr_name_len] = '\0'; + + if (__wasilibc_register_preopened_fd(fd, path) != 0) { + free(path); + return __WASI_ENOMEM; + } + + free(path); + break; + } + default: + break; + } + } + + return __WASI_ESUCCESS; +}