Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions expected/wasm32-wasi/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ __ofl_lock
__ofl_unlock
__optpos
__optreset
__original_main
__overflow
__p1evll
__pio2_hi
Expand Down
4 changes: 3 additions & 1 deletion libc-bottom-half/cloudlibc/src/include/stdlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,11 @@ typedef __wchar_t wchar_t;
#define MB_CUR_MAX_L MB_CUR_MAX_L

#define alloca(size) __builtin_alloca(size)
#endif

__BEGIN_DECLS
_Noreturn void _Exit(int);
#ifdef __wasilibc_unmodified_upstream
size_t MB_CUR_MAX_L(__locale_t);
long a64l(const char *);
#endif
Expand Down Expand Up @@ -196,8 +198,8 @@ size_t wcstombs_l(char *__restrict, const wchar_t *__restrict, size_t,
__locale_t);
int wctomb(char *, wchar_t);
int wctomb_l(char *, wchar_t, __locale_t);
__END_DECLS
#endif
__END_DECLS

#if _CLOUDLIBC_INLINE_FUNCTIONS
#ifdef __wasilibc_unmodified_upstream
Expand Down
62 changes: 6 additions & 56 deletions libc-bottom-half/crt/crt1.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,10 @@

__wasi_errno_t __wasilibc_populate_environ(void) __attribute__((weak));
extern void __wasm_call_ctors(void);
extern int main(int, char *[]);
extern int __original_main(void);
extern void __prepare_for_exit(void);
void _Exit(int) __attribute__((noreturn));

static __wasi_errno_t populate_args(size_t *argc, char ***argv) {
__wasi_errno_t err;

// Get the sizes of the arrays we'll have to create to copy in the args.
size_t argv_buf_size;
size_t new_argc;
err = __wasi_args_sizes_get(&new_argc, &argv_buf_size);
if (err != __WASI_ESUCCESS) {
return err;
}
if (new_argc == 0) {
return __WASI_ESUCCESS;
}

// Add 1 for the NULL pointer to mark the end, and check for overflow.
size_t num_ptrs = new_argc + 1;
if (num_ptrs == 0) {
return __WASI_ENOMEM;
}

// Allocate memory for storing the argument chars.
char *argv_buf = malloc(argv_buf_size);
if (argv_buf == NULL) {
return __WASI_ENOMEM;
}

// Allocate memory for the array of pointers. This uses `calloc` both to
// handle overflow and to initialize the NULL pointer at the end.
char **argv_ptrs = calloc(num_ptrs, sizeof(char *));
if (argv_ptrs == NULL) {
free(argv_buf);
return __WASI_ENOMEM;
}

// Fill the argument chars, and the argv array with pointers into those chars.
err = __wasi_args_get(argv_ptrs, argv_buf);
if (err == __WASI_ESUCCESS) {
*argc = new_argc;
*argv = argv_ptrs;
} else {
free(argv_buf);
free(argv_ptrs);
}
return err;
}

static __wasi_errno_t populate_libpreopen(void) {
__wasilibc_init_preopen();

Expand Down Expand Up @@ -110,18 +64,14 @@ void _start(void) {
}
}

// Fill in the arguments from WASI syscalls.
size_t argc;
char **argv;
if (populate_args(&argc, &argv) != __WASI_ESUCCESS) {
_Exit(EX_OSERR);
}

// The linker synthesizes this to call constructors.
__wasm_call_ctors();

// Call main with the arguments.
int r = main(argc, argv);
// Call `__original_main` which will either be the application's
// zero-argument `main` function (renamed by the compiler) or a libc
// routine which populates `argv` and `argc` and calls the application's
// two-argument `main`.
int r = __original_main();

// Call atexit functions, destructors, stdio cleanup, etc.
__prepare_for_exit();
Expand Down
53 changes: 53 additions & 0 deletions libc-bottom-half/sources/__original_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <wasi/core.h>
#include <wasi/libc.h>
#include <stdlib.h>
#include <sysexits.h>

// The user's `main` function, expecting arguments.
int main(int argc, char *argv[]);

// If the user's `main` function expects arguments, the compiler won't emit
// an `__original_main` function so this version will get linked in, which
// initializes the argument data and calls `main`.
int __original_main(void) {
__wasi_errno_t err;

// Get the sizes of the arrays we'll have to create to copy in the args.
size_t argv_buf_size;
size_t argc;
err = __wasi_args_sizes_get(&argc, &argv_buf_size);
if (err != __WASI_ESUCCESS) {
_Exit(EX_OSERR);
}

// Add 1 for the NULL pointer to mark the end, and check for overflow.
size_t num_ptrs = argc + 1;
if (num_ptrs == 0) {
_Exit(EX_SOFTWARE);
}

// Allocate memory for storing the argument chars.
char *argv_buf = malloc(argv_buf_size);
if (argv_buf == NULL) {
_Exit(EX_SOFTWARE);
}

// Allocate memory for the array of pointers. This uses `calloc` both to
// handle overflow and to initialize the NULL pointer at the end.
char **argv = calloc(num_ptrs, sizeof(char *));
if (argv == NULL) {
free(argv_buf);
_Exit(EX_SOFTWARE);
}

// Fill the argument chars, and the argv array with pointers into those chars.
err = __wasi_args_get(argv, argv_buf);
if (err != __WASI_ESUCCESS) {
free(argv_buf);
free(argv);
_Exit(EX_OSERR);
}

// Call main with the arguments!
return main(argc, argv);
}