diff --git a/basics/crt/crt1.c b/basics/crt/crt1.c index a0f5a73..744baab 100644 --- a/basics/crt/crt1.c +++ b/basics/crt/crt1.c @@ -7,10 +7,9 @@ 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 `main` function (renamed by the compiler) or a libc - // routine which populates `argv` and `argc` and calls the application's - // two-argument `main`. + // 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. diff --git a/expected/wasm32-wasi/defined-symbols.txt b/expected/wasm32-wasi/defined-symbols.txt index a510508..761f980 100644 --- a/expected/wasm32-wasi/defined-symbols.txt +++ b/expected/wasm32-wasi/defined-symbols.txt @@ -140,6 +140,8 @@ __log2f_data __log_data __logf_data __lseek +__main_argc_argv +__main_void __math_divzero __math_divzerof __math_invalid diff --git a/libc-bottom-half/crt/crt1.c b/libc-bottom-half/crt/crt1.c index 1b9cadb..f70c24a 100644 --- a/libc-bottom-half/crt/crt1.c +++ b/libc-bottom-half/crt/crt1.c @@ -1,5 +1,4 @@ #include -#include extern void __wasm_call_ctors(void); extern int __original_main(void); extern void __prepare_for_exit(void); @@ -8,10 +7,9 @@ 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 `main` function (renamed by the compiler) or a libc - // routine which populates `argv` and `argc` and calls the application's - // two-argument `main`. + // 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. diff --git a/libc-bottom-half/sources/__main_argc_argv.c b/libc-bottom-half/sources/__main_argc_argv.c new file mode 100644 index 0000000..decaa2d --- /dev/null +++ b/libc-bottom-half/sources/__main_argc_argv.c @@ -0,0 +1,10 @@ +// New compilers define `__main_argc_argv`. If that doesn't exist, we +// may get called here. Old compilers define `main` expecting an +// argv/argc, so call that. +// TODO: Remove this layer when we no longer have to support old compilers. +int __wasilibc_main(int argc, char *argv[]) asm("main"); + +__attribute__((weak, nodebug)) +int __main_argc_argv(int argc, char *argv[]) { + return __wasilibc_main(argc, argv); +} diff --git a/libc-bottom-half/sources/__main_void.c b/libc-bottom-half/sources/__main_void.c new file mode 100644 index 0000000..6be5c1e --- /dev/null +++ b/libc-bottom-half/sources/__main_void.c @@ -0,0 +1,54 @@ +#include +#include +#include + +// The user's `main` function, expecting arguments. +int __main_argc_argv(int argc, char *argv[]); + +// If the user's `main` function expects arguments, the compiler will rename +// it to `__main_argc_argv`, and this version will get linked in, which +// initializes the argument data and calls `__main_argc_argv`. +__attribute__((weak, nodebug)) +int __main_void(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_ERRNO_SUCCESS) { + _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. + // TODO: Remove the casts on `argv_ptrs` and `argv_buf` once the witx is updated with char8 support. + err = __wasi_args_get((uint8_t **)argv, (uint8_t *)argv_buf); + if (err != __WASI_ERRNO_SUCCESS) { + free(argv_buf); + free(argv); + _Exit(EX_OSERR); + } + + // Call `__main_argc_argv` with the arguments! + return __main_argc_argv(argc, argv); +} diff --git a/libc-bottom-half/sources/__original_main.c b/libc-bottom-half/sources/__original_main.c index b0982d5..73564d4 100644 --- a/libc-bottom-half/sources/__original_main.c +++ b/libc-bottom-half/sources/__original_main.c @@ -1,55 +1,10 @@ -#include -#include -#include -#include +// Old compilers define `__original_main`. If that doesn't exist, we +// get called here. New compilers define `__main_void`. If that doesn't +// exist, we'll try something else. +// TODO: Remove this layer when we no longer have to support old compilers. +int __main_void(void); -// 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`. __attribute__((weak)) 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_ERRNO_SUCCESS) { - _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. - // TODO: Remove the casts on `argv_ptrs` and `argv_buf` once the witx is updated with char8 support. - err = __wasi_args_get((uint8_t **)argv, (uint8_t *)argv_buf); - if (err != __WASI_ERRNO_SUCCESS) { - free(argv_buf); - free(argv); - _Exit(EX_OSERR); - } - - // Call main with the arguments! - return main(argc, argv); + return __main_void(); }