Skip to content

Commit 410c660

Browse files
authoredNov 25, 2019
Use constructor functions for optional init routines. (#142)
* 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.
1 parent fe13053 commit 410c660

File tree

5 files changed

+38
-62
lines changed

5 files changed

+38
-62
lines changed
 

‎expected/wasm32-wasi/defined-symbols.txt

-2
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,6 @@ __wasilibc_fd_renumber
253253
__wasilibc_find_relpath
254254
__wasilibc_open_nomode
255255
__wasilibc_openat_nomode
256-
__wasilibc_populate_environ
257-
__wasilibc_populate_libpreopen
258256
__wasilibc_register_preopened_fd
259257
__wasilibc_rmdirat
260258
__wasilibc_tell

‎libc-bottom-half/crt/crt1.c

+3-23
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,10 @@
1-
#include <stdlib.h>
2-
#include <sysexits.h>
31
#include <wasi/api.h>
42
#include <wasi/libc.h>
5-
#include <wasi/libc-internal.h>
6-
7-
__wasi_errno_t __wasilibc_populate_environ(void) __attribute__((weak));
83
extern void __wasm_call_ctors(void);
94
extern int __original_main(void);
105
extern void __prepare_for_exit(void);
11-
void _Exit(int) __attribute__((noreturn));
12-
__wasi_errno_t __wasilibc_populate_libpreopen(void) __attribute__((weak));
136

147
void _start(void) {
15-
// Record the preopened resources, if needed.
16-
if (&__wasilibc_populate_libpreopen != NULL &&
17-
__wasilibc_populate_libpreopen() != __WASI_ERRNO_SUCCESS)
18-
{
19-
_Exit(EX_OSERR);
20-
}
21-
22-
// Fill in the environment from WASI syscalls, if needed.
23-
if (&__wasilibc_populate_environ != NULL &&
24-
__wasilibc_populate_environ() != __WASI_ERRNO_SUCCESS)
25-
{
26-
_Exit(EX_OSERR);
27-
}
28-
298
// The linker synthesizes this to call constructors.
309
__wasm_call_ctors();
3110

@@ -38,8 +17,9 @@ void _start(void) {
3817
// Call atexit functions, destructors, stdio cleanup, etc.
3918
__prepare_for_exit();
4019

41-
// If main exited successfully, just return, otherwise call _Exit.
20+
// If main exited successfully, just return, otherwise call
21+
// `__wasi_proc_exit`.
4222
if (r != 0) {
43-
_Exit(r);
23+
__wasi_proc_exit(r);
4424
}
4525
}

‎libc-bottom-half/headers/private/wasi/libc-internal.h

-17
This file was deleted.

‎libc-bottom-half/libpreopen/libpreopen.c

+14-6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include <errno.h>
5555
#include <dirent.h>
5656
#include <assert.h>
57+
#include <sysexits.h>
5758
#include <wasi/libc.h>
5859
#include <wasi/libc-find-relpath.h>
5960

@@ -522,7 +523,10 @@ __wasilibc_find_relpath(
522523

523524
/// This is referenced by weak reference from crt1.c and lives in the same source
524525
/// file as `__wasilibc_find_relpath` so that it's linked in when it's needed.
525-
__wasi_errno_t
526+
// Concerning the 51 -- see the comment by the constructor priority in
527+
// libc-bottom-half/sources/__environ.c.
528+
__attribute__((constructor(51)))
529+
static void
526530
__wasilibc_populate_libpreopen(void)
527531
{
528532
// Skip stdin, stdout, and stderr, and count up until we reach an invalid
@@ -533,24 +537,24 @@ __wasilibc_populate_libpreopen(void)
533537
if (ret == __WASI_ERRNO_BADF)
534538
break;
535539
if (ret != __WASI_ERRNO_SUCCESS)
536-
return ret;
540+
goto oserr;
537541
switch (prestat.pr_type) {
538542
case __WASI_PREOPENTYPE_DIR: {
539543
char *path = malloc(prestat.u.dir.pr_name_len + 1);
540544
if (path == NULL)
541-
return __WASI_ERRNO_NOMEM;
545+
goto software;
542546

543547
// TODO: Remove the cast on `path` once the witx is updated with char8 support.
544548
ret = __wasi_fd_prestat_dir_name(fd, (uint8_t *)path, prestat.u.dir.pr_name_len);
545549
if (ret != __WASI_ERRNO_SUCCESS) {
546550
free(path);
547-
return ret;
551+
goto oserr;
548552
}
549553
path[prestat.u.dir.pr_name_len] = '\0';
550554

551555
if (internal_register_preopened_fd(fd, path) != 0) {
552556
free(path);
553-
return __WASI_ERRNO_NOMEM;
557+
goto software;
554558
}
555559

556560
break;
@@ -560,5 +564,9 @@ __wasilibc_populate_libpreopen(void)
560564
}
561565
}
562566

563-
return __WASI_ERRNO_SUCCESS;
567+
return;
568+
oserr:
569+
_Exit(EX_OSERR);
570+
software:
571+
_Exit(EX_SOFTWARE);
564572
}

‎libc-bottom-half/sources/__environ.c

+21-14
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,66 @@
11
#include <unistd.h>
22
#include <stdlib.h>
3+
#include <sysexits.h>
34
#include <wasi/api.h>
45
#include <wasi/libc.h>
5-
#include <wasi/libc-internal.h>
66

77
static char *empty_environ[1] = { NULL };
88
char **__environ = empty_environ;
99
extern __typeof(__environ) _environ __attribute__((weak, alias("__environ")));
1010
extern __typeof(__environ) environ __attribute__((weak, alias("__environ")));
1111

12-
// This function is referenced by a weak symbol in crt1.c, and we define
13-
// it here in the same source file as __environ, so that this function is
14-
// linked in iff environment variable support is used.
15-
__wasi_errno_t __wasilibc_populate_environ(void) {
12+
// We define this function here in the same source file as __environ, so that
13+
// this function is called in iff environment variable support is used.
14+
// Concerning the 50 -- levels up to 100 are reserved for the implementation,
15+
// so we an arbitrary number in the middle of the range to allow other
16+
// reserved things to go before or after.
17+
__attribute__((constructor(50)))
18+
static void __wasilibc_populate_environ(void) {
1619
__wasi_errno_t err;
1720

1821
// Get the sizes of the arrays we'll have to create to copy in the environment.
1922
size_t environ_count;
2023
size_t environ_buf_size;
2124
err = __wasi_environ_sizes_get(&environ_count, &environ_buf_size);
2225
if (err != __WASI_ERRNO_SUCCESS) {
23-
return err;
26+
goto oserr;
2427
}
2528
if (environ_count == 0) {
26-
return __WASI_ERRNO_SUCCESS;
29+
return;
2730
}
2831

2932
// Add 1 for the NULL pointer to mark the end, and check for overflow.
3033
size_t num_ptrs = environ_count + 1;
3134
if (num_ptrs == 0) {
32-
return __WASI_ERRNO_NOMEM;
35+
goto software;
3336
}
3437

3538
// Allocate memory for storing the environment chars.
3639
char *environ_buf = malloc(environ_buf_size);
3740
if (environ_buf == NULL) {
38-
return __WASI_ERRNO_NOMEM;
41+
goto software;
3942
}
4043

4144
// Allocate memory for the array of pointers. This uses `calloc` both to
4245
// handle overflow and to initialize the NULL pointer at the end.
4346
char **environ_ptrs = calloc(num_ptrs, sizeof(char *));
4447
if (environ_ptrs == NULL) {
4548
free(environ_buf);
46-
return __WASI_ERRNO_NOMEM;
49+
goto software;
4750
}
4851

4952
// Fill the environment chars, and the __environ array with pointers into those chars.
5053
// TODO: Remove the casts on `environ_ptrs` and `environ_buf` once the witx is updated with char8 support.
5154
err = __wasi_environ_get((uint8_t **)environ_ptrs, (uint8_t *)environ_buf);
52-
if (err == __WASI_ERRNO_SUCCESS) {
53-
__environ = environ_ptrs;
54-
} else {
55+
if (err != __WASI_ERRNO_SUCCESS) {
5556
free(environ_buf);
5657
free(environ_ptrs);
58+
goto oserr;
5759
}
58-
return err;
60+
61+
__environ = environ_ptrs;
62+
oserr:
63+
_Exit(EX_OSERR);
64+
software:
65+
_Exit(EX_SOFTWARE);
5966
}

0 commit comments

Comments
 (0)
Please sign in to comment.