]> git.proxmox.com Git - wasi-libc.git/commitdiff
Add support for `__main_argc_argv`.
authorDan Gohman <sunfish@mozilla.com>
Fri, 20 Dec 2019 23:14:02 +0000 (15:14 -0800)
committerDan Gohman <sunfish@mozilla.com>
Thu, 27 Feb 2020 21:09:38 +0000 (13:09 -0800)
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.

basics/crt/crt1.c
expected/wasm32-wasi/defined-symbols.txt
libc-bottom-half/crt/crt1.c
libc-bottom-half/sources/__main_argc_argv.c [new file with mode: 0644]
libc-bottom-half/sources/__main_void.c [new file with mode: 0644]
libc-bottom-half/sources/__original_main.c

index a0f5a7349be7d72bdfd0690db6e01e1a646f6bc0..744baab85078aab5749eeba769817b439333c24b 100644 (file)
@@ -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.
index a5105081bba8f64e8cbf3ae6e4a0c965c0ec99fc..761f98031b023f9f4c544bf240581085d0e2f0b4 100644 (file)
@@ -140,6 +140,8 @@ __log2f_data
 __log_data
 __logf_data
 __lseek
+__main_argc_argv
+__main_void
 __math_divzero
 __math_divzerof
 __math_invalid
index 1b9cadb46999f2a0e1590f6bdcd6b29547855932..f70c24a9fd3264294848e19622e3563cb87b66e6 100644 (file)
@@ -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.
diff --git a/libc-bottom-half/sources/__main_argc_argv.c b/libc-bottom-half/sources/__main_argc_argv.c
new file mode 100644 (file)
index 0000000..decaa2d
--- /dev/null
@@ -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 (file)
index 0000000..6be5c1e
--- /dev/null
@@ -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);
+}
index b0982d50bef9dbe524e0eae7e70df91df09293a3..73564d46f0b576523ed214489895ec19df2c1b23 100644 (file)
@@ -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();
 }