mirror of
https://git.proxmox.com/git/wasi-libc
synced 2025-07-27 11:20:43 +00:00
Add support for __main_argc_argv
.
This adds support for the `__main_argc_argv` change, while preserving compatibility with `__original_main`. This is needed by the LTO build because the `__original_main` hack works in LLVM codegen, which is after LTO. The `__main_argc_argv` change is implemented in clang, which makes it properly visible to LTO.
This commit is contained in:
parent
575e1579a4
commit
d9066a87c0
@ -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.
|
||||
|
@ -140,6 +140,8 @@ __log2f_data
|
||||
__log_data
|
||||
__logf_data
|
||||
__lseek
|
||||
__main_argc_argv
|
||||
__main_void
|
||||
__math_divzero
|
||||
__math_divzerof
|
||||
__math_invalid
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <wasi/api.h>
|
||||
#include <wasi/libc.h>
|
||||
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.
|
||||
|
10
libc-bottom-half/sources/__main_argc_argv.c
Normal file
10
libc-bottom-half/sources/__main_argc_argv.c
Normal file
@ -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);
|
||||
}
|
54
libc-bottom-half/sources/__main_void.c
Normal file
54
libc-bottom-half/sources/__main_void.c
Normal file
@ -0,0 +1,54 @@
|
||||
#include <wasi/api.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
// 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);
|
||||
}
|
@ -1,55 +1,10 @@
|
||||
#include <wasi/api.h>
|
||||
#include <wasi/libc.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysexits.h>
|
||||
// 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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user