diff --git a/src/jsifier.mjs b/src/jsifier.mjs index 50f8a0abb3c6d..15270ce00511b 100644 --- a/src/jsifier.mjs +++ b/src/jsifier.mjs @@ -124,6 +124,9 @@ function getTransitiveDeps(symbol, debug) { directDeps = directDeps.filter((d) => typeof d === 'string'); for (const dep of directDeps) { const resolved = resolveAlias(dep); + if (VERBOSE && !transitiveDeps.has(dep)) { + printErr(`adding dependency ${symbol} -> ${dep}`); + } transitiveDeps.add(resolved); toVisit.push(resolved); } diff --git a/src/library.js b/src/library.js index 338a7165258fb..15d666db5dc44 100644 --- a/src/library.js +++ b/src/library.js @@ -1431,129 +1431,15 @@ addToLibrary({ 'EOWNERDEAD': {{{ cDefs.EOWNERDEAD }}}, 'ESTRPIPE': {{{ cDefs.ESTRPIPE }}}, }`, - $ERRNO_MESSAGES: { - 0: 'Success', - {{{ cDefs.EPERM }}}: 'Not super-user', - {{{ cDefs.ENOENT }}}: 'No such file or directory', - {{{ cDefs.ESRCH }}}: 'No such process', - {{{ cDefs.EINTR }}}: 'Interrupted system call', - {{{ cDefs.EIO }}}: 'I/O error', - {{{ cDefs.ENXIO }}}: 'No such device or address', - {{{ cDefs.E2BIG }}}: 'Arg list too long', - {{{ cDefs.ENOEXEC }}}: 'Exec format error', - {{{ cDefs.EBADF }}}: 'Bad file number', - {{{ cDefs.ECHILD }}}: 'No children', - {{{ cDefs.EWOULDBLOCK }}}: 'No more processes', - {{{ cDefs.ENOMEM }}}: 'Not enough core', - {{{ cDefs.EACCES }}}: 'Permission denied', - {{{ cDefs.EFAULT }}}: 'Bad address', - {{{ cDefs.ENOTBLK }}}: 'Block device required', - {{{ cDefs.EBUSY }}}: 'Mount device busy', - {{{ cDefs.EEXIST }}}: 'File exists', - {{{ cDefs.EXDEV }}}: 'Cross-device link', - {{{ cDefs.ENODEV }}}: 'No such device', - {{{ cDefs.ENOTDIR }}}: 'Not a directory', - {{{ cDefs.EISDIR }}}: 'Is a directory', - {{{ cDefs.EINVAL }}}: 'Invalid argument', - {{{ cDefs.ENFILE }}}: 'Too many open files in system', - {{{ cDefs.EMFILE }}}: 'Too many open files', - {{{ cDefs.ENOTTY }}}: 'Not a typewriter', - {{{ cDefs.ETXTBSY }}}: 'Text file busy', - {{{ cDefs.EFBIG }}}: 'File too large', - {{{ cDefs.ENOSPC }}}: 'No space left on device', - {{{ cDefs.ESPIPE }}}: 'Illegal seek', - {{{ cDefs.EROFS }}}: 'Read only file system', - {{{ cDefs.EMLINK }}}: 'Too many links', - {{{ cDefs.EPIPE }}}: 'Broken pipe', - {{{ cDefs.EDOM }}}: 'Math arg out of domain of func', - {{{ cDefs.ERANGE }}}: 'Math result not representable', - {{{ cDefs.ENOMSG }}}: 'No message of desired type', - {{{ cDefs.EIDRM }}}: 'Identifier removed', - {{{ cDefs.ECHRNG }}}: 'Channel number out of range', - {{{ cDefs.EL2NSYNC }}}: 'Level 2 not synchronized', - {{{ cDefs.EL3HLT }}}: 'Level 3 halted', - {{{ cDefs.EL3RST }}}: 'Level 3 reset', - {{{ cDefs.ELNRNG }}}: 'Link number out of range', - {{{ cDefs.EUNATCH }}}: 'Protocol driver not attached', - {{{ cDefs.ENOCSI }}}: 'No CSI structure available', - {{{ cDefs.EL2HLT }}}: 'Level 2 halted', - {{{ cDefs.EDEADLK }}}: 'Deadlock condition', - {{{ cDefs.ENOLCK }}}: 'No record locks available', - {{{ cDefs.EBADE }}}: 'Invalid exchange', - {{{ cDefs.EBADR }}}: 'Invalid request descriptor', - {{{ cDefs.EXFULL }}}: 'Exchange full', - {{{ cDefs.ENOANO }}}: 'No anode', - {{{ cDefs.EBADRQC }}}: 'Invalid request code', - {{{ cDefs.EBADSLT }}}: 'Invalid slot', - {{{ cDefs.EDEADLOCK }}}: 'File locking deadlock error', - {{{ cDefs.EBFONT }}}: 'Bad font file fmt', - {{{ cDefs.ENOSTR }}}: 'Device not a stream', - {{{ cDefs.ENODATA }}}: 'No data (for no delay io)', - {{{ cDefs.ETIME }}}: 'Timer expired', - {{{ cDefs.ENOSR }}}: 'Out of streams resources', - {{{ cDefs.ENONET }}}: 'Machine is not on the network', - {{{ cDefs.ENOPKG }}}: 'Package not installed', - {{{ cDefs.EREMOTE }}}: 'The object is remote', - {{{ cDefs.ENOLINK }}}: 'The link has been severed', - {{{ cDefs.EADV }}}: 'Advertise error', - {{{ cDefs.ESRMNT }}}: 'Srmount error', - {{{ cDefs.ECOMM }}}: 'Communication error on send', - {{{ cDefs.EPROTO }}}: 'Protocol error', - {{{ cDefs.EMULTIHOP }}}: 'Multihop attempted', - {{{ cDefs.EDOTDOT }}}: 'Cross mount point (not really error)', - {{{ cDefs.EBADMSG }}}: 'Trying to read unreadable message', - {{{ cDefs.ENOTUNIQ }}}: 'Given log. name not unique', - {{{ cDefs.EBADFD }}}: 'f.d. invalid for this operation', - {{{ cDefs.EREMCHG }}}: 'Remote address changed', - {{{ cDefs.ELIBACC }}}: 'Can access a needed shared lib', - {{{ cDefs.ELIBBAD }}}: 'Accessing a corrupted shared lib', - {{{ cDefs.ELIBSCN }}}: '.lib section in a.out corrupted', - {{{ cDefs.ELIBMAX }}}: 'Attempting to link in too many libs', - {{{ cDefs.ELIBEXEC }}}: 'Attempting to exec a shared library', - {{{ cDefs.ENOSYS }}}: 'Function not implemented', - {{{ cDefs.ENOTEMPTY }}}: 'Directory not empty', - {{{ cDefs.ENAMETOOLONG }}}: 'File or path name too long', - {{{ cDefs.ELOOP }}}: 'Too many symbolic links', - {{{ cDefs.EOPNOTSUPP }}}: 'Operation not supported on transport endpoint', - {{{ cDefs.EPFNOSUPPORT }}}: 'Protocol family not supported', - {{{ cDefs.ECONNRESET }}}: 'Connection reset by peer', - {{{ cDefs.ENOBUFS }}}: 'No buffer space available', - {{{ cDefs.EAFNOSUPPORT }}}: 'Address family not supported by protocol family', - {{{ cDefs.EPROTOTYPE }}}: 'Protocol wrong type for socket', - {{{ cDefs.ENOTSOCK }}}: 'Socket operation on non-socket', - {{{ cDefs.ENOPROTOOPT }}}: 'Protocol not available', - {{{ cDefs.ESHUTDOWN }}}: 'Can\'t send after socket shutdown', - {{{ cDefs.ECONNREFUSED }}}: 'Connection refused', - {{{ cDefs.EADDRINUSE }}}: 'Address already in use', - {{{ cDefs.ECONNABORTED }}}: 'Connection aborted', - {{{ cDefs.ENETUNREACH }}}: 'Network is unreachable', - {{{ cDefs.ENETDOWN }}}: 'Network interface is not configured', - {{{ cDefs.ETIMEDOUT }}}: 'Connection timed out', - {{{ cDefs.EHOSTDOWN }}}: 'Host is down', - {{{ cDefs.EHOSTUNREACH }}}: 'Host is unreachable', - {{{ cDefs.EINPROGRESS }}}: 'Connection already in progress', - {{{ cDefs.EALREADY }}}: 'Socket already connected', - {{{ cDefs.EDESTADDRREQ }}}: 'Destination address required', - {{{ cDefs.EMSGSIZE }}}: 'Message too long', - {{{ cDefs.EPROTONOSUPPORT }}}: 'Unknown protocol', - {{{ cDefs.ESOCKTNOSUPPORT }}}: 'Socket type not supported', - {{{ cDefs.EADDRNOTAVAIL }}}: 'Address not available', - {{{ cDefs.ENETRESET }}}: 'Connection reset by network', - {{{ cDefs.EISCONN }}}: 'Socket is already connected', - {{{ cDefs.ENOTCONN }}}: 'Socket is not connected', - {{{ cDefs.ETOOMANYREFS }}}: 'Too many references', - {{{ cDefs.EUSERS }}}: 'Too many users', - {{{ cDefs.EDQUOT }}}: 'Quota exceeded', - {{{ cDefs.ESTALE }}}: 'Stale file handle', - {{{ cDefs.ENOTSUP }}}: 'Not supported', - {{{ cDefs.ENOMEDIUM }}}: 'No medium (in tape drive)', - {{{ cDefs.EILSEQ }}}: 'Illegal byte sequence', - {{{ cDefs.EOVERFLOW }}}: 'Value too large for defined data type', - {{{ cDefs.ECANCELED }}}: 'Operation canceled', - {{{ cDefs.ENOTRECOVERABLE }}}: 'State not recoverable', - {{{ cDefs.EOWNERDEAD }}}: 'Previous owner died', - {{{ cDefs.ESTRPIPE }}}: 'Streams pipe error', + +#if PURE_WASI + $strError: (errno) => errno + '', +#else + $strError__deps: ['strerror', '$UTF8ToString'], + $strError: (errno) => { + return UTF8ToString(_strerror(errno)); }, +#endif #if PROXY_POSIX_SOCKETS == 0 // ========================================================================== @@ -3386,7 +3272,7 @@ function wrapSyscallFunction(x, library, isWasi) { pre += "var ret = (() => {"; post += "})();\n"; post += "if (ret && ret < 0 && canWarn) {\n"; - post += " dbg(`error: syscall may have failed with ${-ret} (${ERRNO_MESSAGES[-ret]})`);\n"; + post += " dbg(`error: syscall may have failed with ${-ret} (${strError(-ret)})`);\n"; post += "}\n"; post += "dbg(`syscall return: ${ret}`);\n"; post += "return ret;\n"; @@ -3400,7 +3286,7 @@ function wrapSyscallFunction(x, library, isWasi) { " if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;\n"; #if SYSCALL_DEBUG handler += - " dbg(`error: syscall failed with ${e.errno} (${ERRNO_MESSAGES[e.errno]})`);\n" + + " dbg(`error: syscall failed with ${e.errno} (${strError(e.errno)})`);\n" + " canWarn = false;\n"; #endif // Musl syscalls are negated. diff --git a/src/library_fs.js b/src/library_fs.js index 0eab3fcb8006b..d6744ace3c348 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -28,7 +28,7 @@ addToLibrary({ '$PROXYFS', #endif #if ASSERTIONS - '$ERRNO_MESSAGES', '$ERRNO_CODES', + '$strError', '$ERRNO_CODES', #endif ], $FS__postset: function() { @@ -80,7 +80,7 @@ FS.staticInit();` + // we'll use the reliable test `err.name == "ErrnoError"` instead constructor(errno) { #if ASSERTIONS - super(ERRNO_MESSAGES[errno]); + super(runtimeInitialized ? strError(errno) : ''); #endif // TODO(sbc): Use the inline member declaration syntax once we // support it in acorn and closure. diff --git a/src/library_syscall.js b/src/library_syscall.js index 897d48c5a6f34..0f963a81f9f70 100644 --- a/src/library_syscall.js +++ b/src/library_syscall.js @@ -11,7 +11,7 @@ var SyscallsLibrary = { '$FS', #endif #if SYSCALL_DEBUG - '$ERRNO_MESSAGES' + '$strError', #endif ], $SYSCALLS: { diff --git a/system/lib/libc/musl/src/errno/strerror.c b/system/lib/libc/musl/src/errno/strerror.c index 7f926432b3090..8ee4ac2f8b9ee 100644 --- a/system/lib/libc/musl/src/errno/strerror.c +++ b/system/lib/libc/musl/src/errno/strerror.c @@ -36,12 +36,24 @@ char *__strerror_l(int e, locale_t loc) #endif if (e >= sizeof errmsgidx / sizeof *errmsgidx) e = 0; s = (char *)&errmsgstr + errmsgidx[e]; +#ifdef __EMSCRIPTEN__ + // strerror is a (debug) dependency of many emscripten syscalls which mean it + // must be excluded from LTO, along with all of its dependencies. + // In order to limit the transitive dependencies we disable localization of + // rrno messages here. + return (char *)s; +#else return (char *)LCTRANS(s, LC_MESSAGES, loc); +#endif } char *strerror(int e) { +#ifdef __EMSCRIPTEN__ + return __strerror_l(e, NULL); +#else return __strerror_l(e, CURRENT_LOCALE); +#endif } weak_alias(__strerror_l, strerror_l); diff --git a/test/core/test_emmalloc_trim.out b/test/core/test_emmalloc_trim.out index 160a42927987b..f745d4c03565f 100644 --- a/test/core/test_emmalloc_trim.out +++ b/test/core/test_emmalloc_trim.out @@ -1,35 +1,35 @@ heap size: 134217728 dynamic heap 0: 4096 free dynamic memory 0: 4096 -unclaimed heap memory 0: 2147352576 -sbrk 0: 0x11000 +unclaimed heap memory 0: 2147348480 +sbrk 0: 0x12000 1 dynamic heap 1: 37752832 free dynamic memory 1: 4096 -unclaimed heap memory 1: 2109603840 -sbrk 1: 0x2411000 +unclaimed heap memory 1: 2109599744 +sbrk 1: 0x2412000 1st trim: 1 dynamic heap 1: 37752832 free dynamic memory 1: 0 -unclaimed heap memory 1: 2109603840 -sbrk 1: 0x2411000 +unclaimed heap memory 1: 2109599744 +sbrk 1: 0x2412000 2nd trim: 0 dynamic heap 2: 37752832 free dynamic memory 2: 0 -unclaimed heap memory 2: 2109603840 -sbrk 2: 0x2411000 +unclaimed heap memory 2: 2109599744 +sbrk 2: 0x2412000 3rd trim: 1 dynamic heap 3: 33656832 free dynamic memory 3: 102400 -unclaimed heap memory 3: 2109603840 -sbrk 3: 0x2411000 +unclaimed heap memory 3: 2109599744 +sbrk 3: 0x2412000 4th trim: 0 dynamic heap 4: 33656832 free dynamic memory 4: 102400 -unclaimed heap memory 4: 2109603840 -sbrk 4: 0x2411000 +unclaimed heap memory 4: 2109599744 +sbrk 4: 0x2412000 5th trim: 1 dynamic heap 5: 33558528 free dynamic memory 5: 0 -unclaimed heap memory 5: 2109603840 -sbrk 5: 0x2411000 +unclaimed heap memory 5: 2109599744 +sbrk 5: 0x2412000 diff --git a/test/other/metadce/test_metadce_hello_O0.exports b/test/other/metadce/test_metadce_hello_O0.exports index 2ca637cc2dc99..46f6d0a6df26a 100644 --- a/test/other/metadce/test_metadce_hello_O0.exports +++ b/test/other/metadce/test_metadce_hello_O0.exports @@ -11,3 +11,4 @@ emscripten_stack_init fflush main memory +strerror diff --git a/test/other/metadce/test_metadce_hello_O0.funcs b/test/other/metadce/test_metadce_hello_O0.funcs index 828c134afc8c2..7b3556720ebea 100644 --- a/test/other/metadce/test_metadce_hello_O0.funcs +++ b/test/other/metadce/test_metadce_hello_O0.funcs @@ -14,6 +14,7 @@ $__ofl_lock $__ofl_unlock $__original_main $__stdio_write +$__strerror_l $__syscall_getpid $__towrite $__trunctfdf2 @@ -50,6 +51,7 @@ $pop_arg $pop_arg_long_double $printf $printf_core +$strerror $strnlen $vfprintf $wcrtomb diff --git a/test/other/metadce/test_metadce_hello_O0.gzsize b/test/other/metadce/test_metadce_hello_O0.gzsize index 42b603432aefe..20989ae74120d 100644 --- a/test/other/metadce/test_metadce_hello_O0.gzsize +++ b/test/other/metadce/test_metadce_hello_O0.gzsize @@ -1 +1 @@ -8017 +8014 diff --git a/test/other/metadce/test_metadce_hello_O0.jssize b/test/other/metadce/test_metadce_hello_O0.jssize index 08c6c3c6baf79..eadc795a750a7 100644 --- a/test/other/metadce/test_metadce_hello_O0.jssize +++ b/test/other/metadce/test_metadce_hello_O0.jssize @@ -1 +1 @@ -21507 +21501 diff --git a/test/other/metadce/test_metadce_hello_O0.size b/test/other/metadce/test_metadce_hello_O0.size index 049dd29b20364..df02f8bdc6a99 100644 --- a/test/other/metadce/test_metadce_hello_O0.size +++ b/test/other/metadce/test_metadce_hello_O0.size @@ -1 +1 @@ -12167 +14447 diff --git a/test/other/metadce/test_metadce_minimal_O0.gzsize b/test/other/metadce/test_metadce_minimal_O0.gzsize index 0590e000d1be1..27b7c4c784d54 100644 --- a/test/other/metadce/test_metadce_minimal_O0.gzsize +++ b/test/other/metadce/test_metadce_minimal_O0.gzsize @@ -1 +1 @@ -6584 +6581 diff --git a/test/other/metadce/test_metadce_minimal_O0.jssize b/test/other/metadce/test_metadce_minimal_O0.jssize index beee3558f3fa0..d9451ff90784f 100644 --- a/test/other/metadce/test_metadce_minimal_O0.jssize +++ b/test/other/metadce/test_metadce_minimal_O0.jssize @@ -1 +1 @@ -17647 +17641 diff --git a/test/other/test_unoptimized_code_size.js.size b/test/other/test_unoptimized_code_size.js.size index cc6bec5c11b1e..1344beee1bd04 100644 --- a/test/other/test_unoptimized_code_size.js.size +++ b/test/other/test_unoptimized_code_size.js.size @@ -1 +1 @@ -55036 +55082 diff --git a/test/other/test_unoptimized_code_size.wasm.size b/test/other/test_unoptimized_code_size.wasm.size index 5290e3177eb6a..6536a2077a279 100644 --- a/test/other/test_unoptimized_code_size.wasm.size +++ b/test/other/test_unoptimized_code_size.wasm.size @@ -1 +1 @@ -12164 +14444 diff --git a/test/other/test_unoptimized_code_size_strict.js.size b/test/other/test_unoptimized_code_size_strict.js.size index f341ef989e816..261660aa0cc6e 100644 --- a/test/other/test_unoptimized_code_size_strict.js.size +++ b/test/other/test_unoptimized_code_size_strict.js.size @@ -1 +1 @@ -53933 +53979 diff --git a/test/other/test_unoptimized_code_size_strict.wasm.size b/test/other/test_unoptimized_code_size_strict.wasm.size index 5290e3177eb6a..6536a2077a279 100644 --- a/test/other/test_unoptimized_code_size_strict.wasm.size +++ b/test/other/test_unoptimized_code_size_strict.wasm.size @@ -1 +1 @@ -12164 +14444 diff --git a/tools/emscripten.py b/tools/emscripten.py index 696da9b7297a1..7ecc849aa6cf5 100644 --- a/tools/emscripten.py +++ b/tools/emscripten.py @@ -1075,6 +1075,7 @@ def create_pointer_conversion_wrappers(metadata): 'stbi_image_free': 'vp', 'stbi_load': 'ppppp_', 'stbi_load_from_memory': 'pp_ppp_', + 'strerror': 'p_', 'emscripten_proxy_finish': '_p', 'emscripten_proxy_execute_queue': '_p', '_emval_coro_resume': '_pp', diff --git a/tools/system_libs.py b/tools/system_libs.py index 1892de757cc58..04a458975d9c8 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -1070,9 +1070,10 @@ def get_libcall_files(self): path='system/lib/libc/musl/src/string', filenames=['strlen.c']) + # Transitively required by many system call imports errno_files = files_in_path( path='system/lib/libc/musl/src/errno', - filenames=['__errno_location.c']) + filenames=['__errno_location.c', 'strerror.c']) return math_files + exit_files + other_files + iprintf_files + errno_files