* Use constructor functions for optional init routines.
Instead of using weak symbols, use constructor function attributes for the
environment and preopen initialization routines. This is simpler, uses
less code, and is more LTO-friendly.
* Change the constructor priorities to start at 50.
We don't currently have specific plans for other levels in the reserved
range (0-100), so leave room for both lower and higher priorities.
__wasilibc_find_relpath
__wasilibc_open_nomode
__wasilibc_openat_nomode
-__wasilibc_populate_environ
-__wasilibc_populate_libpreopen
__wasilibc_register_preopened_fd
__wasilibc_rmdirat
__wasilibc_tell
-#include <stdlib.h>
-#include <sysexits.h>
#include <wasi/api.h>
#include <wasi/libc.h>
-#include <wasi/libc-internal.h>
-
-__wasi_errno_t __wasilibc_populate_environ(void) __attribute__((weak));
extern void __wasm_call_ctors(void);
extern int __original_main(void);
extern void __prepare_for_exit(void);
-void _Exit(int) __attribute__((noreturn));
-__wasi_errno_t __wasilibc_populate_libpreopen(void) __attribute__((weak));
void _start(void) {
- // Record the preopened resources, if needed.
- if (&__wasilibc_populate_libpreopen != NULL &&
- __wasilibc_populate_libpreopen() != __WASI_ERRNO_SUCCESS)
- {
- _Exit(EX_OSERR);
- }
-
- // Fill in the environment from WASI syscalls, if needed.
- if (&__wasilibc_populate_environ != NULL &&
- __wasilibc_populate_environ() != __WASI_ERRNO_SUCCESS)
- {
- _Exit(EX_OSERR);
- }
-
// The linker synthesizes this to call constructors.
__wasm_call_ctors();
// Call atexit functions, destructors, stdio cleanup, etc.
__prepare_for_exit();
- // If main exited successfully, just return, otherwise call _Exit.
+ // If main exited successfully, just return, otherwise call
+ // `__wasi_proc_exit`.
if (r != 0) {
- _Exit(r);
+ __wasi_proc_exit(r);
}
}
+++ /dev/null
-#ifndef __wasi_libc_internal_h
-#define __wasi_libc_internal_h
-
-#include <wasi/api.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void __wasilibc_init_preopen(void);
-__wasi_errno_t __wasilibc_populate_environ(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
#include <errno.h>
#include <dirent.h>
#include <assert.h>
+#include <sysexits.h>
#include <wasi/libc.h>
#include <wasi/libc-find-relpath.h>
/// 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
+// Concerning the 51 -- see the comment by the constructor priority in
+// libc-bottom-half/sources/__environ.c.
+__attribute__((constructor(51)))
+static void
__wasilibc_populate_libpreopen(void)
{
// Skip stdin, stdout, and stderr, and count up until we reach an invalid
if (ret == __WASI_ERRNO_BADF)
break;
if (ret != __WASI_ERRNO_SUCCESS)
- return ret;
+ goto oserr;
switch (prestat.pr_type) {
case __WASI_PREOPENTYPE_DIR: {
char *path = malloc(prestat.u.dir.pr_name_len + 1);
if (path == NULL)
- return __WASI_ERRNO_NOMEM;
+ 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) {
free(path);
- return ret;
+ goto oserr;
}
path[prestat.u.dir.pr_name_len] = '\0';
if (internal_register_preopened_fd(fd, path) != 0) {
free(path);
- return __WASI_ERRNO_NOMEM;
+ goto software;
}
break;
}
}
- return __WASI_ERRNO_SUCCESS;
+ return;
+oserr:
+ _Exit(EX_OSERR);
+software:
+ _Exit(EX_SOFTWARE);
}
#include <unistd.h>
#include <stdlib.h>
+#include <sysexits.h>
#include <wasi/api.h>
#include <wasi/libc.h>
-#include <wasi/libc-internal.h>
static char *empty_environ[1] = { NULL };
char **__environ = empty_environ;
extern __typeof(__environ) _environ __attribute__((weak, alias("__environ")));
extern __typeof(__environ) environ __attribute__((weak, alias("__environ")));
-// This function is referenced by a weak symbol in crt1.c, and we define
-// it here in the same source file as __environ, so that this function is
-// linked in iff environment variable support is used.
-__wasi_errno_t __wasilibc_populate_environ(void) {
+// We define this function here in the same source file as __environ, so that
+// this function is called in iff environment variable support is used.
+// Concerning the 50 -- levels up to 100 are reserved for the implementation,
+// so we an arbitrary number in the middle of the range to allow other
+// reserved things to go before or after.
+__attribute__((constructor(50)))
+static void __wasilibc_populate_environ(void) {
__wasi_errno_t err;
// Get the sizes of the arrays we'll have to create to copy in the environment.
size_t environ_buf_size;
err = __wasi_environ_sizes_get(&environ_count, &environ_buf_size);
if (err != __WASI_ERRNO_SUCCESS) {
- return err;
+ goto oserr;
}
if (environ_count == 0) {
- return __WASI_ERRNO_SUCCESS;
+ return;
}
// Add 1 for the NULL pointer to mark the end, and check for overflow.
size_t num_ptrs = environ_count + 1;
if (num_ptrs == 0) {
- return __WASI_ERRNO_NOMEM;
+ goto software;
}
// Allocate memory for storing the environment chars.
char *environ_buf = malloc(environ_buf_size);
if (environ_buf == NULL) {
- return __WASI_ERRNO_NOMEM;
+ goto software;
}
// Allocate memory for the array of pointers. This uses `calloc` both to
char **environ_ptrs = calloc(num_ptrs, sizeof(char *));
if (environ_ptrs == NULL) {
free(environ_buf);
- return __WASI_ERRNO_NOMEM;
+ goto software;
}
// Fill the environment chars, and the __environ array with pointers into those chars.
// TODO: Remove the casts on `environ_ptrs` and `environ_buf` once the witx is updated with char8 support.
err = __wasi_environ_get((uint8_t **)environ_ptrs, (uint8_t *)environ_buf);
- if (err == __WASI_ERRNO_SUCCESS) {
- __environ = environ_ptrs;
- } else {
+ if (err != __WASI_ERRNO_SUCCESS) {
free(environ_buf);
free(environ_ptrs);
+ goto oserr;
}
- return err;
+
+ __environ = environ_ptrs;
+oserr:
+ _Exit(EX_OSERR);
+software:
+ _Exit(EX_SOFTWARE);
}