From 22620d5cc008f54d4a4c327dac1c88fead4c1545 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 04:22:25 +0000 Subject: [PATCH 01/58] Locate shared libraries using rpath --- src/lib/libdylink.js | 54 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index af499dc561f5a..57d52d702c8d6 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -48,6 +48,40 @@ var LibraryDylink = { registerWasmPlugin(); `, $preloadedWasm: {}, + + // Read file from the filesystem. + // This is used to load shared libraries from the filesystem. + $readFileFromFS__deps: ['$FS', '$PATH'], + $readFileFromFS: (filename, searchDirs) => { + var candidates = []; + if (PATH.isAbs(filename)) { + candidates.push(filename); + } else if (searchDirs) { + for (var i = 0; i < searchDirs.length; i++) { + candidates.push(PATH.join(searchDirs[i], filename)); + } + } else { + return null; + } + + for (var i = 0; i < candidates.length; i++) { + var path = candidates[i]; + if (FS.findObject(path)) { + return FS.readFile(path, {encoding: 'binary'}); + } + } + + return null; + }, + + $getDefaultLibDirs__deps: ['$ENV'], + $getDefaultLibDirs: () => { + var ldLibraryPath = ENV.get('LD_LIBRARY_PATH'); + if (ldLibraryPath) { + return ldLibraryPath.split(':'); + } + return []; + }, #endif // FILESYSTEM $isSymbolDefined: (symName) => { @@ -889,12 +923,12 @@ var LibraryDylink = { if (flags.loadAsync) { return metadata.neededDynlibs .reduce((chain, dynNeeded) => chain.then(() => - loadDynamicLibrary(dynNeeded, flags, localScope) + loadDynamicLibrary(dynNeeded, flags, localScope, metadata.runtimePaths) ), Promise.resolve()) .then(loadModule); } - metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope)); + metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope, metadata.runtimePaths)); return loadModule(); }, @@ -949,6 +983,8 @@ var LibraryDylink = { '$asyncLoad', #if FILESYSTEM '$preloadedWasm', + '$readFileFromFS', + '$getDefaultLibDirs', #endif #if DYNCALLS || !WASM_BIGINT '$registerDynCallSymbols', @@ -959,7 +995,7 @@ var LibraryDylink = { * @param {number=} handle * @param {Object=} localScope */`, - $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, handle) { + $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, runtimePaths, handle) { #if DYLINK_DEBUG dbg(`loadDynamicLibrary: ${libName} handle: ${handle}`); dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); @@ -1024,6 +1060,14 @@ var LibraryDylink = { } } +#if FILESYSTEM + var searchDirs = getDefaultLibDirs() + (runtimePaths || []); + var libData = readFileFromFS(libName, searchDirs); + if (libData) { + return flags.loadAsync ? Promise.resolve(libData) : libFile; + } +#endif + var libFile = locateFile(libName); if (flags.loadAsync) { return asyncLoad(libFile); @@ -1142,11 +1186,11 @@ var LibraryDylink = { } if (jsflags.loadAsync) { - return loadDynamicLibrary(filename, combinedFlags, localScope, handle); + return loadDynamicLibrary(filename, combinedFlags, localScope, [], handle); } try { - return loadDynamicLibrary(filename, combinedFlags, localScope, handle) + return loadDynamicLibrary(filename, combinedFlags, localScope, [], handle) } catch (e) { #if ASSERTIONS err(`Error in loading dynamic library ${filename}: ${e}`); From dfa80d84331b2098ab1748999b81b9fce449f353 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 05:58:32 +0000 Subject: [PATCH 02/58] Use rpath to load shared libraries --- src/lib/libdylink.js | 54 ++++---------------------------------------- 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 57d52d702c8d6..af499dc561f5a 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -48,40 +48,6 @@ var LibraryDylink = { registerWasmPlugin(); `, $preloadedWasm: {}, - - // Read file from the filesystem. - // This is used to load shared libraries from the filesystem. - $readFileFromFS__deps: ['$FS', '$PATH'], - $readFileFromFS: (filename, searchDirs) => { - var candidates = []; - if (PATH.isAbs(filename)) { - candidates.push(filename); - } else if (searchDirs) { - for (var i = 0; i < searchDirs.length; i++) { - candidates.push(PATH.join(searchDirs[i], filename)); - } - } else { - return null; - } - - for (var i = 0; i < candidates.length; i++) { - var path = candidates[i]; - if (FS.findObject(path)) { - return FS.readFile(path, {encoding: 'binary'}); - } - } - - return null; - }, - - $getDefaultLibDirs__deps: ['$ENV'], - $getDefaultLibDirs: () => { - var ldLibraryPath = ENV.get('LD_LIBRARY_PATH'); - if (ldLibraryPath) { - return ldLibraryPath.split(':'); - } - return []; - }, #endif // FILESYSTEM $isSymbolDefined: (symName) => { @@ -923,12 +889,12 @@ var LibraryDylink = { if (flags.loadAsync) { return metadata.neededDynlibs .reduce((chain, dynNeeded) => chain.then(() => - loadDynamicLibrary(dynNeeded, flags, localScope, metadata.runtimePaths) + loadDynamicLibrary(dynNeeded, flags, localScope) ), Promise.resolve()) .then(loadModule); } - metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope, metadata.runtimePaths)); + metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope)); return loadModule(); }, @@ -983,8 +949,6 @@ var LibraryDylink = { '$asyncLoad', #if FILESYSTEM '$preloadedWasm', - '$readFileFromFS', - '$getDefaultLibDirs', #endif #if DYNCALLS || !WASM_BIGINT '$registerDynCallSymbols', @@ -995,7 +959,7 @@ var LibraryDylink = { * @param {number=} handle * @param {Object=} localScope */`, - $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, runtimePaths, handle) { + $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, handle) { #if DYLINK_DEBUG dbg(`loadDynamicLibrary: ${libName} handle: ${handle}`); dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); @@ -1060,14 +1024,6 @@ var LibraryDylink = { } } -#if FILESYSTEM - var searchDirs = getDefaultLibDirs() + (runtimePaths || []); - var libData = readFileFromFS(libName, searchDirs); - if (libData) { - return flags.loadAsync ? Promise.resolve(libData) : libFile; - } -#endif - var libFile = locateFile(libName); if (flags.loadAsync) { return asyncLoad(libFile); @@ -1186,11 +1142,11 @@ var LibraryDylink = { } if (jsflags.loadAsync) { - return loadDynamicLibrary(filename, combinedFlags, localScope, [], handle); + return loadDynamicLibrary(filename, combinedFlags, localScope, handle); } try { - return loadDynamicLibrary(filename, combinedFlags, localScope, [], handle) + return loadDynamicLibrary(filename, combinedFlags, localScope, handle) } catch (e) { #if ASSERTIONS err(`Error in loading dynamic library ${filename}: ${e}`); From 3b9d68eea5973d11d1c6bedffaf2cf864938c506 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 06:02:12 +0000 Subject: [PATCH 03/58] Update test --- src/lib/libdylink.js | 90 +++++++++++++++++++++++++-- test/test_other.py | 144 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+), 5 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index af499dc561f5a..a3c48f6d89551 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -48,6 +48,57 @@ var LibraryDylink = { registerWasmPlugin(); `, $preloadedWasm: {}, + + $locateLibraryFromFS__deps: ['$FS', '$PATH'], + $locateLibraryFromFS: (filename, searchDirs) => { + // Find the library in the filesystem + // returns [true, abspath] if found, [false, null] otherwise. + var candidates = []; + if (PATH.isAbs(filename)) { + candidates.push(filename); + } else if (searchDirs) { + for (var i = 0; i < searchDirs.length; i++) { + candidates.push(PATH.join(searchDirs[i], filename)); + } + } else { + return [false, null]; + } + + for (var i = 0; i < candidates.length; i++) { + var path = candidates[i]; + if (FS.findObject(path)) { + return [true, path]; + } + } + + return [false, null]; + }, + + $readLibraryFromFS__deps: ['$FS'], + $readLibraryFromFS: (path) => { + var data = FS.readFile(path, {encoding: 'binary'}); + return data; + }, + + $getDefaultLibDirs__deps: ['$ENV'], + $getDefaultLibDirs: () => { + var ldLibraryPath = ENV['LD_LIBRARY_PATH']; + if (ldLibraryPath) { + return ldLibraryPath.split(':'); + } + return []; + }, + + $replaceORIGIN__deps: ['$FS', '$PATH'], + $replaceORIGIN: (parentLibPath, rpath) => { + if (rpath.startsWith('$ORIGIN')) { + // TODO: what to do if we only know the relative path of the file? It will return "." here. + var origin = PATH.dirname(parentLibPath); + return rpath.replace('$ORIGIN', origin); + } + + return rpath + }, #endif // FILESYSTEM $isSymbolDefined: (symName) => { @@ -889,12 +940,12 @@ var LibraryDylink = { if (flags.loadAsync) { return metadata.neededDynlibs .reduce((chain, dynNeeded) => chain.then(() => - loadDynamicLibrary(dynNeeded, flags, localScope) + loadDynamicLibrary(dynNeeded, flags, localScope, { parentLibPath: libName, paths: metadata.runtimePaths }) ), Promise.resolve()) .then(loadModule); } - metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope)); + metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope, { parentLibPath: libName, paths: metadata.runtimePaths })); return loadModule(); }, @@ -949,6 +1000,10 @@ var LibraryDylink = { '$asyncLoad', #if FILESYSTEM '$preloadedWasm', + '$locateLibraryFromFS', + '$readLibraryFromFS', + '$getDefaultLibDirs', + '$replaceORIGIN', #endif #if DYNCALLS || !WASM_BIGINT '$registerDynCallSymbols', @@ -959,11 +1014,24 @@ var LibraryDylink = { * @param {number=} handle * @param {Object=} localScope */`, - $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, handle) { + $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, rpath = {parentLibPath: '', paths: []}, handle) { #if DYLINK_DEBUG dbg(`loadDynamicLibrary: ${libName} handle: ${handle}`); dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); #endif + +#if FILESYSTEM + var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); + var searchDirs = getDefaultLibDirs().concat(runtimePathsAbs); + var [existsInFS, libNameAbs] = locateLibraryFromFS(libName, searchDirs); + if (existsInFS) { + libName = libNameAbs; +#if DYLINK_DEBUG + dbg(`found library from filesystem: ${libName}`); +#endif + } +#endif + // when loadDynamicLibrary did not have flags, libraries were loaded // globally & permanently @@ -1024,6 +1092,18 @@ var LibraryDylink = { } } +#if FILESYSTEM + if (existsInFS) { + var libData = readLibraryFromFS(libName); + if (libData) { +#if DYLINK_DEBUG + dbg(`loaded library from filesystem: ${libName}`); +#endif + return flags.loadAsync ? Promise.resolve(libData) : libData; + } + } +#endif + var libFile = locateFile(libName); if (flags.loadAsync) { return asyncLoad(libFile); @@ -1142,11 +1222,11 @@ var LibraryDylink = { } if (jsflags.loadAsync) { - return loadDynamicLibrary(filename, combinedFlags, localScope, handle); + return loadDynamicLibrary(filename, combinedFlags, localScope, {}, handle); } try { - return loadDynamicLibrary(filename, combinedFlags, localScope, handle) + return loadDynamicLibrary(filename, combinedFlags, localScope, {}, handle) } catch (e) { #if ASSERTIONS err(`Error in loading dynamic library ${filename}: ${e}`); diff --git a/test/test_other.py b/test/test_other.py index 0d605ac6f5721..6bb3c10600f86 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -2406,6 +2406,7 @@ def get_runtime_paths(path): self.assertEqual(get_runtime_paths('libside1.so'), ['$ORIGIN']) self.assertEqual(get_runtime_paths('a.out.wasm'), ['$ORIGIN']) + def test_dylink_LEGACY_GL_EMULATION(self): # LEGACY_GL_EMULATION wraps JS library functions. This test ensure that when it does # so it preserves the `.sig` attributes needed by dynamic linking. @@ -7662,6 +7663,149 @@ def test_ld_library_path(self, args): self.assertContained('Hello4', out) self.assertContained('Ok', out) + @parameterized({ + '': ([],), + 'pthread': (['-g', '-pthread', '-Wno-experimental', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'],), + }) + def test_ld_library_path_dependencies(self, args): + if args: + self.setup_node_pthreads() + create_file('hello1_dep.c', r''' +#include<stdio.h> + +void hello1_2() { + printf ("Hello1_2\n"); + return; +} +''') + create_file('hello1.c', r''' +#include <stdio.h> + +void hello1_2(); + +void hello1() { + printf ("Hello1\n"); + hello1_2(); + return; +} +''') + create_file('pre.js', r''' +Module.preRun = () => { + ENV['LD_LIBRARY_PATH']='/lib:/usr/lib:/usr/local/lib'; +}; +''') + create_file('main.c', r''' +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> + +int main() { + void *h; + void (*f)(); + double (*f2)(double); + + h = dlopen("libhello1.wasm", RTLD_NOW); + assert(h); + f = dlsym(h, "hello1"); + assert(f); + f(); + dlclose(h); + + printf("Ok\n"); + + return 0; +} +''') + os.mkdir('subdir') + self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE'] + args) + self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so'] + args) + self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', + '--embed-file', 'hello1.wasm@/libhello1.wasm', + '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/libhello1_dep.so', + 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', + '-L./subdir', '-lhello1_dep', '--pre-js', 'pre.js'] + args) + out = self.run_js('main.js') + self.assertContained('Hello1', out) + self.assertContained('Hello1_2', out) + self.assertContained('Ok', out) + + + @parameterized({ + '': ([],), + 'pthread': (['-g', '-pthread', '-Wno-experimental', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'],), + }) + def test_rpath_dependencies(self, args): + if args: + self.setup_node_pthreads() + create_file('hello1_dep.c', r''' +#include<stdio.h> + +void hello1_2() { + printf ("Hello1_2\n"); + return; +} +''') + create_file('hello1.c', r''' +#include <stdio.h> + +void hello1_2(); + +void hello1() { + printf ("Hello1\n"); + hello1_2(); + return; +} +''') + create_file('main.c', r''' +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> + +int main() { + void *h; + void (*f)(); + double (*f2)(double); + + h = dlopen("/usr/lib/libhello1.wasm", RTLD_NOW); + assert(h); + f = dlsym(h, "hello1"); + assert(f); + f(); + dlclose(h); + + printf("Ok\n"); + + return 0; +} +''') + os.mkdir('subdir') + + def _build(rpath_flag): + self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE'] + args) + self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so'] + rpath_flag + args) + self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', + '--embed-file', 'hello1.wasm@/usr/lib/libhello1.wasm', + '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/subdir/libhello1_dep.so', + 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', + '-L./subdir', '-lhello1_dep'] + args) + + # case 1) without rpath: fail to locate the library + _build([]) + out = self.run_js('main.js', assert_returncode=NON_ZERO) + self.assertContained(r"no such file or directory, open '.*libhello1_dep\.so'", out, regex=True) + + # case 2) with rpath: success + _build(['-Wl,-rpath,$ORIGIN/subdir']) + out = self.run_js('main.js') + self.assertContained('Hello1', out) + self.assertContained('Hello1_2', out) + self.assertContained('Ok', out) + + def test_dlopen_bad_flags(self): create_file('main.c', r''' #include <dlfcn.h> From 39db9748c44eb4f54179868f5d8816c68c6c7b31 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 08:28:44 +0000 Subject: [PATCH 04/58] ruff --- test/test_other.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index 6bb3c10600f86..997380d5b6921 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -2406,7 +2406,6 @@ def get_runtime_paths(path): self.assertEqual(get_runtime_paths('libside1.so'), ['$ORIGIN']) self.assertEqual(get_runtime_paths('a.out.wasm'), ['$ORIGIN']) - def test_dylink_LEGACY_GL_EMULATION(self): # LEGACY_GL_EMULATION wraps JS library functions. This test ensure that when it does # so it preserves the `.sig` attributes needed by dynamic linking. @@ -7731,7 +7730,6 @@ def test_ld_library_path_dependencies(self, args): self.assertContained('Hello1_2', out) self.assertContained('Ok', out) - @parameterized({ '': ([],), 'pthread': (['-g', '-pthread', '-Wno-experimental', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'],), @@ -7805,7 +7803,6 @@ def _build(rpath_flag): self.assertContained('Hello1_2', out) self.assertContained('Ok', out) - def test_dlopen_bad_flags(self): create_file('main.c', r''' #include <dlfcn.h> From 1568cfe00860efe0140485e44f30dbb0084444d0 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 08:32:32 +0000 Subject: [PATCH 05/58] Automatic rebaseline of codesize expectations. NFC This is an automatic change generated by tools/maint/rebaseline_tests.py. The following (2) test expectation files were updated by running the tests with `--rebaseline`: ``` other/codesize/test_codesize_hello_dylink.gzsize: 5892 => 11266 [+5374 bytes / +91.21%] other/codesize/test_codesize_hello_dylink.jssize: 12932 => 26423 [+13491 bytes / +104.32%] Average change: +97.77% (+91.21% - +104.32%) ``` --- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index 0d610d1996601..e454b3b9be32b 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -5892 +11266 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index ec95a0a152106..dc8901063b09e 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -12932 +26423 From 4f3ffe56dc0a4c4b1af7e21cdb1a625017e0b3e2 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 08:57:45 +0000 Subject: [PATCH 06/58] Don't run test on pthread --- src/lib/libdylink.js | 4 ++-- test/test_other.py | 26 +++++++++----------------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index a3c48f6d89551..eee21ecf7e65f 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -1026,10 +1026,10 @@ var LibraryDylink = { var [existsInFS, libNameAbs] = locateLibraryFromFS(libName, searchDirs); if (existsInFS) { libName = libNameAbs; + } #if DYLINK_DEBUG - dbg(`found library from filesystem: ${libName}`); + dbg(`checking filesystem: ${libName}: ${existsInFS ? 'found' : 'not found'}`); #endif - } #endif // when loadDynamicLibrary did not have flags, libraries were loaded diff --git a/test/test_other.py b/test/test_other.py index 997380d5b6921..814680a6424f9 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -2406,6 +2406,7 @@ def get_runtime_paths(path): self.assertEqual(get_runtime_paths('libside1.so'), ['$ORIGIN']) self.assertEqual(get_runtime_paths('a.out.wasm'), ['$ORIGIN']) + def test_dylink_LEGACY_GL_EMULATION(self): # LEGACY_GL_EMULATION wraps JS library functions. This test ensure that when it does # so it preserves the `.sig` attributes needed by dynamic linking. @@ -7662,10 +7663,6 @@ def test_ld_library_path(self, args): self.assertContained('Hello4', out) self.assertContained('Ok', out) - @parameterized({ - '': ([],), - 'pthread': (['-g', '-pthread', '-Wno-experimental', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'],), - }) def test_ld_library_path_dependencies(self, args): if args: self.setup_node_pthreads() @@ -7718,25 +7715,19 @@ def test_ld_library_path_dependencies(self, args): } ''') os.mkdir('subdir') - self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE'] + args) - self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so'] + args) + self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE']) + self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so']) self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', '--embed-file', 'hello1.wasm@/libhello1.wasm', '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/libhello1_dep.so', 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', - '-L./subdir', '-lhello1_dep', '--pre-js', 'pre.js'] + args) + '-L./subdir', '-lhello1_dep', '--pre-js', 'pre.js']) out = self.run_js('main.js') self.assertContained('Hello1', out) self.assertContained('Hello1_2', out) self.assertContained('Ok', out) - @parameterized({ - '': ([],), - 'pthread': (['-g', '-pthread', '-Wno-experimental', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'],), - }) - def test_rpath_dependencies(self, args): - if args: - self.setup_node_pthreads() + def test_rpath_dependencies(self): create_file('hello1_dep.c', r''' #include<stdio.h> @@ -7783,13 +7774,13 @@ def test_rpath_dependencies(self, args): os.mkdir('subdir') def _build(rpath_flag): - self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE'] + args) - self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so'] + rpath_flag + args) + self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE']) + self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so'] + rpath_flag) self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', '--embed-file', 'hello1.wasm@/usr/lib/libhello1.wasm', '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/subdir/libhello1_dep.so', 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', - '-L./subdir', '-lhello1_dep'] + args) + '-L./subdir', '-lhello1_dep']) # case 1) without rpath: fail to locate the library _build([]) @@ -7803,6 +7794,7 @@ def _build(rpath_flag): self.assertContained('Hello1_2', out) self.assertContained('Ok', out) + def test_dlopen_bad_flags(self): create_file('main.c', r''' #include <dlfcn.h> From e49d1a2aea1606b37bb5d7e223b505709a076805 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 09:18:12 +0000 Subject: [PATCH 07/58] Fix wasmfs test --- src/lib/libdylink.js | 5 +++++ src/lib/libwasmfs.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index eee21ecf7e65f..fa7b49b0baf1c 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -53,6 +53,11 @@ var LibraryDylink = { $locateLibraryFromFS: (filename, searchDirs) => { // Find the library in the filesystem // returns [true, abspath] if found, [false, null] otherwise. + if (!(typeof FS.findObject === 'function')) { + // FS may not have the findObject method if the filesystem is not + // used in the build. Skip the search in this case. + return [false, null]; + } var candidates = []; if (PATH.isAbs(filename)) { candidates.push(filename); diff --git a/src/lib/libwasmfs.js b/src/lib/libwasmfs.js index 4c62b1dffebbb..2d5fe3b3d8e44 100644 --- a/src/lib/libwasmfs.js +++ b/src/lib/libwasmfs.js @@ -512,7 +512,7 @@ addToLibrary({ return FS_mknod(path, mode, 0); }, - $FS_writeFile__deps: ['_wasmfs_write_file', '$stackSave', '$stackRestore'], + $FS_writeFile__deps: ['_wasmfs_write_file', '$stackSave', '$stackRestore', 'malloc', 'free'], $FS_writeFile: (path, data) => { var sp = stackSave(); var pathBuffer = stringToUTF8OnStack(path); From 82b38da05cb6daeee11be63c7cc6022fc93aba39 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 09:22:50 +0000 Subject: [PATCH 08/58] Automatic rebaseline of codesize expectations. NFC This is an automatic change generated by tools/maint/rebaseline_tests.py. The following (2) test expectation files were updated by running the tests with `--rebaseline`: ``` other/codesize/test_codesize_hello_dylink.gzsize: 11266 => 11204 [-62 bytes / -0.55%] other/codesize/test_codesize_hello_dylink.jssize: 26423 => 26287 [-136 bytes / -0.51%] Average change: -0.53% (-0.55% - -0.51%) ``` --- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index e454b3b9be32b..f4fadde1d4a04 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11266 +11204 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index dc8901063b09e..915a6dc91cdb4 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -26423 +26287 From 3689d4ef3b5762fd16b60e05e4fc432135042727 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Sun, 9 Mar 2025 09:32:22 +0000 Subject: [PATCH 09/58] ruff --- test/test_other.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index 814680a6424f9..5135ce5019b60 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -2406,7 +2406,6 @@ def get_runtime_paths(path): self.assertEqual(get_runtime_paths('libside1.so'), ['$ORIGIN']) self.assertEqual(get_runtime_paths('a.out.wasm'), ['$ORIGIN']) - def test_dylink_LEGACY_GL_EMULATION(self): # LEGACY_GL_EMULATION wraps JS library functions. This test ensure that when it does # so it preserves the `.sig` attributes needed by dynamic linking. @@ -7794,7 +7793,6 @@ def _build(rpath_flag): self.assertContained('Hello1_2', out) self.assertContained('Ok', out) - def test_dlopen_bad_flags(self): create_file('main.c', r''' #include <dlfcn.h> From a0732d7752e5633deea61315e6cb6a86c2716626 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Mon, 10 Mar 2025 13:55:18 +0000 Subject: [PATCH 10/58] Address comments --- src/lib/libdylink.js | 38 +++++++++++++++----------------------- test/test_other.py | 4 +--- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index fa7b49b0baf1c..09afa366df1e3 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -12,6 +12,7 @@ var LibraryDylink = { #if FILESYSTEM + // FILESYSTEM comes with FS and PATH modules $registerWasmPlugin__deps: ['$preloadPlugins'], $registerWasmPlugin: () => { // Use string keys here to avoid minification since the plugin consumer @@ -49,15 +50,9 @@ var LibraryDylink = { `, $preloadedWasm: {}, - $locateLibraryFromFS__deps: ['$FS', '$PATH'], $locateLibraryFromFS: (filename, searchDirs) => { - // Find the library in the filesystem - // returns [true, abspath] if found, [false, null] otherwise. - if (!(typeof FS.findObject === 'function')) { - // FS may not have the findObject method if the filesystem is not - // used in the build. Skip the search in this case. - return [false, null]; - } + // Find the library in the filesystem. + // returns null if not found. var candidates = []; if (PATH.isAbs(filename)) { candidates.push(filename); @@ -66,20 +61,22 @@ var LibraryDylink = { candidates.push(PATH.join(searchDirs[i], filename)); } } else { - return [false, null]; + return null; } for (var i = 0; i < candidates.length; i++) { var path = candidates[i]; - if (FS.findObject(path)) { - return [true, path]; + try { + var res = FS.lookupPath(path); + return res.path; + } catch(e) { + // do nothing is file is not found } } - return [false, null]; + return null; }, - $readLibraryFromFS__deps: ['$FS'], $readLibraryFromFS: (path) => { var data = FS.readFile(path, {encoding: 'binary'}); return data; @@ -87,14 +84,9 @@ var LibraryDylink = { $getDefaultLibDirs__deps: ['$ENV'], $getDefaultLibDirs: () => { - var ldLibraryPath = ENV['LD_LIBRARY_PATH']; - if (ldLibraryPath) { - return ldLibraryPath.split(':'); - } - return []; + return ENV['LD_LIBRARY_PATH']?.split(':') ?? []; }, - $replaceORIGIN__deps: ['$FS', '$PATH'], $replaceORIGIN: (parentLibPath, rpath) => { if (rpath.startsWith('$ORIGIN')) { // TODO: what to do if we only know the relative path of the file? It will return "." here. @@ -1028,12 +1020,12 @@ var LibraryDylink = { #if FILESYSTEM var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); var searchDirs = getDefaultLibDirs().concat(runtimePathsAbs); - var [existsInFS, libNameAbs] = locateLibraryFromFS(libName, searchDirs); - if (existsInFS) { + var libNameAbs = locateLibraryFromFS(libName, searchDirs); + if (libNameAbs) { libName = libNameAbs; } #if DYLINK_DEBUG - dbg(`checking filesystem: ${libName}: ${existsInFS ? 'found' : 'not found'}`); + dbg(`checking filesystem: ${libName}: ${libNameAbs ? 'found' : 'not found'}`); #endif #endif @@ -1098,7 +1090,7 @@ var LibraryDylink = { } #if FILESYSTEM - if (existsInFS) { + if (libNameAbs) { var libData = readLibraryFromFS(libName); if (libData) { #if DYLINK_DEBUG diff --git a/test/test_other.py b/test/test_other.py index 5135ce5019b60..82c30ee6d4982 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7662,9 +7662,7 @@ def test_ld_library_path(self, args): self.assertContained('Hello4', out) self.assertContained('Ok', out) - def test_ld_library_path_dependencies(self, args): - if args: - self.setup_node_pthreads() + def test_ld_library_path_dependencies(self): create_file('hello1_dep.c', r''' #include<stdio.h> From defefc2e26988d3fc770d7d3931fec7018037568 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Mon, 10 Mar 2025 14:06:55 +0000 Subject: [PATCH 11/58] Make closure compiler happy --- src/lib/libdylink.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 09afa366df1e3..bf824adc22b22 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -12,7 +12,6 @@ var LibraryDylink = { #if FILESYSTEM - // FILESYSTEM comes with FS and PATH modules $registerWasmPlugin__deps: ['$preloadPlugins'], $registerWasmPlugin: () => { // Use string keys here to avoid minification since the plugin consumer @@ -53,6 +52,12 @@ var LibraryDylink = { $locateLibraryFromFS: (filename, searchDirs) => { // Find the library in the filesystem. // returns null if not found. + if (!(typeof PATH === 'object' && typeof FS === 'object')) { + // FILESYSTEM comes with FS and PATH modules + // so this will always pass, but closure compiler complains if we don't check this here. + return null + } + var candidates = []; if (PATH.isAbs(filename)) { candidates.push(filename); From 8a7196dcb7cd40a4e27f45c03316e24f9cecece1 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Mon, 10 Mar 2025 14:12:57 +0000 Subject: [PATCH 12/58] Automatic rebaseline of codesize expectations. NFC This is an automatic change generated by tools/maint/rebaseline_tests.py. The following (2) test expectation files were updated by running the tests with `--rebaseline`: ``` other/codesize/test_codesize_hello_dylink.gzsize: 11204 => 6148 [-5056 bytes / -45.13%] other/codesize/test_codesize_hello_dylink.jssize: 26287 => 13509 [-12778 bytes / -48.61%] Average change: -46.87% (-48.61% - -45.13%) ``` --- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index f4fadde1d4a04..1cee4c1d1d8bd 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11204 +6148 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index 915a6dc91cdb4..e07ddf9ef30eb 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -26287 +13509 From abacbf04884d5eda3cd116fdfced323f037effee Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Tue, 11 Mar 2025 14:05:22 +0000 Subject: [PATCH 13/58] Fix tests --- src/lib/libdylink.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index bf824adc22b22..49184cf7ba31f 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -49,28 +49,28 @@ var LibraryDylink = { `, $preloadedWasm: {}, + $locateLibraryFromFS__deps: ['$FS'], $locateLibraryFromFS: (filename, searchDirs) => { // Find the library in the filesystem. // returns null if not found. - if (!(typeof PATH === 'object' && typeof FS === 'object')) { - // FILESYSTEM comes with FS and PATH modules - // so this will always pass, but closure compiler complains if we don't check this here. - return null + if (typeof FS.lookupPath !== 'function') { + // wasmfs does not implement FS.lookupPath + return null; } var candidates = []; - if (PATH.isAbs(filename)) { + if (filename.charAt(0) === '/') { // abs path candidates.push(filename); } else if (searchDirs) { - for (var i = 0; i < searchDirs.length; i++) { - candidates.push(PATH.join(searchDirs[i], filename)); + for (var dir of searchDirs) { + // PATH.join does not work well with symlinks + candidates.push(dir + '/' + filename); } } else { return null; } - for (var i = 0; i < candidates.length; i++) { - var path = candidates[i]; + for (var path of candidates) { try { var res = FS.lookupPath(path); return res.path; @@ -82,6 +82,7 @@ var LibraryDylink = { return null; }, + $readLibraryFromFS__deps: ['$FS'], $readLibraryFromFS: (path) => { var data = FS.readFile(path, {encoding: 'binary'}); return data; @@ -92,6 +93,7 @@ var LibraryDylink = { return ENV['LD_LIBRARY_PATH']?.split(':') ?? []; }, + $replaceORIGIN__deps: ['$PATH'], $replaceORIGIN: (parentLibPath, rpath) => { if (rpath.startsWith('$ORIGIN')) { // TODO: what to do if we only know the relative path of the file? It will return "." here. From 2df17b34c06d95dfb9b933e4034377aa393a26e9 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi <def6488@gmail.com> Date: Tue, 11 Mar 2025 14:10:57 +0000 Subject: [PATCH 14/58] Automatic rebaseline of codesize expectations. NFC This is an automatic change generated by tools/maint/rebaseline_tests.py. The following (2) test expectation files were updated by running the tests with `--rebaseline`: ``` other/codesize/test_codesize_hello_dylink.gzsize: 6148 => 11089 [+4941 bytes / +80.37%] other/codesize/test_codesize_hello_dylink.jssize: 13509 => 25945 [+12436 bytes / +92.06%] Average change: +86.21% (+80.37% - +92.06%) ``` --- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index 1cee4c1d1d8bd..48f2b41978d7b 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -6148 +11089 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index e07ddf9ef30eb..d066a1c62bc9e 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -13509 +25945 From b23485cfbd866390ebec058d762195b7b47675f7 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Mon, 31 Mar 2025 16:08:17 +0200 Subject: [PATCH 15/58] Use C function for path lookup --- src/lib/libdylink.js | 39 ++++++++++++++++-------- system/lib/libc/dynlink.c | 63 ++++++++++++++++++++++----------------- test/test_other.py | 1 + 3 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 2907d422a2d01..26497e1cb54d9 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -88,11 +88,6 @@ var LibraryDylink = { return data; }, - $getDefaultLibDirs__deps: ['$ENV'], - $getDefaultLibDirs: () => { - return ENV['LD_LIBRARY_PATH']?.split(':') ?? []; - }, - $replaceORIGIN__deps: ['$PATH'], $replaceORIGIN: (parentLibPath, rpath) => { if (rpath.startsWith('$ORIGIN')) { @@ -1006,8 +1001,14 @@ var LibraryDylink = { '$preloadedWasm', '$locateLibraryFromFS', '$readLibraryFromFS', - '$getDefaultLibDirs', '$replaceORIGIN', + '_emscripten_resolve_path', + '$stackSave', + '$stackAlloc', + '$stackRestore', + '$lengthBytesUTF8', + '$stringToUTF8OnStack', + '$stringToUTF8', #endif #if DYNCALLS || !WASM_BIGINT '$registerDynCallSymbols', @@ -1026,13 +1027,27 @@ var LibraryDylink = { #if FILESYSTEM var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); - var searchDirs = getDefaultLibDirs().concat(runtimePathsAbs); - var libNameAbs = locateLibraryFromFS(libName, searchDirs); - if (libNameAbs) { - libName = libNameAbs; + var origStack = stackSave(); + var bufSize = 2*255 + 2; + var buf = stackAlloc(bufSize); + var size = 0; + for (var str of runtimePathsAbs) { + size += lengthBytesUTF8(str) + 1; + } + var rpath = stackAlloc(size); + var cur = rpath + for (var str of runtimePathsAbs) { + cur += stringToUTF8(str, cur, size); + HEAP8[cur] = ':'.charCodeAt(0); } + HEAP8[cur] = 0; + var libNameC = stringToUTF8OnStack(libName); + var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); + var foundFile = resLibNameC !== libNameC; + libName = UTF8ToString(resLibNameC); + stackRestore(origStack); #if DYLINK_DEBUG - dbg(`checking filesystem: ${libName}: ${libNameAbs ? 'found' : 'not found'}`); + dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); #endif #endif @@ -1097,7 +1112,7 @@ var LibraryDylink = { } #if FILESYSTEM - if (libNameAbs) { + if (foundFile) { var libData = readLibraryFromFS(libName); if (libData) { #if DYLINK_DEBUG diff --git a/system/lib/libc/dynlink.c b/system/lib/libc/dynlink.c index f5d0c57e95531..b594a67c2c2b3 100644 --- a/system/lib/libc/dynlink.c +++ b/system/lib/libc/dynlink.c @@ -484,41 +484,50 @@ static void dlopen_onerror(struct dso* dso, void* user_data) { } // Modified version of path_open from musl/ldso/dynlink.c -static int path_find(const char *name, const char *s, char *buf, size_t buf_size) { +static int path_find(const char *name, int ncandidates, const char **candidates, char *buf, size_t buf_size) { size_t l; int fd; - for (;;) { - s += strspn(s, ":\n"); - l = strcspn(s, ":\n"); - if (l-1 >= INT_MAX) return -1; - if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { - dbg("dlopen: path_find: %s", buf); - struct stat statbuf; - if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { - return 0; - } - switch (errno) { - case ENOENT: - case ENOTDIR: - case EACCES: - case ENAMETOOLONG: - break; - default: - dbg("dlopen: path_find failed: %s", strerror(errno)); - /* Any negative value but -1 will inhibit - * futher path search. */ - return -2; + for (int c = 0; c < ncandidates; c ++) { + const char* s = candidates[c]; + if (s == NULL) { + continue; + } + for (;;) { + s += strspn(s, ":\n"); + l = strcspn(s, ":\n"); + if (l-1 >= INT_MAX) return -1; + if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { + dbg("dlopen: path_find: %s", buf); + struct stat statbuf; + if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + return 0; + } + switch (errno) { + case ENOENT: + case ENOTDIR: + case EACCES: + case ENAMETOOLONG: + break; + default: + dbg("dlopen: path_find failed: %s", strerror(errno)); + /* Any negative value but -1 will inhibit + * futher path search. */ + return -2; + } } + s += l; } - s += l; } + return -1; } // Resolve filename using LD_LIBRARY_PATH -static const char* resolve_path(char* buf, const char* file, size_t buflen) { +const char* _emscripten_resolve_path(char* buf, const char* rpath, const char* file, size_t buflen) { if (!strchr(file, '/')) { const char* env_path = getenv("LD_LIBRARY_PATH"); - if (env_path && path_find(file, env_path, buf, buflen) == 0) { + int ncandidates = 2; + const char* candidates[2] = {env_path, rpath}; + if (env_path && path_find(file, ncandidates, candidates, buf, buflen) == 0) { dbg("dlopen: found in LD_LIBRARY_PATH: %s", buf); return buf; } @@ -553,7 +562,7 @@ static struct dso* _dlopen(const char* file, int flags) { do_write_lock(); char buf[2*NAME_MAX+2]; - file = resolve_path(buf, file, sizeof buf); + file = _emscripten_resolve_path(buf, NULL, file, sizeof buf); struct dso* p = find_existing(file); if (p) { @@ -593,7 +602,7 @@ void emscripten_dlopen(const char* filename, int flags, void* user_data, } do_write_lock(); char buf[2*NAME_MAX+2]; - filename = resolve_path(buf, filename, sizeof buf); + filename = _emscripten_resolve_path(buf, NULL, filename, sizeof buf); struct dso* p = find_existing(filename); if (p) { onsuccess(user_data, p); diff --git a/test/test_other.py b/test/test_other.py index cf8b71f4f76d1..76f011f55bf7c 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7691,6 +7691,7 @@ def test_ld_library_path(self, args): self.assertContained('Hello4', out) self.assertContained('Ok', out) + @also_with_wasmfs def test_ld_library_path_dependencies(self): create_file('hello1_dep.c', r''' #include<stdio.h> From 47f36f42ebac72a111b179babb7474eef3a543f9 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Mon, 31 Mar 2025 16:42:09 +0200 Subject: [PATCH 16/58] Revert "Use C function for path lookup" This reverts commit b23485cfbd866390ebec058d762195b7b47675f7. --- src/lib/libdylink.js | 39 ++++++++---------------- system/lib/libc/dynlink.c | 63 +++++++++++++++++---------------------- test/test_other.py | 1 - 3 files changed, 39 insertions(+), 64 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 26497e1cb54d9..2907d422a2d01 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -88,6 +88,11 @@ var LibraryDylink = { return data; }, + $getDefaultLibDirs__deps: ['$ENV'], + $getDefaultLibDirs: () => { + return ENV['LD_LIBRARY_PATH']?.split(':') ?? []; + }, + $replaceORIGIN__deps: ['$PATH'], $replaceORIGIN: (parentLibPath, rpath) => { if (rpath.startsWith('$ORIGIN')) { @@ -1001,14 +1006,8 @@ var LibraryDylink = { '$preloadedWasm', '$locateLibraryFromFS', '$readLibraryFromFS', + '$getDefaultLibDirs', '$replaceORIGIN', - '_emscripten_resolve_path', - '$stackSave', - '$stackAlloc', - '$stackRestore', - '$lengthBytesUTF8', - '$stringToUTF8OnStack', - '$stringToUTF8', #endif #if DYNCALLS || !WASM_BIGINT '$registerDynCallSymbols', @@ -1027,27 +1026,13 @@ var LibraryDylink = { #if FILESYSTEM var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); - var origStack = stackSave(); - var bufSize = 2*255 + 2; - var buf = stackAlloc(bufSize); - var size = 0; - for (var str of runtimePathsAbs) { - size += lengthBytesUTF8(str) + 1; - } - var rpath = stackAlloc(size); - var cur = rpath - for (var str of runtimePathsAbs) { - cur += stringToUTF8(str, cur, size); - HEAP8[cur] = ':'.charCodeAt(0); + var searchDirs = getDefaultLibDirs().concat(runtimePathsAbs); + var libNameAbs = locateLibraryFromFS(libName, searchDirs); + if (libNameAbs) { + libName = libNameAbs; } - HEAP8[cur] = 0; - var libNameC = stringToUTF8OnStack(libName); - var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); - var foundFile = resLibNameC !== libNameC; - libName = UTF8ToString(resLibNameC); - stackRestore(origStack); #if DYLINK_DEBUG - dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); + dbg(`checking filesystem: ${libName}: ${libNameAbs ? 'found' : 'not found'}`); #endif #endif @@ -1112,7 +1097,7 @@ var LibraryDylink = { } #if FILESYSTEM - if (foundFile) { + if (libNameAbs) { var libData = readLibraryFromFS(libName); if (libData) { #if DYLINK_DEBUG diff --git a/system/lib/libc/dynlink.c b/system/lib/libc/dynlink.c index b594a67c2c2b3..f5d0c57e95531 100644 --- a/system/lib/libc/dynlink.c +++ b/system/lib/libc/dynlink.c @@ -484,50 +484,41 @@ static void dlopen_onerror(struct dso* dso, void* user_data) { } // Modified version of path_open from musl/ldso/dynlink.c -static int path_find(const char *name, int ncandidates, const char **candidates, char *buf, size_t buf_size) { +static int path_find(const char *name, const char *s, char *buf, size_t buf_size) { size_t l; int fd; - for (int c = 0; c < ncandidates; c ++) { - const char* s = candidates[c]; - if (s == NULL) { - continue; - } - for (;;) { - s += strspn(s, ":\n"); - l = strcspn(s, ":\n"); - if (l-1 >= INT_MAX) return -1; - if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { - dbg("dlopen: path_find: %s", buf); - struct stat statbuf; - if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { - return 0; - } - switch (errno) { - case ENOENT: - case ENOTDIR: - case EACCES: - case ENAMETOOLONG: - break; - default: - dbg("dlopen: path_find failed: %s", strerror(errno)); - /* Any negative value but -1 will inhibit - * futher path search. */ - return -2; - } + for (;;) { + s += strspn(s, ":\n"); + l = strcspn(s, ":\n"); + if (l-1 >= INT_MAX) return -1; + if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { + dbg("dlopen: path_find: %s", buf); + struct stat statbuf; + if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + return 0; + } + switch (errno) { + case ENOENT: + case ENOTDIR: + case EACCES: + case ENAMETOOLONG: + break; + default: + dbg("dlopen: path_find failed: %s", strerror(errno)); + /* Any negative value but -1 will inhibit + * futher path search. */ + return -2; } - s += l; } + s += l; } - return -1; } // Resolve filename using LD_LIBRARY_PATH -const char* _emscripten_resolve_path(char* buf, const char* rpath, const char* file, size_t buflen) { +static const char* resolve_path(char* buf, const char* file, size_t buflen) { if (!strchr(file, '/')) { const char* env_path = getenv("LD_LIBRARY_PATH"); - int ncandidates = 2; - const char* candidates[2] = {env_path, rpath}; - if (env_path && path_find(file, ncandidates, candidates, buf, buflen) == 0) { + if (env_path && path_find(file, env_path, buf, buflen) == 0) { dbg("dlopen: found in LD_LIBRARY_PATH: %s", buf); return buf; } @@ -562,7 +553,7 @@ static struct dso* _dlopen(const char* file, int flags) { do_write_lock(); char buf[2*NAME_MAX+2]; - file = _emscripten_resolve_path(buf, NULL, file, sizeof buf); + file = resolve_path(buf, file, sizeof buf); struct dso* p = find_existing(file); if (p) { @@ -602,7 +593,7 @@ void emscripten_dlopen(const char* filename, int flags, void* user_data, } do_write_lock(); char buf[2*NAME_MAX+2]; - filename = _emscripten_resolve_path(buf, NULL, filename, sizeof buf); + filename = resolve_path(buf, filename, sizeof buf); struct dso* p = find_existing(filename); if (p) { onsuccess(user_data, p); diff --git a/test/test_other.py b/test/test_other.py index 76f011f55bf7c..cf8b71f4f76d1 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7691,7 +7691,6 @@ def test_ld_library_path(self, args): self.assertContained('Hello4', out) self.assertContained('Ok', out) - @also_with_wasmfs def test_ld_library_path_dependencies(self): create_file('hello1_dep.c', r''' #include<stdio.h> From 76d8fc826f4aeeee1714f92caa46d047012296b4 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Mon, 31 Mar 2025 16:45:30 +0200 Subject: [PATCH 17/58] Add also_with_wasmfs decorator --- test/test_other.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_other.py b/test/test_other.py index cf8b71f4f76d1..76f011f55bf7c 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7691,6 +7691,7 @@ def test_ld_library_path(self, args): self.assertContained('Hello4', out) self.assertContained('Ok', out) + @also_with_wasmfs def test_ld_library_path_dependencies(self): create_file('hello1_dep.c', r''' #include<stdio.h> From 17191ba3ca52f5609dbb67ba483e2235ef91c136 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Mon, 31 Mar 2025 17:04:01 +0200 Subject: [PATCH 18/58] Revert "Revert "Use C function for path lookup"" This reverts commit 47f36f42ebac72a111b179babb7474eef3a543f9. --- src/lib/libdylink.js | 39 ++++++++++++++++-------- system/lib/libc/dynlink.c | 63 ++++++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 39 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 2907d422a2d01..26497e1cb54d9 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -88,11 +88,6 @@ var LibraryDylink = { return data; }, - $getDefaultLibDirs__deps: ['$ENV'], - $getDefaultLibDirs: () => { - return ENV['LD_LIBRARY_PATH']?.split(':') ?? []; - }, - $replaceORIGIN__deps: ['$PATH'], $replaceORIGIN: (parentLibPath, rpath) => { if (rpath.startsWith('$ORIGIN')) { @@ -1006,8 +1001,14 @@ var LibraryDylink = { '$preloadedWasm', '$locateLibraryFromFS', '$readLibraryFromFS', - '$getDefaultLibDirs', '$replaceORIGIN', + '_emscripten_resolve_path', + '$stackSave', + '$stackAlloc', + '$stackRestore', + '$lengthBytesUTF8', + '$stringToUTF8OnStack', + '$stringToUTF8', #endif #if DYNCALLS || !WASM_BIGINT '$registerDynCallSymbols', @@ -1026,13 +1027,27 @@ var LibraryDylink = { #if FILESYSTEM var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); - var searchDirs = getDefaultLibDirs().concat(runtimePathsAbs); - var libNameAbs = locateLibraryFromFS(libName, searchDirs); - if (libNameAbs) { - libName = libNameAbs; + var origStack = stackSave(); + var bufSize = 2*255 + 2; + var buf = stackAlloc(bufSize); + var size = 0; + for (var str of runtimePathsAbs) { + size += lengthBytesUTF8(str) + 1; + } + var rpath = stackAlloc(size); + var cur = rpath + for (var str of runtimePathsAbs) { + cur += stringToUTF8(str, cur, size); + HEAP8[cur] = ':'.charCodeAt(0); } + HEAP8[cur] = 0; + var libNameC = stringToUTF8OnStack(libName); + var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); + var foundFile = resLibNameC !== libNameC; + libName = UTF8ToString(resLibNameC); + stackRestore(origStack); #if DYLINK_DEBUG - dbg(`checking filesystem: ${libName}: ${libNameAbs ? 'found' : 'not found'}`); + dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); #endif #endif @@ -1097,7 +1112,7 @@ var LibraryDylink = { } #if FILESYSTEM - if (libNameAbs) { + if (foundFile) { var libData = readLibraryFromFS(libName); if (libData) { #if DYLINK_DEBUG diff --git a/system/lib/libc/dynlink.c b/system/lib/libc/dynlink.c index f5d0c57e95531..b594a67c2c2b3 100644 --- a/system/lib/libc/dynlink.c +++ b/system/lib/libc/dynlink.c @@ -484,41 +484,50 @@ static void dlopen_onerror(struct dso* dso, void* user_data) { } // Modified version of path_open from musl/ldso/dynlink.c -static int path_find(const char *name, const char *s, char *buf, size_t buf_size) { +static int path_find(const char *name, int ncandidates, const char **candidates, char *buf, size_t buf_size) { size_t l; int fd; - for (;;) { - s += strspn(s, ":\n"); - l = strcspn(s, ":\n"); - if (l-1 >= INT_MAX) return -1; - if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { - dbg("dlopen: path_find: %s", buf); - struct stat statbuf; - if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { - return 0; - } - switch (errno) { - case ENOENT: - case ENOTDIR: - case EACCES: - case ENAMETOOLONG: - break; - default: - dbg("dlopen: path_find failed: %s", strerror(errno)); - /* Any negative value but -1 will inhibit - * futher path search. */ - return -2; + for (int c = 0; c < ncandidates; c ++) { + const char* s = candidates[c]; + if (s == NULL) { + continue; + } + for (;;) { + s += strspn(s, ":\n"); + l = strcspn(s, ":\n"); + if (l-1 >= INT_MAX) return -1; + if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { + dbg("dlopen: path_find: %s", buf); + struct stat statbuf; + if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + return 0; + } + switch (errno) { + case ENOENT: + case ENOTDIR: + case EACCES: + case ENAMETOOLONG: + break; + default: + dbg("dlopen: path_find failed: %s", strerror(errno)); + /* Any negative value but -1 will inhibit + * futher path search. */ + return -2; + } } + s += l; } - s += l; } + return -1; } // Resolve filename using LD_LIBRARY_PATH -static const char* resolve_path(char* buf, const char* file, size_t buflen) { +const char* _emscripten_resolve_path(char* buf, const char* rpath, const char* file, size_t buflen) { if (!strchr(file, '/')) { const char* env_path = getenv("LD_LIBRARY_PATH"); - if (env_path && path_find(file, env_path, buf, buflen) == 0) { + int ncandidates = 2; + const char* candidates[2] = {env_path, rpath}; + if (env_path && path_find(file, ncandidates, candidates, buf, buflen) == 0) { dbg("dlopen: found in LD_LIBRARY_PATH: %s", buf); return buf; } @@ -553,7 +562,7 @@ static struct dso* _dlopen(const char* file, int flags) { do_write_lock(); char buf[2*NAME_MAX+2]; - file = resolve_path(buf, file, sizeof buf); + file = _emscripten_resolve_path(buf, NULL, file, sizeof buf); struct dso* p = find_existing(file); if (p) { @@ -593,7 +602,7 @@ void emscripten_dlopen(const char* filename, int flags, void* user_data, } do_write_lock(); char buf[2*NAME_MAX+2]; - filename = resolve_path(buf, filename, sizeof buf); + filename = _emscripten_resolve_path(buf, NULL, filename, sizeof buf); struct dso* p = find_existing(filename); if (p) { onsuccess(user_data, p); From 820805a98871ae43faedc797a5c986b85fe6656d Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Mon, 31 Mar 2025 17:05:45 +0200 Subject: [PATCH 19/58] Call wasmExports._emscripten_resolve_path directly --- src/lib/libdylink.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 26497e1cb54d9..4067ddc480cde 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -1042,7 +1042,9 @@ var LibraryDylink = { } HEAP8[cur] = 0; var libNameC = stringToUTF8OnStack(libName); - var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); + // We use wasmExports["_emscripten_resolve_path"] so we can use this for + // preloading dynamic libraries when runtimeInitialized is false. + var resLibNameC = wasmExports["_emscripten_resolve_path"](buf, rpath, libNameC, bufSize); var foundFile = resLibNameC !== libNameC; libName = UTF8ToString(resLibNameC); stackRestore(origStack); From 105e77140fd6bd3cdbaa205446a1b570425b920f Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Mon, 31 Mar 2025 17:16:12 +0200 Subject: [PATCH 20/58] Tidy up --- src/lib/libdylink.js | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 4067ddc480cde..7f984049ae02e 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -49,45 +49,6 @@ var LibraryDylink = { `, $preloadedWasm: {}, - $locateLibraryFromFS__deps: ['$FS'], - $locateLibraryFromFS: (filename, searchDirs) => { - // Find the library in the filesystem. - // returns null if not found. - if (typeof FS.lookupPath !== 'function') { - // wasmfs does not implement FS.lookupPath - return null; - } - - var candidates = []; - if (filename.charAt(0) === '/') { // abs path - candidates.push(filename); - } else if (searchDirs) { - for (var dir of searchDirs) { - // PATH.join does not work well with symlinks - candidates.push(dir + '/' + filename); - } - } else { - return null; - } - - for (var path of candidates) { - try { - var res = FS.lookupPath(path); - return res.path; - } catch(e) { - // do nothing is file is not found - } - } - - return null; - }, - - $readLibraryFromFS__deps: ['$FS'], - $readLibraryFromFS: (path) => { - var data = FS.readFile(path, {encoding: 'binary'}); - return data; - }, - $replaceORIGIN__deps: ['$PATH'], $replaceORIGIN: (parentLibPath, rpath) => { if (rpath.startsWith('$ORIGIN')) { @@ -999,8 +960,6 @@ var LibraryDylink = { '$asyncLoad', #if FILESYSTEM '$preloadedWasm', - '$locateLibraryFromFS', - '$readLibraryFromFS', '$replaceORIGIN', '_emscripten_resolve_path', '$stackSave', @@ -1115,7 +1074,7 @@ var LibraryDylink = { #if FILESYSTEM if (foundFile) { - var libData = readLibraryFromFS(libName); + var libData = FS.readFile(libName, {encoding: 'binary'}); if (libData) { #if DYLINK_DEBUG dbg(`loaded library from filesystem: ${libName}`); From bbc7be94bd51ec535727bc98541562aca65f10cd Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Mon, 31 Mar 2025 17:51:11 +0200 Subject: [PATCH 21/58] Rename test to test_dlopen_rpath --- test/test_other.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_other.py b/test/test_other.py index 76f011f55bf7c..6647ba6ea042e 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7692,7 +7692,7 @@ def test_ld_library_path(self, args): self.assertContained('Ok', out) @also_with_wasmfs - def test_ld_library_path_dependencies(self): + def test_dlopen_rpath(self): create_file('hello1_dep.c', r''' #include<stdio.h> From c6c5bdc1277985f395ba9fadc8e3dad2bce10e15 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 1 Apr 2025 12:50:09 +0200 Subject: [PATCH 22/58] Fix tests --- src/lib/libdylink.js | 48 ++++++++++++++++++++++----------------- system/lib/libc/dynlink.c | 5 ++++ 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 7f984049ae02e..87570b4f91fe5 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -985,28 +985,34 @@ var LibraryDylink = { #endif #if FILESYSTEM - var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); - var origStack = stackSave(); - var bufSize = 2*255 + 2; - var buf = stackAlloc(bufSize); - var size = 0; - for (var str of runtimePathsAbs) { - size += lengthBytesUTF8(str) + 1; - } - var rpath = stackAlloc(size); - var cur = rpath - for (var str of runtimePathsAbs) { - cur += stringToUTF8(str, cur, size); - HEAP8[cur] = ':'.charCodeAt(0); + var foundFile = false; + if (libName.startsWith("/")) { + try { + FS.lookupPath(libName); + foundFile = true; + } catch(e){} + } else if (runtimeInitialized) { + var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); + var origStack = stackSave(); + var bufSize = 2*255 + 2; + var buf = stackAlloc(bufSize); + var size = 0; + for (var str of runtimePathsAbs) { + size += lengthBytesUTF8(str) + 1; + } + var rpath = stackAlloc(size); + var cur = rpath + for (var str of runtimePathsAbs) { + cur += stringToUTF8(str, cur, size); + HEAP8[cur] = ':'.charCodeAt(0); + } + HEAP8[cur] = 0; + var libNameC = stringToUTF8OnStack(libName); + var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); + var foundFile = resLibNameC !== libNameC; + libName = UTF8ToString(resLibNameC); + stackRestore(origStack); } - HEAP8[cur] = 0; - var libNameC = stringToUTF8OnStack(libName); - // We use wasmExports["_emscripten_resolve_path"] so we can use this for - // preloading dynamic libraries when runtimeInitialized is false. - var resLibNameC = wasmExports["_emscripten_resolve_path"](buf, rpath, libNameC, bufSize); - var foundFile = resLibNameC !== libNameC; - libName = UTF8ToString(resLibNameC); - stackRestore(origStack); #if DYLINK_DEBUG dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); #endif diff --git a/system/lib/libc/dynlink.c b/system/lib/libc/dynlink.c index b594a67c2c2b3..be1ffb21b2bd8 100644 --- a/system/lib/libc/dynlink.c +++ b/system/lib/libc/dynlink.c @@ -490,8 +490,10 @@ static int path_find(const char *name, int ncandidates, const char **candidates, for (int c = 0; c < ncandidates; c ++) { const char* s = candidates[c]; if (s == NULL) { + dbg("Candidate %d is null, skipping\n", c); continue; } + dbg("Candidate %d...\n", c); for (;;) { s += strspn(s, ":\n"); l = strcspn(s, ":\n"); @@ -499,9 +501,12 @@ static int path_find(const char *name, int ncandidates, const char **candidates, if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { dbg("dlopen: path_find: %s", buf); struct stat statbuf; + dbg("Checking file: %s\n", buf); if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + dbg(" .. found\n"); return 0; } + dbg(" .. not found\n"); switch (errno) { case ENOENT: case ENOTDIR: From d03329bb62921904609d8f8beb9f0c5dec34700b Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 1 Apr 2025 12:50:45 +0200 Subject: [PATCH 23/58] Revert codesizes --- test/other/codesize/test_codesize_cxx_ctors1.gzsize | 2 +- test/other/codesize/test_codesize_cxx_ctors1.jssize | 2 +- test/other/codesize/test_codesize_cxx_ctors1.size | 2 +- test/other/codesize/test_codesize_cxx_ctors2.gzsize | 2 +- test/other/codesize/test_codesize_cxx_ctors2.jssize | 2 +- test/other/codesize/test_codesize_cxx_ctors2.size | 2 +- test/other/codesize/test_codesize_cxx_except.gzsize | 2 +- test/other/codesize/test_codesize_cxx_except.jssize | 2 +- test/other/codesize/test_codesize_cxx_except.size | 2 +- test/other/codesize/test_codesize_cxx_except_wasm.gzsize | 2 +- test/other/codesize/test_codesize_cxx_except_wasm.jssize | 2 +- test/other/codesize/test_codesize_cxx_except_wasm.size | 2 +- test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize | 2 +- test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize | 2 +- test/other/codesize/test_codesize_cxx_except_wasm_legacy.size | 2 +- test/other/codesize/test_codesize_cxx_lto.gzsize | 2 +- test/other/codesize/test_codesize_cxx_lto.jssize | 2 +- test/other/codesize/test_codesize_cxx_lto.size | 2 +- test/other/codesize/test_codesize_cxx_mangle.gzsize | 2 +- test/other/codesize/test_codesize_cxx_mangle.jssize | 2 +- test/other/codesize/test_codesize_cxx_mangle.size | 2 +- test/other/codesize/test_codesize_cxx_noexcept.gzsize | 2 +- test/other/codesize/test_codesize_cxx_noexcept.jssize | 2 +- test/other/codesize/test_codesize_cxx_noexcept.size | 2 +- test/other/codesize/test_codesize_cxx_wasmfs.gzsize | 2 +- test/other/codesize/test_codesize_cxx_wasmfs.jssize | 2 +- test/other/codesize/test_codesize_cxx_wasmfs.size | 2 +- test/other/codesize/test_codesize_files_js_fs.gzsize | 2 +- test/other/codesize/test_codesize_files_js_fs.jssize | 2 +- test/other/codesize/test_codesize_files_wasmfs.gzsize | 2 +- test/other/codesize/test_codesize_files_wasmfs.jssize | 2 +- test/other/codesize/test_codesize_hello_O0.gzsize | 2 +- test/other/codesize/test_codesize_hello_O0.jssize | 2 +- test/other/codesize/test_codesize_hello_O0.size | 2 +- test/other/codesize/test_codesize_hello_O1.gzsize | 2 +- test/other/codesize/test_codesize_hello_O1.jssize | 2 +- test/other/codesize/test_codesize_hello_O2.gzsize | 2 +- test/other/codesize/test_codesize_hello_O2.jssize | 2 +- test/other/codesize/test_codesize_hello_O3.gzsize | 2 +- test/other/codesize/test_codesize_hello_O3.jssize | 2 +- test/other/codesize/test_codesize_hello_Os.gzsize | 2 +- test/other/codesize/test_codesize_hello_Os.jssize | 2 +- test/other/codesize/test_codesize_hello_Oz.gzsize | 2 +- test/other/codesize/test_codesize_hello_Oz.jssize | 2 +- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- test/other/codesize/test_codesize_hello_export_nothing.gzsize | 2 +- test/other/codesize/test_codesize_hello_export_nothing.jssize | 2 +- test/other/codesize/test_codesize_hello_wasmfs.gzsize | 2 +- test/other/codesize/test_codesize_hello_wasmfs.jssize | 2 +- test/other/codesize/test_codesize_libcxxabi_message_O3.gzsize | 2 +- test/other/codesize/test_codesize_libcxxabi_message_O3.jssize | 2 +- .../test_codesize_libcxxabi_message_O3_standalone.gzsize | 2 +- .../test_codesize_libcxxabi_message_O3_standalone.jssize | 2 +- test/other/codesize/test_codesize_mem_O3.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_grow.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_grow.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize | 2 +- .../codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize | 2 +- .../codesize/test_codesize_mem_O3_standalone_narg_flto.jssize | 2 +- test/other/codesize/test_codesize_minimal_64.gzsize | 2 +- test/other/codesize/test_codesize_minimal_64.jssize | 2 +- test/other/codesize/test_codesize_minimal_O0.gzsize | 2 +- test/other/codesize/test_codesize_minimal_O0.jssize | 2 +- test/other/codesize/test_codesize_minimal_O1.gzsize | 2 +- test/other/codesize/test_codesize_minimal_O1.jssize | 2 +- test/other/codesize/test_codesize_minimal_O2.gzsize | 2 +- test/other/codesize/test_codesize_minimal_O2.jssize | 2 +- test/other/codesize/test_codesize_minimal_O3.gzsize | 2 +- test/other/codesize/test_codesize_minimal_O3.jssize | 2 +- test/other/codesize/test_codesize_minimal_Os.gzsize | 2 +- test/other/codesize/test_codesize_minimal_Os.jssize | 2 +- test/other/codesize/test_codesize_minimal_Oz-ctors.gzsize | 2 +- test/other/codesize/test_codesize_minimal_Oz-ctors.jssize | 2 +- test/other/codesize/test_codesize_minimal_Oz.gzsize | 2 +- test/other/codesize/test_codesize_minimal_Oz.jssize | 2 +- test/other/codesize/test_codesize_minimal_esm.gzsize | 2 +- test/other/codesize/test_codesize_minimal_esm.jssize | 2 +- test/other/codesize/test_codesize_minimal_pthreads.gzsize | 2 +- test/other/codesize/test_codesize_minimal_pthreads.jssize | 2 +- test/other/codesize/test_codesize_minimal_wasmfs.gzsize | 2 +- test/other/codesize/test_codesize_minimal_wasmfs.jssize | 2 +- 90 files changed, 90 insertions(+), 90 deletions(-) diff --git a/test/other/codesize/test_codesize_cxx_ctors1.gzsize b/test/other/codesize/test_codesize_cxx_ctors1.gzsize index e3db4d209f412..d8f3dc7482479 100644 --- a/test/other/codesize/test_codesize_cxx_ctors1.gzsize +++ b/test/other/codesize/test_codesize_cxx_ctors1.gzsize @@ -1 +1 @@ -8240 +8232 diff --git a/test/other/codesize/test_codesize_cxx_ctors1.jssize b/test/other/codesize/test_codesize_cxx_ctors1.jssize index f2f22de47dce3..27c796a162b97 100644 --- a/test/other/codesize/test_codesize_cxx_ctors1.jssize +++ b/test/other/codesize/test_codesize_cxx_ctors1.jssize @@ -1 +1 @@ -19983 +19993 diff --git a/test/other/codesize/test_codesize_cxx_ctors1.size b/test/other/codesize/test_codesize_cxx_ctors1.size index 9bec2937b57fa..9863b896c0d5a 100644 --- a/test/other/codesize/test_codesize_cxx_ctors1.size +++ b/test/other/codesize/test_codesize_cxx_ctors1.size @@ -1 +1 @@ -129166 +129206 diff --git a/test/other/codesize/test_codesize_cxx_ctors2.gzsize b/test/other/codesize/test_codesize_cxx_ctors2.gzsize index 66fa55bcc4460..2b886f8252fa8 100644 --- a/test/other/codesize/test_codesize_cxx_ctors2.gzsize +++ b/test/other/codesize/test_codesize_cxx_ctors2.gzsize @@ -1 +1 @@ -8229 +8221 diff --git a/test/other/codesize/test_codesize_cxx_ctors2.jssize b/test/other/codesize/test_codesize_cxx_ctors2.jssize index fbb5e0a08f958..7d5b516726c18 100644 --- a/test/other/codesize/test_codesize_cxx_ctors2.jssize +++ b/test/other/codesize/test_codesize_cxx_ctors2.jssize @@ -1 +1 @@ -19961 +19971 diff --git a/test/other/codesize/test_codesize_cxx_ctors2.size b/test/other/codesize/test_codesize_cxx_ctors2.size index 55bbf315fb86a..835acf9cccd93 100644 --- a/test/other/codesize/test_codesize_cxx_ctors2.size +++ b/test/other/codesize/test_codesize_cxx_ctors2.size @@ -1 +1 @@ -128578 +128599 diff --git a/test/other/codesize/test_codesize_cxx_except.gzsize b/test/other/codesize/test_codesize_cxx_except.gzsize index abcd8b14f0171..0f05e3f519b14 100644 --- a/test/other/codesize/test_codesize_cxx_except.gzsize +++ b/test/other/codesize/test_codesize_cxx_except.gzsize @@ -1 +1 @@ -9240 +9231 diff --git a/test/other/codesize/test_codesize_cxx_except.jssize b/test/other/codesize/test_codesize_cxx_except.jssize index 5960086d9db02..aa74b4197966a 100644 --- a/test/other/codesize/test_codesize_cxx_except.jssize +++ b/test/other/codesize/test_codesize_cxx_except.jssize @@ -1 +1 @@ -23720 +23730 diff --git a/test/other/codesize/test_codesize_cxx_except.size b/test/other/codesize/test_codesize_cxx_except.size index c1e4ea11dc81f..b52355112c25c 100644 --- a/test/other/codesize/test_codesize_cxx_except.size +++ b/test/other/codesize/test_codesize_cxx_except.size @@ -1 +1 @@ -170787 +170827 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm.gzsize b/test/other/codesize/test_codesize_cxx_except_wasm.gzsize index 50b9644c88713..964a1e5390897 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm.gzsize +++ b/test/other/codesize/test_codesize_cxx_except_wasm.gzsize @@ -1 +1 @@ -8189 +8177 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm.jssize b/test/other/codesize/test_codesize_cxx_except_wasm.jssize index 9301b07db1f5f..e56210bf45015 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm.jssize +++ b/test/other/codesize/test_codesize_cxx_except_wasm.jssize @@ -1 +1 @@ -19875 +19885 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm.size b/test/other/codesize/test_codesize_cxx_except_wasm.size index 8eed18be13dd3..65c93519d4ef8 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm.size +++ b/test/other/codesize/test_codesize_cxx_except_wasm.size @@ -1 +1 @@ -144542 +144582 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize index 50b9644c88713..964a1e5390897 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize +++ b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize @@ -1 +1 @@ -8189 +8177 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize index 9301b07db1f5f..e56210bf45015 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize +++ b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize @@ -1 +1 @@ -19875 +19885 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.size b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.size index 6e92f12fe6389..57ffcc52fadcb 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.size +++ b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.size @@ -1 +1 @@ -142117 +142157 diff --git a/test/other/codesize/test_codesize_cxx_lto.gzsize b/test/other/codesize/test_codesize_cxx_lto.gzsize index 6098d2d252fd2..6f786d398902e 100644 --- a/test/other/codesize/test_codesize_cxx_lto.gzsize +++ b/test/other/codesize/test_codesize_cxx_lto.gzsize @@ -1 +1 @@ -8257 +8245 diff --git a/test/other/codesize/test_codesize_cxx_lto.jssize b/test/other/codesize/test_codesize_cxx_lto.jssize index cc71b3a1e4909..2f8cb06ad1fcd 100644 --- a/test/other/codesize/test_codesize_cxx_lto.jssize +++ b/test/other/codesize/test_codesize_cxx_lto.jssize @@ -1 +1 @@ -20057 +20067 diff --git a/test/other/codesize/test_codesize_cxx_lto.size b/test/other/codesize/test_codesize_cxx_lto.size index 88d6ea82474fa..11625edb7f313 100644 --- a/test/other/codesize/test_codesize_cxx_lto.size +++ b/test/other/codesize/test_codesize_cxx_lto.size @@ -1 +1 @@ -122011 +121939 diff --git a/test/other/codesize/test_codesize_cxx_mangle.gzsize b/test/other/codesize/test_codesize_cxx_mangle.gzsize index c7777890d386d..7f4fc4bd45847 100644 --- a/test/other/codesize/test_codesize_cxx_mangle.gzsize +++ b/test/other/codesize/test_codesize_cxx_mangle.gzsize @@ -1 +1 @@ -9244 +9268 diff --git a/test/other/codesize/test_codesize_cxx_mangle.jssize b/test/other/codesize/test_codesize_cxx_mangle.jssize index 5960086d9db02..fe17b4115c2b8 100644 --- a/test/other/codesize/test_codesize_cxx_mangle.jssize +++ b/test/other/codesize/test_codesize_cxx_mangle.jssize @@ -1 +1 @@ -23720 +23844 diff --git a/test/other/codesize/test_codesize_cxx_mangle.size b/test/other/codesize/test_codesize_cxx_mangle.size index c8f3a8138f92e..1f389fe78d47f 100644 --- a/test/other/codesize/test_codesize_cxx_mangle.size +++ b/test/other/codesize/test_codesize_cxx_mangle.size @@ -1 +1 @@ -232560 +232604 diff --git a/test/other/codesize/test_codesize_cxx_noexcept.gzsize b/test/other/codesize/test_codesize_cxx_noexcept.gzsize index e3db4d209f412..d8f3dc7482479 100644 --- a/test/other/codesize/test_codesize_cxx_noexcept.gzsize +++ b/test/other/codesize/test_codesize_cxx_noexcept.gzsize @@ -1 +1 @@ -8240 +8232 diff --git a/test/other/codesize/test_codesize_cxx_noexcept.jssize b/test/other/codesize/test_codesize_cxx_noexcept.jssize index f2f22de47dce3..27c796a162b97 100644 --- a/test/other/codesize/test_codesize_cxx_noexcept.jssize +++ b/test/other/codesize/test_codesize_cxx_noexcept.jssize @@ -1 +1 @@ -19983 +19993 diff --git a/test/other/codesize/test_codesize_cxx_noexcept.size b/test/other/codesize/test_codesize_cxx_noexcept.size index a6f187935bad9..38b37880347b1 100644 --- a/test/other/codesize/test_codesize_cxx_noexcept.size +++ b/test/other/codesize/test_codesize_cxx_noexcept.size @@ -1 +1 @@ -131729 +131769 diff --git a/test/other/codesize/test_codesize_cxx_wasmfs.gzsize b/test/other/codesize/test_codesize_cxx_wasmfs.gzsize index 7a267b792c773..ce6800c84df61 100644 --- a/test/other/codesize/test_codesize_cxx_wasmfs.gzsize +++ b/test/other/codesize/test_codesize_cxx_wasmfs.gzsize @@ -1 +1 @@ -3469 +3440 diff --git a/test/other/codesize/test_codesize_cxx_wasmfs.jssize b/test/other/codesize/test_codesize_cxx_wasmfs.jssize index da1daa6ddb13c..cbe97cf27b005 100644 --- a/test/other/codesize/test_codesize_cxx_wasmfs.jssize +++ b/test/other/codesize/test_codesize_cxx_wasmfs.jssize @@ -1 +1 @@ -7483 +7429 diff --git a/test/other/codesize/test_codesize_cxx_wasmfs.size b/test/other/codesize/test_codesize_cxx_wasmfs.size index 686931801bde3..756e251803e5c 100644 --- a/test/other/codesize/test_codesize_cxx_wasmfs.size +++ b/test/other/codesize/test_codesize_cxx_wasmfs.size @@ -1 +1 @@ -169089 +169129 diff --git a/test/other/codesize/test_codesize_files_js_fs.gzsize b/test/other/codesize/test_codesize_files_js_fs.gzsize index c3c69e6e707b3..8b822a3f7bf83 100644 --- a/test/other/codesize/test_codesize_files_js_fs.gzsize +++ b/test/other/codesize/test_codesize_files_js_fs.gzsize @@ -1 +1 @@ -7553 +7542 diff --git a/test/other/codesize/test_codesize_files_js_fs.jssize b/test/other/codesize/test_codesize_files_js_fs.jssize index f0166e8b0df01..69a8a69a318fa 100644 --- a/test/other/codesize/test_codesize_files_js_fs.jssize +++ b/test/other/codesize/test_codesize_files_js_fs.jssize @@ -1 +1 @@ -18529 +18551 diff --git a/test/other/codesize/test_codesize_files_wasmfs.gzsize b/test/other/codesize/test_codesize_files_wasmfs.gzsize index 8361266fd249f..1f62501d6c9d3 100644 --- a/test/other/codesize/test_codesize_files_wasmfs.gzsize +++ b/test/other/codesize/test_codesize_files_wasmfs.gzsize @@ -1 +1 @@ -2710 +2682 diff --git a/test/other/codesize/test_codesize_files_wasmfs.jssize b/test/other/codesize/test_codesize_files_wasmfs.jssize index 201d6812c5259..da710c1aba587 100644 --- a/test/other/codesize/test_codesize_files_wasmfs.jssize +++ b/test/other/codesize/test_codesize_files_wasmfs.jssize @@ -1 +1 @@ -5794 +5753 diff --git a/test/other/codesize/test_codesize_hello_O0.gzsize b/test/other/codesize/test_codesize_hello_O0.gzsize index 2d831067ed5e3..b59bd0a89971a 100644 --- a/test/other/codesize/test_codesize_hello_O0.gzsize +++ b/test/other/codesize/test_codesize_hello_O0.gzsize @@ -1 +1 @@ -7984 +7940 diff --git a/test/other/codesize/test_codesize_hello_O0.jssize b/test/other/codesize/test_codesize_hello_O0.jssize index 93301a1e5cb73..d90ba01dfb58c 100644 --- a/test/other/codesize/test_codesize_hello_O0.jssize +++ b/test/other/codesize/test_codesize_hello_O0.jssize @@ -1 +1 @@ -21327 +21295 diff --git a/test/other/codesize/test_codesize_hello_O0.size b/test/other/codesize/test_codesize_hello_O0.size index c55377b036b99..4ed4cbb4a695f 100644 --- a/test/other/codesize/test_codesize_hello_O0.size +++ b/test/other/codesize/test_codesize_hello_O0.size @@ -1 +1 @@ -15105 +15170 diff --git a/test/other/codesize/test_codesize_hello_O1.gzsize b/test/other/codesize/test_codesize_hello_O1.gzsize index e2c12dfcdca3e..efbf27c074661 100644 --- a/test/other/codesize/test_codesize_hello_O1.gzsize +++ b/test/other/codesize/test_codesize_hello_O1.gzsize @@ -1 +1 @@ -2577 +2547 diff --git a/test/other/codesize/test_codesize_hello_O1.jssize b/test/other/codesize/test_codesize_hello_O1.jssize index 9444a45e4e809..0590e000d1be1 100644 --- a/test/other/codesize/test_codesize_hello_O1.jssize +++ b/test/other/codesize/test_codesize_hello_O1.jssize @@ -1 +1 @@ -6633 +6584 diff --git a/test/other/codesize/test_codesize_hello_O2.gzsize b/test/other/codesize/test_codesize_hello_O2.gzsize index 150b7eab65e7a..6230c73f166e0 100644 --- a/test/other/codesize/test_codesize_hello_O2.gzsize +++ b/test/other/codesize/test_codesize_hello_O2.gzsize @@ -1 +1 @@ -2231 +2204 diff --git a/test/other/codesize/test_codesize_hello_O2.jssize b/test/other/codesize/test_codesize_hello_O2.jssize index 98f966d4bcf90..42e82cc24d931 100644 --- a/test/other/codesize/test_codesize_hello_O2.jssize +++ b/test/other/codesize/test_codesize_hello_O2.jssize @@ -1 +1 @@ -4587 +4546 diff --git a/test/other/codesize/test_codesize_hello_O3.gzsize b/test/other/codesize/test_codesize_hello_O3.gzsize index b3c27164e383f..1ff3df5453eed 100644 --- a/test/other/codesize/test_codesize_hello_O3.gzsize +++ b/test/other/codesize/test_codesize_hello_O3.gzsize @@ -1 +1 @@ -2189 +2162 diff --git a/test/other/codesize/test_codesize_hello_O3.jssize b/test/other/codesize/test_codesize_hello_O3.jssize index e6bb77876d21f..4a4c5f9fbad97 100644 --- a/test/other/codesize/test_codesize_hello_O3.jssize +++ b/test/other/codesize/test_codesize_hello_O3.jssize @@ -1 +1 @@ -4529 +4488 diff --git a/test/other/codesize/test_codesize_hello_Os.gzsize b/test/other/codesize/test_codesize_hello_Os.gzsize index b3c27164e383f..1ff3df5453eed 100644 --- a/test/other/codesize/test_codesize_hello_Os.gzsize +++ b/test/other/codesize/test_codesize_hello_Os.gzsize @@ -1 +1 @@ -2189 +2162 diff --git a/test/other/codesize/test_codesize_hello_Os.jssize b/test/other/codesize/test_codesize_hello_Os.jssize index e6bb77876d21f..4a4c5f9fbad97 100644 --- a/test/other/codesize/test_codesize_hello_Os.jssize +++ b/test/other/codesize/test_codesize_hello_Os.jssize @@ -1 +1 @@ -4529 +4488 diff --git a/test/other/codesize/test_codesize_hello_Oz.gzsize b/test/other/codesize/test_codesize_hello_Oz.gzsize index b3c27164e383f..1ff3df5453eed 100644 --- a/test/other/codesize/test_codesize_hello_Oz.gzsize +++ b/test/other/codesize/test_codesize_hello_Oz.gzsize @@ -1 +1 @@ -2189 +2162 diff --git a/test/other/codesize/test_codesize_hello_Oz.jssize b/test/other/codesize/test_codesize_hello_Oz.jssize index e6bb77876d21f..4a4c5f9fbad97 100644 --- a/test/other/codesize/test_codesize_hello_Oz.jssize +++ b/test/other/codesize/test_codesize_hello_Oz.jssize @@ -1 +1 @@ -4529 +4488 diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index 48f2b41978d7b..3fb524c7bdfc3 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11089 +5860 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index d066a1c62bc9e..9ccb3323f6fac 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -25945 +12839 diff --git a/test/other/codesize/test_codesize_hello_export_nothing.gzsize b/test/other/codesize/test_codesize_hello_export_nothing.gzsize index b67470f1dcac7..239cbd5e3488f 100644 --- a/test/other/codesize/test_codesize_hello_export_nothing.gzsize +++ b/test/other/codesize/test_codesize_hello_export_nothing.gzsize @@ -1 +1 @@ -1600 +1577 diff --git a/test/other/codesize/test_codesize_hello_export_nothing.jssize b/test/other/codesize/test_codesize_hello_export_nothing.jssize index a82b2ee2a7015..9867a63213fcc 100644 --- a/test/other/codesize/test_codesize_hello_export_nothing.jssize +++ b/test/other/codesize/test_codesize_hello_export_nothing.jssize @@ -1 +1 @@ -3458 +3419 diff --git a/test/other/codesize/test_codesize_hello_wasmfs.gzsize b/test/other/codesize/test_codesize_hello_wasmfs.gzsize index b3c27164e383f..1ff3df5453eed 100644 --- a/test/other/codesize/test_codesize_hello_wasmfs.gzsize +++ b/test/other/codesize/test_codesize_hello_wasmfs.gzsize @@ -1 +1 @@ -2189 +2162 diff --git a/test/other/codesize/test_codesize_hello_wasmfs.jssize b/test/other/codesize/test_codesize_hello_wasmfs.jssize index e6bb77876d21f..4a4c5f9fbad97 100644 --- a/test/other/codesize/test_codesize_hello_wasmfs.jssize +++ b/test/other/codesize/test_codesize_hello_wasmfs.jssize @@ -1 +1 @@ -4529 +4488 diff --git a/test/other/codesize/test_codesize_libcxxabi_message_O3.gzsize b/test/other/codesize/test_codesize_libcxxabi_message_O3.gzsize index 2b8bb9e2cd8de..ca06b0eafbbf3 100644 --- a/test/other/codesize/test_codesize_libcxxabi_message_O3.gzsize +++ b/test/other/codesize/test_codesize_libcxxabi_message_O3.gzsize @@ -1 +1 @@ -1787 +1761 diff --git a/test/other/codesize/test_codesize_libcxxabi_message_O3.jssize b/test/other/codesize/test_codesize_libcxxabi_message_O3.jssize index e953d33731a03..940846629fe66 100644 --- a/test/other/codesize/test_codesize_libcxxabi_message_O3.jssize +++ b/test/other/codesize/test_codesize_libcxxabi_message_O3.jssize @@ -1 +1 @@ -3812 +3773 diff --git a/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.gzsize b/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.gzsize index c97f63c6d2ed8..93752caf01bd5 100644 --- a/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.gzsize +++ b/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.gzsize @@ -1 +1 @@ -1825 +1798 diff --git a/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.jssize b/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.jssize index 5c2649e45afaf..069ccfea1e738 100644 --- a/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.jssize +++ b/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.jssize @@ -1 +1 @@ -3855 +3816 diff --git a/test/other/codesize/test_codesize_mem_O3.gzsize b/test/other/codesize/test_codesize_mem_O3.gzsize index 828519819fadc..37e23e5ef7eee 100644 --- a/test/other/codesize/test_codesize_mem_O3.gzsize +++ b/test/other/codesize/test_codesize_mem_O3.gzsize @@ -1 +1 @@ -2241 +2211 diff --git a/test/other/codesize/test_codesize_mem_O3.jssize b/test/other/codesize/test_codesize_mem_O3.jssize index e1d7a339108ea..ff84458304aa8 100644 --- a/test/other/codesize/test_codesize_mem_O3.jssize +++ b/test/other/codesize/test_codesize_mem_O3.jssize @@ -1 +1 @@ -4697 +4644 diff --git a/test/other/codesize/test_codesize_mem_O3_grow.gzsize b/test/other/codesize/test_codesize_mem_O3_grow.gzsize index bb74fd5213aae..9174391f5931e 100644 --- a/test/other/codesize/test_codesize_mem_O3_grow.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_grow.gzsize @@ -1 +1 @@ -2390 +2358 diff --git a/test/other/codesize/test_codesize_mem_O3_grow.jssize b/test/other/codesize/test_codesize_mem_O3_grow.jssize index b57a54bac2f42..a635065fa4aa4 100644 --- a/test/other/codesize/test_codesize_mem_O3_grow.jssize +++ b/test/other/codesize/test_codesize_mem_O3_grow.jssize @@ -1 +1 @@ -4981 +4928 diff --git a/test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize b/test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize index cfd0f983d1835..b742f79e29933 100644 --- a/test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize @@ -1 +1 @@ -2086 +2058 diff --git a/test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize b/test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize index 04ce7441022ae..cbc92e3811d9b 100644 --- a/test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize +++ b/test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize @@ -1 +1 @@ -4392 +4341 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone.gzsize b/test/other/codesize/test_codesize_mem_O3_standalone.gzsize index e83bd430367e6..b39a36a7c18b4 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_standalone.gzsize @@ -1 +1 @@ -2046 +2018 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone.jssize b/test/other/codesize/test_codesize_mem_O3_standalone.jssize index d597259861b18..d99ef68f083f3 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone.jssize +++ b/test/other/codesize/test_codesize_mem_O3_standalone.jssize @@ -1 +1 @@ -4324 +4273 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize b/test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize index 179dea5c50051..f6f19007d10bc 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize @@ -1 +1 @@ -1818 +1793 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize b/test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize index ac90f94ef85e1..60a2cc58753fa 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize @@ -1 +1 @@ -3868 +3829 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize b/test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize index c97f63c6d2ed8..93752caf01bd5 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize @@ -1 +1 @@ -1825 +1798 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize b/test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize index 5c2649e45afaf..069ccfea1e738 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize @@ -1 +1 @@ -3855 +3816 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize b/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize index c97f63c6d2ed8..93752caf01bd5 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize @@ -1 +1 @@ -1825 +1798 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.jssize b/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.jssize index 5c2649e45afaf..069ccfea1e738 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.jssize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.jssize @@ -1 +1 @@ -3855 +3816 diff --git a/test/other/codesize/test_codesize_minimal_64.gzsize b/test/other/codesize/test_codesize_minimal_64.gzsize index 85ce1508b00ad..fe2568ccc291f 100644 --- a/test/other/codesize/test_codesize_minimal_64.gzsize +++ b/test/other/codesize/test_codesize_minimal_64.gzsize @@ -1 +1 @@ -1332 +1317 diff --git a/test/other/codesize/test_codesize_minimal_64.jssize b/test/other/codesize/test_codesize_minimal_64.jssize index 681f6fefb05e3..024c51cbaff52 100644 --- a/test/other/codesize/test_codesize_minimal_64.jssize +++ b/test/other/codesize/test_codesize_minimal_64.jssize @@ -1 +1 @@ -2814 +2775 diff --git a/test/other/codesize/test_codesize_minimal_O0.gzsize b/test/other/codesize/test_codesize_minimal_O0.gzsize index 25aad289ec2a8..3352be8311244 100644 --- a/test/other/codesize/test_codesize_minimal_O0.gzsize +++ b/test/other/codesize/test_codesize_minimal_O0.gzsize @@ -1 +1 @@ -6330 +6284 diff --git a/test/other/codesize/test_codesize_minimal_O0.jssize b/test/other/codesize/test_codesize_minimal_O0.jssize index 3c0d84cf62dfe..94f278be21096 100644 --- a/test/other/codesize/test_codesize_minimal_O0.jssize +++ b/test/other/codesize/test_codesize_minimal_O0.jssize @@ -1 +1 @@ -16673 +16651 diff --git a/test/other/codesize/test_codesize_minimal_O1.gzsize b/test/other/codesize/test_codesize_minimal_O1.gzsize index a11d586ce91d1..1eea322546e5a 100644 --- a/test/other/codesize/test_codesize_minimal_O1.gzsize +++ b/test/other/codesize/test_codesize_minimal_O1.gzsize @@ -1 +1 @@ -1407 +1381 diff --git a/test/other/codesize/test_codesize_minimal_O1.jssize b/test/other/codesize/test_codesize_minimal_O1.jssize index c0fac8d63000c..c989d24ff3203 100644 --- a/test/other/codesize/test_codesize_minimal_O1.jssize +++ b/test/other/codesize/test_codesize_minimal_O1.jssize @@ -1 +1 @@ -3287 +3240 diff --git a/test/other/codesize/test_codesize_minimal_O2.gzsize b/test/other/codesize/test_codesize_minimal_O2.gzsize index 88a90959dc27c..23ea2188912c0 100644 --- a/test/other/codesize/test_codesize_minimal_O2.gzsize +++ b/test/other/codesize/test_codesize_minimal_O2.gzsize @@ -1 +1 @@ -1272 +1247 diff --git a/test/other/codesize/test_codesize_minimal_O2.jssize b/test/other/codesize/test_codesize_minimal_O2.jssize index e075ec72ad62c..6357d643027cd 100644 --- a/test/other/codesize/test_codesize_minimal_O2.jssize +++ b/test/other/codesize/test_codesize_minimal_O2.jssize @@ -1 +1 @@ -2561 +2522 diff --git a/test/other/codesize/test_codesize_minimal_O3.gzsize b/test/other/codesize/test_codesize_minimal_O3.gzsize index 7b6369b1040ed..1f8248ceace7b 100644 --- a/test/other/codesize/test_codesize_minimal_O3.gzsize +++ b/test/other/codesize/test_codesize_minimal_O3.gzsize @@ -1 +1 @@ -1237 +1212 diff --git a/test/other/codesize/test_codesize_minimal_O3.jssize b/test/other/codesize/test_codesize_minimal_O3.jssize index cc52cd5075d29..1717fe9e7fe81 100644 --- a/test/other/codesize/test_codesize_minimal_O3.jssize +++ b/test/other/codesize/test_codesize_minimal_O3.jssize @@ -1 +1 @@ -2511 +2472 diff --git a/test/other/codesize/test_codesize_minimal_Os.gzsize b/test/other/codesize/test_codesize_minimal_Os.gzsize index 7b6369b1040ed..1f8248ceace7b 100644 --- a/test/other/codesize/test_codesize_minimal_Os.gzsize +++ b/test/other/codesize/test_codesize_minimal_Os.gzsize @@ -1 +1 @@ -1237 +1212 diff --git a/test/other/codesize/test_codesize_minimal_Os.jssize b/test/other/codesize/test_codesize_minimal_Os.jssize index cc52cd5075d29..1717fe9e7fe81 100644 --- a/test/other/codesize/test_codesize_minimal_Os.jssize +++ b/test/other/codesize/test_codesize_minimal_Os.jssize @@ -1 +1 @@ -2511 +2472 diff --git a/test/other/codesize/test_codesize_minimal_Oz-ctors.gzsize b/test/other/codesize/test_codesize_minimal_Oz-ctors.gzsize index 9d63033fa51d4..34a5f9bcac300 100644 --- a/test/other/codesize/test_codesize_minimal_Oz-ctors.gzsize +++ b/test/other/codesize/test_codesize_minimal_Oz-ctors.gzsize @@ -1 +1 @@ -1222 +1197 diff --git a/test/other/codesize/test_codesize_minimal_Oz-ctors.jssize b/test/other/codesize/test_codesize_minimal_Oz-ctors.jssize index bf6937821e4d1..0b0d24a555ebb 100644 --- a/test/other/codesize/test_codesize_minimal_Oz-ctors.jssize +++ b/test/other/codesize/test_codesize_minimal_Oz-ctors.jssize @@ -1 +1 @@ -2490 +2451 diff --git a/test/other/codesize/test_codesize_minimal_Oz.gzsize b/test/other/codesize/test_codesize_minimal_Oz.gzsize index 7b6369b1040ed..1f8248ceace7b 100644 --- a/test/other/codesize/test_codesize_minimal_Oz.gzsize +++ b/test/other/codesize/test_codesize_minimal_Oz.gzsize @@ -1 +1 @@ -1237 +1212 diff --git a/test/other/codesize/test_codesize_minimal_Oz.jssize b/test/other/codesize/test_codesize_minimal_Oz.jssize index cc52cd5075d29..1717fe9e7fe81 100644 --- a/test/other/codesize/test_codesize_minimal_Oz.jssize +++ b/test/other/codesize/test_codesize_minimal_Oz.jssize @@ -1 +1 @@ -2511 +2472 diff --git a/test/other/codesize/test_codesize_minimal_esm.gzsize b/test/other/codesize/test_codesize_minimal_esm.gzsize index 06415b870d0fc..ed45f450e2506 100644 --- a/test/other/codesize/test_codesize_minimal_esm.gzsize +++ b/test/other/codesize/test_codesize_minimal_esm.gzsize @@ -1 +1 @@ -1437 +1404 diff --git a/test/other/codesize/test_codesize_minimal_esm.jssize b/test/other/codesize/test_codesize_minimal_esm.jssize index 4448785bdb2ae..9b0efd1d1a0ec 100644 --- a/test/other/codesize/test_codesize_minimal_esm.jssize +++ b/test/other/codesize/test_codesize_minimal_esm.jssize @@ -1 +1 @@ -2982 +2928 diff --git a/test/other/codesize/test_codesize_minimal_pthreads.gzsize b/test/other/codesize/test_codesize_minimal_pthreads.gzsize index df9ce788b35f2..7a4e7818cfbdd 100644 --- a/test/other/codesize/test_codesize_minimal_pthreads.gzsize +++ b/test/other/codesize/test_codesize_minimal_pthreads.gzsize @@ -1 +1 @@ -4054 +4045 diff --git a/test/other/codesize/test_codesize_minimal_pthreads.jssize b/test/other/codesize/test_codesize_minimal_pthreads.jssize index e2bf23cff5d1d..e71810d76035f 100644 --- a/test/other/codesize/test_codesize_minimal_pthreads.jssize +++ b/test/other/codesize/test_codesize_minimal_pthreads.jssize @@ -1 +1 @@ -8420 +8382 diff --git a/test/other/codesize/test_codesize_minimal_wasmfs.gzsize b/test/other/codesize/test_codesize_minimal_wasmfs.gzsize index 7b6369b1040ed..1f8248ceace7b 100644 --- a/test/other/codesize/test_codesize_minimal_wasmfs.gzsize +++ b/test/other/codesize/test_codesize_minimal_wasmfs.gzsize @@ -1 +1 @@ -1237 +1212 diff --git a/test/other/codesize/test_codesize_minimal_wasmfs.jssize b/test/other/codesize/test_codesize_minimal_wasmfs.jssize index cc52cd5075d29..1717fe9e7fe81 100644 --- a/test/other/codesize/test_codesize_minimal_wasmfs.jssize +++ b/test/other/codesize/test_codesize_minimal_wasmfs.jssize @@ -1 +1 @@ -2511 +2472 From f2a839fcbe51fbc47d6d0ecec2d680de938c6aa1 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 1 Apr 2025 12:54:18 +0200 Subject: [PATCH 24/58] Remove repeat declarations --- src/lib/libdylink.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 87570b4f91fe5..c0927378c6f60 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -1000,7 +1000,7 @@ var LibraryDylink = { for (var str of runtimePathsAbs) { size += lengthBytesUTF8(str) + 1; } - var rpath = stackAlloc(size); + rpath = stackAlloc(size); var cur = rpath for (var str of runtimePathsAbs) { cur += stringToUTF8(str, cur, size); @@ -1009,7 +1009,7 @@ var LibraryDylink = { HEAP8[cur] = 0; var libNameC = stringToUTF8OnStack(libName); var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); - var foundFile = resLibNameC !== libNameC; + foundFile = resLibNameC !== libNameC; libName = UTF8ToString(resLibNameC); stackRestore(origStack); } From 676e156bb011e1de56f46588f987c6ada56f9bcb Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 1 Apr 2025 13:10:50 +0200 Subject: [PATCH 25/58] Add SUPPORT_RPATH setting --- src/lib/libdylink.js | 6 ++++-- src/settings.js | 4 ++++ test/test_other.py | 2 +- tools/settings.py | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index c0927378c6f60..1ceeda42c6096 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -960,6 +960,8 @@ var LibraryDylink = { '$asyncLoad', #if FILESYSTEM '$preloadedWasm', +#endif +#if FILESYSTEM && SUPPORT_RPATH '$replaceORIGIN', '_emscripten_resolve_path', '$stackSave', @@ -984,7 +986,7 @@ var LibraryDylink = { dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); #endif -#if FILESYSTEM +#if FILESYSTEM && SUPPORT_RPATH var foundFile = false; if (libName.startsWith("/")) { try { @@ -1078,7 +1080,7 @@ var LibraryDylink = { } } -#if FILESYSTEM +#if FILESYSTEM && SUPPORT_RPATH if (foundFile) { var libData = FS.readFile(libName, {encoding: 'binary'}); if (libData) { diff --git a/src/settings.js b/src/settings.js index e14bfc4bb997b..74f20e6dec974 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1135,6 +1135,10 @@ var MAIN_MODULE = 0; // [compile+link] var SIDE_MODULE = 0; +// Include RPATH support. +// [link] +var SUPPORT_RPATH = 0; + // Deprecated, list shared libraries directly on the command line instead. // [link] // [deprecated] diff --git a/test/test_other.py b/test/test_other.py index 6647ba6ea042e..818af3c894c79 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7806,7 +7806,7 @@ def _build(rpath_flag): self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', '--embed-file', 'hello1.wasm@/usr/lib/libhello1.wasm', '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/subdir/libhello1_dep.so', - 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', + 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', '-sSUPPORT_RPATH', '-L./subdir', '-lhello1_dep']) # case 1) without rpath: fail to locate the library diff --git a/tools/settings.py b/tools/settings.py index 8970cff20e7b4..2e1576c4962f9 100644 --- a/tools/settings.py +++ b/tools/settings.py @@ -74,6 +74,7 @@ 'PTHREAD_POOL_SIZE_STRICT', 'PTHREAD_POOL_DELAY_LOAD', 'DEFAULT_PTHREAD_STACK_SIZE', + 'SUPPORT_RPATH', } # Subset of settings that apply at compile time. From 8edc342b7fc25972d7f7c22f34ef4ee4fb2f07ef Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 1 Apr 2025 14:43:44 +0200 Subject: [PATCH 26/58] Update settings_reference.rst --- site/source/docs/tools_reference/settings_reference.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/site/source/docs/tools_reference/settings_reference.rst b/site/source/docs/tools_reference/settings_reference.rst index 49c2ab4204cb4..fec5b8b95ca2d 100644 --- a/site/source/docs/tools_reference/settings_reference.rst +++ b/site/source/docs/tools_reference/settings_reference.rst @@ -1667,6 +1667,15 @@ Corresponds to MAIN_MODULE (also supports modes 1 and 2) Default value: 0 +.. _support_rpath: + +SUPPORT_RPATH +============= + +Include RPATH support. + +Default value: 0 + .. _runtime_linked_libs: RUNTIME_LINKED_LIBS From 0895d17555eacd6b91e6ebd0b9131efd8db989b5 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 1 Apr 2025 14:49:27 +0200 Subject: [PATCH 27/58] Fix test --- test/test_other.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index 818af3c894c79..106cd2034d163 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7692,7 +7692,7 @@ def test_ld_library_path(self, args): self.assertContained('Ok', out) @also_with_wasmfs - def test_dlopen_rpath(self): + def test_dlopen_library_path(self): create_file('hello1_dep.c', r''' #include<stdio.h> @@ -7745,16 +7745,17 @@ def test_dlopen_rpath(self): self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE']) self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so']) self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', - '--embed-file', 'hello1.wasm@/libhello1.wasm', + '--embed-file', 'hello1.wasm@/lib/libhello1.wasm', '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/libhello1_dep.so', - 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', + 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', '-sSUPPORT_RPATH', '-L./subdir', '-lhello1_dep', '--pre-js', 'pre.js']) out = self.run_js('main.js') self.assertContained('Hello1', out) self.assertContained('Hello1_2', out) self.assertContained('Ok', out) - def test_rpath_dependencies(self): + @also_with_wasmfs + def test_dlopen_rpath(self): create_file('hello1_dep.c', r''' #include<stdio.h> From 0848d770135a27e5ee5d8a6ca8e453f263b2a553 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 15:11:28 +0200 Subject: [PATCH 28/58] Fix again --- system/lib/libc/dynlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/lib/libc/dynlink.c b/system/lib/libc/dynlink.c index be1ffb21b2bd8..ff9c7b2d48571 100644 --- a/system/lib/libc/dynlink.c +++ b/system/lib/libc/dynlink.c @@ -532,7 +532,7 @@ const char* _emscripten_resolve_path(char* buf, const char* rpath, const char* f const char* env_path = getenv("LD_LIBRARY_PATH"); int ncandidates = 2; const char* candidates[2] = {env_path, rpath}; - if (env_path && path_find(file, ncandidates, candidates, buf, buflen) == 0) { + if (path_find(file, ncandidates, candidates, buf, buflen) == 0) { dbg("dlopen: found in LD_LIBRARY_PATH: %s", buf); return buf; } From 59875c4d296557df915050e9730c510414cfbe96 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 19:47:10 +0200 Subject: [PATCH 29/58] Remove SUPPORT_RPATH --- site/source/docs/tools_reference/settings_reference.rst | 9 --------- src/lib/libdylink.js | 6 +++--- src/settings.js | 4 ---- test/test_other.py | 4 ++-- tools/settings.py | 1 - 5 files changed, 5 insertions(+), 19 deletions(-) diff --git a/site/source/docs/tools_reference/settings_reference.rst b/site/source/docs/tools_reference/settings_reference.rst index fec5b8b95ca2d..49c2ab4204cb4 100644 --- a/site/source/docs/tools_reference/settings_reference.rst +++ b/site/source/docs/tools_reference/settings_reference.rst @@ -1667,15 +1667,6 @@ Corresponds to MAIN_MODULE (also supports modes 1 and 2) Default value: 0 -.. _support_rpath: - -SUPPORT_RPATH -============= - -Include RPATH support. - -Default value: 0 - .. _runtime_linked_libs: RUNTIME_LINKED_LIBS diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 1ceeda42c6096..2032ac1a10cd7 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -961,7 +961,7 @@ var LibraryDylink = { #if FILESYSTEM '$preloadedWasm', #endif -#if FILESYSTEM && SUPPORT_RPATH +#if FILESYSTEM '$replaceORIGIN', '_emscripten_resolve_path', '$stackSave', @@ -986,7 +986,7 @@ var LibraryDylink = { dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); #endif -#if FILESYSTEM && SUPPORT_RPATH +#if FILESYSTEM var foundFile = false; if (libName.startsWith("/")) { try { @@ -1080,7 +1080,7 @@ var LibraryDylink = { } } -#if FILESYSTEM && SUPPORT_RPATH +#if FILESYSTEM if (foundFile) { var libData = FS.readFile(libName, {encoding: 'binary'}); if (libData) { diff --git a/src/settings.js b/src/settings.js index 74f20e6dec974..e14bfc4bb997b 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1135,10 +1135,6 @@ var MAIN_MODULE = 0; // [compile+link] var SIDE_MODULE = 0; -// Include RPATH support. -// [link] -var SUPPORT_RPATH = 0; - // Deprecated, list shared libraries directly on the command line instead. // [link] // [deprecated] diff --git a/test/test_other.py b/test/test_other.py index df5a92b0a23cf..6bd15a89e3620 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7748,7 +7748,7 @@ def test_dlopen_library_path(self): self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', '--embed-file', 'hello1.wasm@/lib/libhello1.wasm', '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/libhello1_dep.so', - 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', '-sSUPPORT_RPATH', + 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', '-L./subdir', '-lhello1_dep', '--pre-js', 'pre.js']) out = self.run_js('main.js') self.assertContained('Hello1', out) @@ -7808,7 +7808,7 @@ def _build(rpath_flag): self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', '--embed-file', 'hello1.wasm@/usr/lib/libhello1.wasm', '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/subdir/libhello1_dep.so', - 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', '-sSUPPORT_RPATH', + 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', '-L./subdir', '-lhello1_dep']) # case 1) without rpath: fail to locate the library diff --git a/tools/settings.py b/tools/settings.py index 2e1576c4962f9..8970cff20e7b4 100644 --- a/tools/settings.py +++ b/tools/settings.py @@ -74,7 +74,6 @@ 'PTHREAD_POOL_SIZE_STRICT', 'PTHREAD_POOL_DELAY_LOAD', 'DEFAULT_PTHREAD_STACK_SIZE', - 'SUPPORT_RPATH', } # Subset of settings that apply at compile time. From 4e4ab3306a62638648a81066387c40cefa81351b Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 19:59:45 +0200 Subject: [PATCH 30/58] Update codesize --- .../test_codesize_hello_dylink.exports | 1 + .../codesize/test_codesize_hello_dylink.funcs | 20 +++++++++++++++++++ .../test_codesize_hello_dylink.gzsize | 2 +- .../test_codesize_hello_dylink.imports | 5 +++++ .../test_codesize_hello_dylink.jssize | 2 +- .../codesize/test_codesize_hello_dylink.sent | 5 +++++ .../codesize/test_codesize_hello_dylink.size | 2 +- 7 files changed, 34 insertions(+), 3 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.exports b/test/other/codesize/test_codesize_hello_dylink.exports index 99ba54eca755a..e05366dabf28c 100644 --- a/test/other/codesize/test_codesize_hello_dylink.exports +++ b/test/other/codesize/test_codesize_hello_dylink.exports @@ -1,5 +1,6 @@ __wasm_apply_data_relocs __wasm_call_ctors +_emscripten_resolve_path _emscripten_stack_alloc _emscripten_stack_restore calloc diff --git a/test/other/codesize/test_codesize_hello_dylink.funcs b/test/other/codesize/test_codesize_hello_dylink.funcs index 67e34312338f4..91cf45f399fd9 100644 --- a/test/other/codesize/test_codesize_hello_dylink.funcs +++ b/test/other/codesize/test_codesize_hello_dylink.funcs @@ -1,15 +1,35 @@ $__emscripten_stdout_close $__emscripten_stdout_seek $__fwritex +$__memcpy +$__memset $__stdio_write +$__strchrnul $__towrite $__wasm_apply_data_relocs $__wasm_call_ctors $__wasm_start +$_emscripten_resolve_path $_emscripten_stack_alloc $_emscripten_stack_restore $dlcalloc +$dlmalloc $emscripten_stack_get_current +$fmt_fp +$fmt_u +$frexp +$getint $main +$out +$pad +$pop_arg +$pop_arg_long_double +$printf_core $sbrk $setThrew +$sn_write +$strcspn +$strlen +$strspn +$vsnprintf +$wctomb diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index e60a4190c3a72..357429c8907f7 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -5858 +11800 diff --git a/test/other/codesize/test_codesize_hello_dylink.imports b/test/other/codesize/test_codesize_hello_dylink.imports index ed7c6d9be94fb..a183f50451034 100644 --- a/test/other/codesize/test_codesize_hello_dylink.imports +++ b/test/other/codesize/test_codesize_hello_dylink.imports @@ -1,8 +1,13 @@ GOT.mem.__heap_base +GOT.mem.__stack_high +GOT.mem.__stack_low env.__indirect_function_table env.__memory_base env.__stack_pointer +env.__syscall_stat64 env.__table_base env.emscripten_resize_heap env.memory +wasi_snapshot_preview1.environ_get +wasi_snapshot_preview1.environ_sizes_get wasi_snapshot_preview1.fd_write diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index 8562d61863ab1..8c789d48edc34 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -12832 +27782 diff --git a/test/other/codesize/test_codesize_hello_dylink.sent b/test/other/codesize/test_codesize_hello_dylink.sent index 1ca2e37d90365..b09314e54011e 100644 --- a/test/other/codesize/test_codesize_hello_dylink.sent +++ b/test/other/codesize/test_codesize_hello_dylink.sent @@ -1,8 +1,13 @@ __heap_base __indirect_function_table __memory_base +__stack_high +__stack_low __stack_pointer +__syscall_stat64 __table_base emscripten_resize_heap +environ_get +environ_sizes_get fd_write memory diff --git a/test/other/codesize/test_codesize_hello_dylink.size b/test/other/codesize/test_codesize_hello_dylink.size index ac37333bb7dd7..1302218c5dd3f 100644 --- a/test/other/codesize/test_codesize_hello_dylink.size +++ b/test/other/codesize/test_codesize_hello_dylink.size @@ -1 +1 @@ -8176 +18605 From 7e985573503a82d050a483f91b1cfcd6e59ca50d Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 20:04:43 +0200 Subject: [PATCH 31/58] Fix indentation and use withStackSave --- src/lib/libdylink.js | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 2032ac1a10cd7..86999655dc565 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -964,9 +964,8 @@ var LibraryDylink = { #if FILESYSTEM '$replaceORIGIN', '_emscripten_resolve_path', - '$stackSave', + '$withStackSave', '$stackAlloc', - '$stackRestore', '$lengthBytesUTF8', '$stringToUTF8OnStack', '$stringToUTF8', @@ -987,15 +986,15 @@ var LibraryDylink = { #endif #if FILESYSTEM - var foundFile = false; - if (libName.startsWith("/")) { - try { - FS.lookupPath(libName); - foundFile = true; - } catch(e){} - } else if (runtimeInitialized) { - var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); - var origStack = stackSave(); + var foundFile = false; + if (libName.startsWith("/")) { + try { + FS.lookupPath(libName); + foundFile = true; + } catch(e){} + } else if (runtimeInitialized) { + var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); + withStackSave(() => { var bufSize = 2*255 + 2; var buf = stackAlloc(bufSize); var size = 0; @@ -1013,10 +1012,10 @@ var LibraryDylink = { var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); foundFile = resLibNameC !== libNameC; libName = UTF8ToString(resLibNameC); - stackRestore(origStack); - } + }); + } #if DYLINK_DEBUG - dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); + dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); #endif #endif From 6fee8c91d50764b8a8371765cd90914a563fad49 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 20:07:16 +0200 Subject: [PATCH 32/58] Move RPATH lookup below checks for loadedLibsByName and handle --- src/lib/libdylink.js | 65 +++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 86999655dc565..595415e8b562c 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -985,40 +985,6 @@ var LibraryDylink = { dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); #endif -#if FILESYSTEM - var foundFile = false; - if (libName.startsWith("/")) { - try { - FS.lookupPath(libName); - foundFile = true; - } catch(e){} - } else if (runtimeInitialized) { - var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); - withStackSave(() => { - var bufSize = 2*255 + 2; - var buf = stackAlloc(bufSize); - var size = 0; - for (var str of runtimePathsAbs) { - size += lengthBytesUTF8(str) + 1; - } - rpath = stackAlloc(size); - var cur = rpath - for (var str of runtimePathsAbs) { - cur += stringToUTF8(str, cur, size); - HEAP8[cur] = ':'.charCodeAt(0); - } - HEAP8[cur] = 0; - var libNameC = stringToUTF8OnStack(libName); - var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); - foundFile = resLibNameC !== libNameC; - libName = UTF8ToString(resLibNameC); - }); - } -#if DYLINK_DEBUG - dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); -#endif -#endif - // when loadDynamicLibrary did not have flags, libraries were loaded // globally & permanently @@ -1080,6 +1046,37 @@ var LibraryDylink = { } #if FILESYSTEM + var foundFile = false; + if (libName.startsWith("/")) { + try { + FS.lookupPath(libName); + foundFile = true; + } catch(e){} + } else if (runtimeInitialized) { + var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); + withStackSave(() => { + var bufSize = 2*255 + 2; + var buf = stackAlloc(bufSize); + var size = 0; + for (var str of runtimePathsAbs) { + size += lengthBytesUTF8(str) + 1; + } + rpath = stackAlloc(size); + var cur = rpath + for (var str of runtimePathsAbs) { + cur += stringToUTF8(str, cur, size); + HEAP8[cur] = ':'.charCodeAt(0); + } + HEAP8[cur] = 0; + var libNameC = stringToUTF8OnStack(libName); + var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); + foundFile = resLibNameC !== libNameC; + libName = UTF8ToString(resLibNameC); + }); + } +#if DYLINK_DEBUG + dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); +#endif if (foundFile) { var libData = FS.readFile(libName, {encoding: 'binary'}); if (libData) { From 0af5e3c8be074dfd692192c64de8a22a61d69dff Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 20:08:15 +0200 Subject: [PATCH 33/58] Cleanup --- src/lib/libdylink.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 595415e8b562c..f4ef961250c29 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -984,7 +984,6 @@ var LibraryDylink = { dbg(`loadDynamicLibrary: ${libName} handle: ${handle}`); dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); #endif - // when loadDynamicLibrary did not have flags, libraries were loaded // globally & permanently From 4904e56d780519d2042bb0a29abec8a51a8677c4 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 20:10:40 +0200 Subject: [PATCH 34/58] Move rpath to end of arguments list and remove default --- src/lib/libdylink.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index f4ef961250c29..761a428d2e30c 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -900,12 +900,12 @@ var LibraryDylink = { if (flags.loadAsync) { return metadata.neededDynlibs .reduce((chain, dynNeeded) => chain.then(() => - loadDynamicLibrary(dynNeeded, flags, localScope, { parentLibPath: libName, paths: metadata.runtimePaths }) + loadDynamicLibrary(dynNeeded, flags, localScope, undefined, { parentLibPath: libName, paths: metadata.runtimePaths }) ), Promise.resolve()) .then(loadModule); } - metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope, { parentLibPath: libName, paths: metadata.runtimePaths })); + metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope, undefined, { parentLibPath: libName, paths: metadata.runtimePaths })); return loadModule(); }, @@ -979,7 +979,7 @@ var LibraryDylink = { * @param {number=} handle * @param {Object=} localScope */`, - $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, rpath = {parentLibPath: '', paths: []}, handle) { + $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, handle, rpath) { #if DYLINK_DEBUG dbg(`loadDynamicLibrary: ${libName} handle: ${handle}`); dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); @@ -1052,7 +1052,7 @@ var LibraryDylink = { foundFile = true; } catch(e){} } else if (runtimeInitialized) { - var runtimePathsAbs = (rpath.paths || []).map((p) => replaceORIGIN(rpath.parentLibPath, p)); + var runtimePathsAbs = (rpath?.paths || []).map((p) => replaceORIGIN(rpath?.parentLibPath, p)); withStackSave(() => { var bufSize = 2*255 + 2; var buf = stackAlloc(bufSize); @@ -1205,11 +1205,11 @@ var LibraryDylink = { } if (jsflags.loadAsync) { - return loadDynamicLibrary(filename, combinedFlags, localScope, {}, handle); + return loadDynamicLibrary(filename, combinedFlags, localScope, handle); } try { - return loadDynamicLibrary(filename, combinedFlags, localScope, {}, handle) + return loadDynamicLibrary(filename, combinedFlags, localScope, handle) } catch (e) { #if ASSERTIONS err(`Error in loading dynamic library ${filename}: ${e}`); From be222177ad7433a06f93f7f6983059c4d1058f0f Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 23:21:52 +0200 Subject: [PATCH 35/58] Put rpath in flags --- src/lib/libdylink.js | 15 ++++++++------- .../codesize/test_codesize_hello_dylink.gzsize | 2 +- .../codesize/test_codesize_hello_dylink.jssize | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 9e26af20166ec..0291f76e50719 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -901,16 +901,17 @@ var LibraryDylink = { return postInstantiation(module, instance); } + flags = Object.assign(flags, {rpath: { parentLibPath: libName, paths: metadata.runtimePaths }}) // now load needed libraries and the module itself. if (flags.loadAsync) { return metadata.neededDynlibs .reduce((chain, dynNeeded) => chain.then(() => - loadDynamicLibrary(dynNeeded, flags, localScope, undefined, { parentLibPath: libName, paths: metadata.runtimePaths }) + loadDynamicLibrary(dynNeeded, flags, localScope) ), Promise.resolve()) .then(loadModule); } - metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope, undefined, { parentLibPath: libName, paths: metadata.runtimePaths })); + metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope)); return loadModule(); }, @@ -984,7 +985,7 @@ var LibraryDylink = { * @param {number=} handle * @param {Object=} localScope */`, - $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, handle, rpath) { + $loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, handle) { #if DYLINK_DEBUG dbg(`loadDynamicLibrary: ${libName} handle: ${handle}`); dbg(`existing: ${Object.keys(LDSO.loadedLibsByName)}`); @@ -1057,7 +1058,7 @@ var LibraryDylink = { foundFile = true; } catch(e){} } else if (runtimeInitialized) { - var runtimePathsAbs = (rpath?.paths || []).map((p) => replaceORIGIN(rpath?.parentLibPath, p)); + var runtimePathsAbs = (flags.rpath?.paths || []).map((p) => replaceORIGIN(flags.rpath?.parentLibPath, p)); withStackSave(() => { var bufSize = 2*255 + 2; var buf = stackAlloc(bufSize); @@ -1065,15 +1066,15 @@ var LibraryDylink = { for (var str of runtimePathsAbs) { size += lengthBytesUTF8(str) + 1; } - rpath = stackAlloc(size); - var cur = rpath + var rpathC = stackAlloc(size); + var cur = rpathC for (var str of runtimePathsAbs) { cur += stringToUTF8(str, cur, size); HEAP8[cur] = ':'.charCodeAt(0); } HEAP8[cur] = 0; var libNameC = stringToUTF8OnStack(libName); - var resLibNameC = __emscripten_resolve_path(buf, rpath, libNameC, bufSize); + var resLibNameC = __emscripten_resolve_path(buf, rpathC, libNameC, bufSize); foundFile = resLibNameC !== libNameC; libName = UTF8ToString(resLibNameC); }); diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index 357429c8907f7..7995272d11f20 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11800 +11787 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index 8c789d48edc34..e7e22c9a012e8 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -27782 +27848 From e27a006b3d4744575401567ae683fc06d663d0d2 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 23:25:21 +0200 Subject: [PATCH 36/58] parentLibPath ==> parentLibName --- src/lib/libdylink.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 0291f76e50719..c4f53909ea5ea 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -50,10 +50,10 @@ var LibraryDylink = { $preloadedWasm: {}, $replaceORIGIN__deps: ['$PATH'], - $replaceORIGIN: (parentLibPath, rpath) => { + $replaceORIGIN: (parentLibName, rpath) => { if (rpath.startsWith('$ORIGIN')) { // TODO: what to do if we only know the relative path of the file? It will return "." here. - var origin = PATH.dirname(parentLibPath); + var origin = PATH.dirname(parentLibName); return rpath.replace('$ORIGIN', origin); } From caf817c98d3fb0b47eb1308c08cf3230bf229511 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Wed, 2 Apr 2025 23:29:07 +0200 Subject: [PATCH 37/58] Add comment --- src/lib/libdylink.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index c4f53909ea5ea..b80c61b4183ca 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -1060,6 +1060,8 @@ var LibraryDylink = { } else if (runtimeInitialized) { var runtimePathsAbs = (flags.rpath?.paths || []).map((p) => replaceORIGIN(flags.rpath?.parentLibPath, p)); withStackSave(() => { + // In dylink.c we use: `char buf[2*NAME_MAX+2];` and NAME_MAX is 255. + // So we use the same size here. var bufSize = 2*255 + 2; var buf = stackAlloc(bufSize); var size = 0; From 8763702253063ab4d6a0ab2d8de93867586abb1a Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Fri, 4 Apr 2025 11:30:18 +0200 Subject: [PATCH 38/58] Fix wasmfs --- src/lib/libdylink.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index b80c61b4183ca..6578ecdbbf218 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -1053,10 +1053,7 @@ var LibraryDylink = { #if FILESYSTEM var foundFile = false; if (libName.startsWith("/")) { - try { - FS.lookupPath(libName); - foundFile = true; - } catch(e){} + foundFile = !!FS.findObject(libName); } else if (runtimeInitialized) { var runtimePathsAbs = (flags.rpath?.paths || []).map((p) => replaceORIGIN(flags.rpath?.parentLibPath, p)); withStackSave(() => { From bb0240a1c43a2fd1c228652924428f72a615a8a2 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Fri, 4 Apr 2025 13:44:52 +0200 Subject: [PATCH 39/58] Fix in wasmfs --- src/lib/libdylink.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 6578ecdbbf218..c4c1415b98692 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -975,6 +975,11 @@ var LibraryDylink = { '$lengthBytesUTF8', '$stringToUTF8OnStack', '$stringToUTF8', + '$FS', +#if WASMFS + '_wasmfs_identify', + '_wasmfs_read_file', +#endif #endif #if DYNCALLS || !WASM_BIGINT '$registerDynCallSymbols', @@ -1053,7 +1058,15 @@ var LibraryDylink = { #if FILESYSTEM var foundFile = false; if (libName.startsWith("/")) { - foundFile = !!FS.findObject(libName); +#if WASMFS + var result = withStackSave(() => __wasmfs_identify(stringToUTF8OnStack(libName))); + foundFile = result === {{{ cDefs.EEXIST }}}; +#else + try { + FS.lookupPath(libName); + foundFile = true; + } catch (e) {} +#endif } else if (runtimeInitialized) { var runtimePathsAbs = (flags.rpath?.paths || []).map((p) => replaceORIGIN(flags.rpath?.parentLibPath, p)); withStackSave(() => { From 8040eee83c2f2d5f23733c8c71e297a18c000495 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Fri, 4 Apr 2025 15:52:10 +0200 Subject: [PATCH 40/58] Add _emscripten_resolve_path to create_pointer_conversion_wrappers --- tools/emscripten.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/emscripten.py b/tools/emscripten.py index 487f3be660a4f..083a266470eda 100644 --- a/tools/emscripten.py +++ b/tools/emscripten.py @@ -1112,6 +1112,7 @@ def create_pointer_conversion_wrappers(metadata): '_emscripten_set_offscreencanvas_size_on_thread': '_pp__', 'fileno': '_p', '_emscripten_run_callback_on_thread': '_pp_pp', + '_emscripten_resolve_path': 'ppppp', } for function in settings.SIGNATURE_CONVERSIONS: From 80b37636b789ffb4a0ec2149bbcd09e67e38da62 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Fri, 4 Apr 2025 16:09:07 +0200 Subject: [PATCH 41/58] Update codesize --- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index 7995272d11f20..f1098c1a9fca3 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11787 +11793 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index e7e22c9a012e8..be2d383ab4d79 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -27848 +27849 From a52f4a8ae0170f383b4fc2e04c6b0e7b804c7382 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 14:30:59 -0400 Subject: [PATCH 42/58] Rename _emscripten_resolve_path to _emscripten_find_dylib --- src/lib/libdylink.js | 4 ++-- system/lib/libc/dynlink.c | 6 +++--- test/other/codesize/test_codesize_hello_dylink.exports | 2 +- test/other/codesize/test_codesize_hello_dylink.funcs | 2 +- tools/emscripten.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index c4c1415b98692..5444a3bf9f421 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -969,7 +969,7 @@ var LibraryDylink = { #endif #if FILESYSTEM '$replaceORIGIN', - '_emscripten_resolve_path', + '_emscripten_find_dylib', '$withStackSave', '$stackAlloc', '$lengthBytesUTF8', @@ -1086,7 +1086,7 @@ var LibraryDylink = { } HEAP8[cur] = 0; var libNameC = stringToUTF8OnStack(libName); - var resLibNameC = __emscripten_resolve_path(buf, rpathC, libNameC, bufSize); + var resLibNameC = __emscripten_find_dylib(buf, rpathC, libNameC, bufSize); foundFile = resLibNameC !== libNameC; libName = UTF8ToString(resLibNameC); }); diff --git a/system/lib/libc/dynlink.c b/system/lib/libc/dynlink.c index ff9c7b2d48571..b105a08d95212 100644 --- a/system/lib/libc/dynlink.c +++ b/system/lib/libc/dynlink.c @@ -527,7 +527,7 @@ static int path_find(const char *name, int ncandidates, const char **candidates, } // Resolve filename using LD_LIBRARY_PATH -const char* _emscripten_resolve_path(char* buf, const char* rpath, const char* file, size_t buflen) { +const char* _emscripten_find_dylib(char* buf, const char* rpath, const char* file, size_t buflen) { if (!strchr(file, '/')) { const char* env_path = getenv("LD_LIBRARY_PATH"); int ncandidates = 2; @@ -567,7 +567,7 @@ static struct dso* _dlopen(const char* file, int flags) { do_write_lock(); char buf[2*NAME_MAX+2]; - file = _emscripten_resolve_path(buf, NULL, file, sizeof buf); + file = _emscripten_find_dylib(buf, NULL, file, sizeof buf); struct dso* p = find_existing(file); if (p) { @@ -607,7 +607,7 @@ void emscripten_dlopen(const char* filename, int flags, void* user_data, } do_write_lock(); char buf[2*NAME_MAX+2]; - filename = _emscripten_resolve_path(buf, NULL, filename, sizeof buf); + filename = _emscripten_find_dylib(buf, NULL, filename, sizeof buf); struct dso* p = find_existing(filename); if (p) { onsuccess(user_data, p); diff --git a/test/other/codesize/test_codesize_hello_dylink.exports b/test/other/codesize/test_codesize_hello_dylink.exports index e05366dabf28c..ad9fe79a10e50 100644 --- a/test/other/codesize/test_codesize_hello_dylink.exports +++ b/test/other/codesize/test_codesize_hello_dylink.exports @@ -1,6 +1,6 @@ __wasm_apply_data_relocs __wasm_call_ctors -_emscripten_resolve_path +_emscripten_find_dylib _emscripten_stack_alloc _emscripten_stack_restore calloc diff --git a/test/other/codesize/test_codesize_hello_dylink.funcs b/test/other/codesize/test_codesize_hello_dylink.funcs index 91cf45f399fd9..22bdbdc3c939e 100644 --- a/test/other/codesize/test_codesize_hello_dylink.funcs +++ b/test/other/codesize/test_codesize_hello_dylink.funcs @@ -9,7 +9,7 @@ $__towrite $__wasm_apply_data_relocs $__wasm_call_ctors $__wasm_start -$_emscripten_resolve_path +$_emscripten_find_dylib $_emscripten_stack_alloc $_emscripten_stack_restore $dlcalloc diff --git a/tools/emscripten.py b/tools/emscripten.py index 083a266470eda..578f00274425a 100644 --- a/tools/emscripten.py +++ b/tools/emscripten.py @@ -1112,7 +1112,7 @@ def create_pointer_conversion_wrappers(metadata): '_emscripten_set_offscreencanvas_size_on_thread': '_pp__', 'fileno': '_p', '_emscripten_run_callback_on_thread': '_pp_pp', - '_emscripten_resolve_path': 'ppppp', + '_emscripten_find_dylib': 'ppppp', } for function in settings.SIGNATURE_CONVERSIONS: From db81df792e8d72cfa668b52bc26f1a81db241536 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 14:47:29 -0400 Subject: [PATCH 43/58] Factor out findLibraryFS --- src/lib/libdylink.js | 118 ++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 5444a3bf9f421..5c9e6f68c06d3 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -944,6 +944,60 @@ var LibraryDylink = { return dso; }, + $findLibraryFS__deps: [ + '$replaceORIGIN', + '_emscripten_find_dylib', + '$withStackSave', + '$stackAlloc', + '$lengthBytesUTF8', + '$stringToUTF8OnStack', + '$stringToUTF8', + '$FS', +#if WASMFS + '_wasmfs_identify', + '_wasmfs_read_file', +#endif + ], + $findLibraryFS: (libName, rpath) => { + if (libName.startsWith("/")) { +#if WASMFS + var result = withStackSave(() => __wasmfs_identify(stringToUTF8OnStack(libName))); + return result === {{{ cDefs.EEXIST }}} ? libName : undefined; +#else + try { + FS.lookupPath(libName); + return libName; + } catch (e) { + return undefined; + } +#endif + } + if (!runtimeInitialized) { + return undefined; + } + var runtimePathsAbs = (rpath?.paths || []).map((p) => replaceORIGIN(rpath?.parentLibPath, p)); + withStackSave(() => { + // In dylink.c we use: `char buf[2*NAME_MAX+2];` and NAME_MAX is 255. + // So we use the same size here. + var bufSize = 2*255 + 2; + var buf = stackAlloc(bufSize); + var size = 0; + for (var str of runtimePathsAbs) { + size += lengthBytesUTF8(str) + 1; + } + var rpathC = stackAlloc(size); + var cur = rpathC + for (var str of runtimePathsAbs) { + cur += stringToUTF8(str, cur, size); + HEAP8[cur] = ':'.charCodeAt(0); + } + HEAP8[cur] = 0; + var libNameC = stringToUTF8OnStack(libName); + var resLibNameC = __emscripten_find_dylib(buf, rpathC, libNameC, bufSize); + return (resLibNameC !== libNameC) ? UTF8ToString(resLibNameC) : undefined; + }); + } + // loadDynamicLibrary loads dynamic library @ lib URL / path and returns // handle for loaded DSO. // @@ -966,20 +1020,7 @@ var LibraryDylink = { '$asyncLoad', #if FILESYSTEM '$preloadedWasm', -#endif -#if FILESYSTEM - '$replaceORIGIN', - '_emscripten_find_dylib', - '$withStackSave', - '$stackAlloc', - '$lengthBytesUTF8', - '$stringToUTF8OnStack', - '$stringToUTF8', - '$FS', -#if WASMFS - '_wasmfs_identify', - '_wasmfs_read_file', -#endif + '$findLibraryFS', #endif #if DYNCALLS || !WASM_BIGINT '$registerDynCallSymbols', @@ -1056,52 +1097,13 @@ var LibraryDylink = { } #if FILESYSTEM - var foundFile = false; - if (libName.startsWith("/")) { -#if WASMFS - var result = withStackSave(() => __wasmfs_identify(stringToUTF8OnStack(libName))); - foundFile = result === {{{ cDefs.EEXIST }}}; -#else - try { - FS.lookupPath(libName); - foundFile = true; - } catch (e) {} -#endif - } else if (runtimeInitialized) { - var runtimePathsAbs = (flags.rpath?.paths || []).map((p) => replaceORIGIN(flags.rpath?.parentLibPath, p)); - withStackSave(() => { - // In dylink.c we use: `char buf[2*NAME_MAX+2];` and NAME_MAX is 255. - // So we use the same size here. - var bufSize = 2*255 + 2; - var buf = stackAlloc(bufSize); - var size = 0; - for (var str of runtimePathsAbs) { - size += lengthBytesUTF8(str) + 1; - } - var rpathC = stackAlloc(size); - var cur = rpathC - for (var str of runtimePathsAbs) { - cur += stringToUTF8(str, cur, size); - HEAP8[cur] = ':'.charCodeAt(0); - } - HEAP8[cur] = 0; - var libNameC = stringToUTF8OnStack(libName); - var resLibNameC = __emscripten_find_dylib(buf, rpathC, libNameC, bufSize); - foundFile = resLibNameC !== libNameC; - libName = UTF8ToString(resLibNameC); - }); - } -#if DYLINK_DEBUG - dbg(`checking filesystem: ${libName}: ${foundFile ? 'found' : 'not found'}`); -#endif - if (foundFile) { - var libData = FS.readFile(libName, {encoding: 'binary'}); - if (libData) { + var f = findLibraryFS(libName, flags.rpath); #if DYLINK_DEBUG - dbg(`loaded library from filesystem: ${libName}`); + dbg(`checking filesystem: ${libName}: ${f ? 'found' : 'not found'}`); #endif - return flags.loadAsync ? Promise.resolve(libData) : libData; - } + if (f) { + var libData = FS.readFile(f, {encoding: 'binary'}); + return flags.loadAsync ? Promise.resolve(libData) : libData; } #endif From 39d91b4a59c0b18c1be6fdb271e870843774cd9f Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 16:27:24 -0400 Subject: [PATCH 44/58] Fix refactor --- src/lib/libdylink.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 5c9e6f68c06d3..2578a1033efc1 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -976,7 +976,7 @@ var LibraryDylink = { return undefined; } var runtimePathsAbs = (rpath?.paths || []).map((p) => replaceORIGIN(rpath?.parentLibPath, p)); - withStackSave(() => { + return withStackSave(() => { // In dylink.c we use: `char buf[2*NAME_MAX+2];` and NAME_MAX is 255. // So we use the same size here. var bufSize = 2*255 + 2; @@ -996,7 +996,7 @@ var LibraryDylink = { var resLibNameC = __emscripten_find_dylib(buf, rpathC, libNameC, bufSize); return (resLibNameC !== libNameC) ? UTF8ToString(resLibNameC) : undefined; }); - } + }, // loadDynamicLibrary loads dynamic library @ lib URL / path and returns // handle for loaded DSO. From 8e3d3e0479d0e856c817220d66dc5f75a75da2e3 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 16:36:38 -0400 Subject: [PATCH 45/58] Some test cleanup --- test/test_other.py | 116 ++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 87 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index 5e82c5fafbecf..050c4e69aad53 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7595,11 +7595,22 @@ def test_RUNTIME_LINKED_LIBS(self): def test_ld_library_path(self, args): if args: self.setup_node_pthreads() + create_file('hello1_dep.c', r''' +#include<stdio.h> + +void hello1_dep() { + printf("Hello1_dep\n"); + return; +} +''') create_file('hello1.c', r''' #include <stdio.h> +void hello1_dep(); + void hello1() { printf("Hello1\n"); + hello1_dep(); return; } ''') @@ -7679,105 +7690,41 @@ def test_ld_library_path(self, args): return 0; } ''') - self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE'] + args) + os.mkdir('subdir') + self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE']) + self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so'] + args) self.run_process([EMCC, '-o', 'hello2.wasm', 'hello2.c', '-sSIDE_MODULE'] + args) self.run_process([EMCC, '-o', 'hello3.wasm', 'hello3.c', '-sSIDE_MODULE'] + args) self.run_process([EMCC, '-o', 'hello4.wasm', 'hello4.c', '-sSIDE_MODULE'] + args) - self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', + emcc_args = ['--profiling-funcs', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', + '-L./subdir', + '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/libhello1_dep.so', '--embed-file', 'hello1.wasm@/lib/libhello1.wasm', '--embed-file', 'hello2.wasm@/usr/lib/libhello2.wasm', '--embed-file', 'hello3.wasm@/libhello3.wasm', '--embed-file', 'hello4.wasm@/usr/local/lib/libhello4.wasm', 'hello1.wasm', 'hello2.wasm', 'hello3.wasm', 'hello4.wasm', '-sNO_AUTOLOAD_DYLIBS', - '--pre-js', 'pre.js'] + args) - out = self.run_js('main.js') - self.assertContained('Hello1', out) - self.assertContained('Hello2', out) - self.assertContained('Hello3', out) - self.assertContained('Hello4', out) - self.assertContained('Ok', out) - - @also_with_wasmfs - def test_dlopen_library_path(self): - create_file('hello1_dep.c', r''' -#include<stdio.h> - -void hello1_2() { - printf ("Hello1_2\n"); - return; -} -''') - create_file('hello1.c', r''' -#include <stdio.h> - -void hello1_2(); - -void hello1() { - printf ("Hello1\n"); - hello1_2(); - return; -} -''') - create_file('pre.js', r''' -Module.preRun = () => { - ENV['LD_LIBRARY_PATH']='/lib:/usr/lib:/usr/local/lib'; -}; -''') - create_file('main.c', r''' -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <dlfcn.h> - -int main() { - void *h; - void (*f)(); - double (*f2)(double); - - h = dlopen("libhello1.wasm", RTLD_NOW); - assert(h); - f = dlsym(h, "hello1"); - assert(f); - f(); - dlclose(h); - - printf("Ok\n"); - - return 0; -} -''') - os.mkdir('subdir') - self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE']) - self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so']) - self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', - '--embed-file', 'hello1.wasm@/lib/libhello1.wasm', - '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/libhello1_dep.so', - 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', - '-L./subdir', '-lhello1_dep', '--pre-js', 'pre.js']) - out = self.run_js('main.js') - self.assertContained('Hello1', out) - self.assertContained('Hello1_2', out) - self.assertContained('Ok', out) + '--pre-js', 'pre.js'] + args + self.do_runf('main.c', 'Hello1\nHello1_dep\nHello2\nHello3\nHello4\nOk\n', emcc_args=emcc_args) @also_with_wasmfs def test_dlopen_rpath(self): create_file('hello1_dep.c', r''' #include<stdio.h> -void hello1_2() { - printf ("Hello1_2\n"); +void hello1_dep() { + printf ("Hello1_dep\n"); return; } ''') create_file('hello1.c', r''' #include <stdio.h> -void hello1_2(); +void hello1_dep(); void hello1() { printf ("Hello1\n"); - hello1_2(); + hello1_dep(); return; } ''') @@ -7807,26 +7754,21 @@ def test_dlopen_rpath(self): ''') os.mkdir('subdir') - def _build(rpath_flag): + def _build(rpath_flag, expected, **kwds): self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE']) self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so'] + rpath_flag) - self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', + args = ['--profiling-funcs', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', '--embed-file', 'hello1.wasm@/usr/lib/libhello1.wasm', '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/subdir/libhello1_dep.so', 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', - '-L./subdir', '-lhello1_dep']) + '-L./subdir', '-lhello1_dep'] + self.do_runf('main.c', expected, emcc_args=args, **kwds) # case 1) without rpath: fail to locate the library - _build([]) - out = self.run_js('main.js', assert_returncode=NON_ZERO) - self.assertContained(r"no such file or directory, open '.*libhello1_dep\.so'", out, regex=True) + _build([], "no such file or directory, open '.*libhello1_dep\.so'", regex=True, assert_returncode=NON_ZERO) # case 2) with rpath: success - _build(['-Wl,-rpath,$ORIGIN/subdir']) - out = self.run_js('main.js') - self.assertContained('Hello1', out) - self.assertContained('Hello1_2', out) - self.assertContained('Ok', out) + _build(['-Wl,-rpath,$ORIGIN/subdir'], "Hello1\nHello1_dep\nOk\n") def test_dlopen_bad_flags(self): create_file('main.c', r''' From fb7ca61e125e30595b5fcd9d77cec76dd5788f4b Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 16:38:33 -0400 Subject: [PATCH 46/58] Rename hello1* to hello* --- test/test_other.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index 050c4e69aad53..a0b4356a20fb6 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7709,22 +7709,22 @@ def test_ld_library_path(self, args): @also_with_wasmfs def test_dlopen_rpath(self): - create_file('hello1_dep.c', r''' + create_file('hello_dep.c', r''' #include<stdio.h> -void hello1_dep() { - printf ("Hello1_dep\n"); +void hello_dep() { + printf ("Hello_dep\n"); return; } ''') - create_file('hello1.c', r''' + create_file('hello.c', r''' #include <stdio.h> -void hello1_dep(); +void hello_dep(); -void hello1() { - printf ("Hello1\n"); - hello1_dep(); +void hello() { + printf ("Hello\n"); + hello_dep(); return; } ''') @@ -7740,9 +7740,9 @@ def test_dlopen_rpath(self): void (*f)(); double (*f2)(double); - h = dlopen("/usr/lib/libhello1.wasm", RTLD_NOW); + h = dlopen("/usr/lib/libhello.wasm", RTLD_NOW); assert(h); - f = dlsym(h, "hello1"); + f = dlsym(h, "hello"); assert(f); f(); dlclose(h); @@ -7755,20 +7755,20 @@ def test_dlopen_rpath(self): os.mkdir('subdir') def _build(rpath_flag, expected, **kwds): - self.run_process([EMCC, '-o', 'subdir/libhello1_dep.so', 'hello1_dep.c', '-sSIDE_MODULE']) - self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE', 'subdir/libhello1_dep.so'] + rpath_flag) + self.run_process([EMCC, '-o', 'subdir/libhello_dep.so', 'hello_dep.c', '-sSIDE_MODULE']) + self.run_process([EMCC, '-o', 'hello.wasm', 'hello.c', '-sSIDE_MODULE', 'subdir/libhello_dep.so'] + rpath_flag) args = ['--profiling-funcs', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb', - '--embed-file', 'hello1.wasm@/usr/lib/libhello1.wasm', - '--embed-file', 'subdir/libhello1_dep.so@/usr/lib/subdir/libhello1_dep.so', - 'hello1.wasm', '-sNO_AUTOLOAD_DYLIBS', - '-L./subdir', '-lhello1_dep'] + '--embed-file', 'hello.wasm@/usr/lib/libhello.wasm', + '--embed-file', 'subdir/libhello_dep.so@/usr/lib/subdir/libhello_dep.so', + 'hello.wasm', '-sNO_AUTOLOAD_DYLIBS', + '-L./subdir', '-lhello_dep'] self.do_runf('main.c', expected, emcc_args=args, **kwds) # case 1) without rpath: fail to locate the library - _build([], "no such file or directory, open '.*libhello1_dep\.so'", regex=True, assert_returncode=NON_ZERO) + _build([], "no such file or directory, open '.*libhello_dep\.so'", regex=True, assert_returncode=NON_ZERO) # case 2) with rpath: success - _build(['-Wl,-rpath,$ORIGIN/subdir'], "Hello1\nHello1_dep\nOk\n") + _build(['-Wl,-rpath,$ORIGIN/subdir'], "Hello\nHello_dep\nOk\n") def test_dlopen_bad_flags(self): create_file('main.c', r''' From f164ddc492b6d885efd389695063d47932cccd1f Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 16:39:37 -0400 Subject: [PATCH 47/58] Format fixes --- test/test_other.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index a0b4356a20fb6..33cefc55fe3ee 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7596,7 +7596,7 @@ def test_ld_library_path(self, args): if args: self.setup_node_pthreads() create_file('hello1_dep.c', r''' -#include<stdio.h> +#include <stdio.h> void hello1_dep() { printf("Hello1_dep\n"); @@ -7626,7 +7626,7 @@ def test_ld_library_path(self, args): #include <stdio.h> void hello3() { - printf ("Hello3\n"); + printf("Hello3\n"); return; } ''') @@ -7710,10 +7710,10 @@ def test_ld_library_path(self, args): @also_with_wasmfs def test_dlopen_rpath(self): create_file('hello_dep.c', r''' -#include<stdio.h> +#include <stdio.h> void hello_dep() { - printf ("Hello_dep\n"); + printf("Hello_dep\n"); return; } ''') @@ -7723,7 +7723,7 @@ def test_dlopen_rpath(self): void hello_dep(); void hello() { - printf ("Hello\n"); + printf("Hello\n"); hello_dep(); return; } From 7422fc92c408d22d50f02a1a7187c9479d440a63 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 16:44:04 -0400 Subject: [PATCH 48/58] Add comment on why we copy flags rather than mutating. --- src/lib/libdylink.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 2578a1033efc1..d5562ba37693e 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -901,7 +901,10 @@ var LibraryDylink = { return postInstantiation(module, instance); } - flags = Object.assign(flags, {rpath: { parentLibPath: libName, paths: metadata.runtimePaths }}) + // We need to set rpath in flags based on the current library's rpath. + // We can't mutate flags or else if a depends on b and c and b depends on d, + // then c will be loaded with b's rpath instead of a's. + flags = {...flags, rpath: { parentLibPath: libName, paths: metadata.runtimePaths }} // now load needed libraries and the module itself. if (flags.loadAsync) { return metadata.neededDynlibs From 31ac4ce8df9606f3d2d902d3bcda623b9e66ac6f Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 17:07:14 -0400 Subject: [PATCH 49/58] Quit out earlier if runtime not initialized and add comment --- src/lib/libdylink.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index d5562ba37693e..a62320ec5b6e4 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -962,6 +962,15 @@ var LibraryDylink = { #endif ], $findLibraryFS: (libName, rpath) => { + // If we're preloading a dynamic library, the runtime is not ready to call + // __wasmfs_identify or __emscripten_find_dylib. So just quit out. + // + // This means that DT_NEEDED for the main module and transitive dependencies + // of it won't work with this code path. Similarly, it means that calling + // loadDynamicLibrary in a preRun hook can't use this code path. + if (!runtimeInitialized) { + return undefined; + } if (libName.startsWith("/")) { #if WASMFS var result = withStackSave(() => __wasmfs_identify(stringToUTF8OnStack(libName))); @@ -975,9 +984,6 @@ var LibraryDylink = { } #endif } - if (!runtimeInitialized) { - return undefined; - } var runtimePathsAbs = (rpath?.paths || []).map((p) => replaceORIGIN(rpath?.parentLibPath, p)); return withStackSave(() => { // In dylink.c we use: `char buf[2*NAME_MAX+2];` and NAME_MAX is 255. From ff9c43196dcf804b1341429839ab77d1aa638729 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 17:09:32 -0400 Subject: [PATCH 50/58] Update codesizes --- .../test_codesize_hello_dylink.exports | 1 + .../codesize/test_codesize_hello_dylink.funcs | 20 +++++++++++++++++++ .../test_codesize_hello_dylink.gzsize | 2 +- .../test_codesize_hello_dylink.imports | 5 +++++ .../test_codesize_hello_dylink.jssize | 2 +- .../codesize/test_codesize_hello_dylink.sent | 5 +++++ .../codesize/test_codesize_hello_dylink.size | 2 +- 7 files changed, 34 insertions(+), 3 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.exports b/test/other/codesize/test_codesize_hello_dylink.exports index 99ba54eca755a..ad9fe79a10e50 100644 --- a/test/other/codesize/test_codesize_hello_dylink.exports +++ b/test/other/codesize/test_codesize_hello_dylink.exports @@ -1,5 +1,6 @@ __wasm_apply_data_relocs __wasm_call_ctors +_emscripten_find_dylib _emscripten_stack_alloc _emscripten_stack_restore calloc diff --git a/test/other/codesize/test_codesize_hello_dylink.funcs b/test/other/codesize/test_codesize_hello_dylink.funcs index 67e34312338f4..22bdbdc3c939e 100644 --- a/test/other/codesize/test_codesize_hello_dylink.funcs +++ b/test/other/codesize/test_codesize_hello_dylink.funcs @@ -1,15 +1,35 @@ $__emscripten_stdout_close $__emscripten_stdout_seek $__fwritex +$__memcpy +$__memset $__stdio_write +$__strchrnul $__towrite $__wasm_apply_data_relocs $__wasm_call_ctors $__wasm_start +$_emscripten_find_dylib $_emscripten_stack_alloc $_emscripten_stack_restore $dlcalloc +$dlmalloc $emscripten_stack_get_current +$fmt_fp +$fmt_u +$frexp +$getint $main +$out +$pad +$pop_arg +$pop_arg_long_double +$printf_core $sbrk $setThrew +$sn_write +$strcspn +$strlen +$strspn +$vsnprintf +$wctomb diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index 1c3de1ed95f5f..4a430ae938670 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -5875 +11790 diff --git a/test/other/codesize/test_codesize_hello_dylink.imports b/test/other/codesize/test_codesize_hello_dylink.imports index ed7c6d9be94fb..a183f50451034 100644 --- a/test/other/codesize/test_codesize_hello_dylink.imports +++ b/test/other/codesize/test_codesize_hello_dylink.imports @@ -1,8 +1,13 @@ GOT.mem.__heap_base +GOT.mem.__stack_high +GOT.mem.__stack_low env.__indirect_function_table env.__memory_base env.__stack_pointer +env.__syscall_stat64 env.__table_base env.emscripten_resize_heap env.memory +wasi_snapshot_preview1.environ_get +wasi_snapshot_preview1.environ_sizes_get wasi_snapshot_preview1.fd_write diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index 0b2eb308687d0..6bf78962170cf 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -12857 +27855 diff --git a/test/other/codesize/test_codesize_hello_dylink.sent b/test/other/codesize/test_codesize_hello_dylink.sent index 1ca2e37d90365..b09314e54011e 100644 --- a/test/other/codesize/test_codesize_hello_dylink.sent +++ b/test/other/codesize/test_codesize_hello_dylink.sent @@ -1,8 +1,13 @@ __heap_base __indirect_function_table __memory_base +__stack_high +__stack_low __stack_pointer +__syscall_stat64 __table_base emscripten_resize_heap +environ_get +environ_sizes_get fd_write memory diff --git a/test/other/codesize/test_codesize_hello_dylink.size b/test/other/codesize/test_codesize_hello_dylink.size index ac37333bb7dd7..8b1fad7e5d462 100644 --- a/test/other/codesize/test_codesize_hello_dylink.size +++ b/test/other/codesize/test_codesize_hello_dylink.size @@ -1 +1 @@ -8176 +18603 From 412fb9662112ae84f3e434d3a2d6c3fca4ad6965 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 17:13:58 -0400 Subject: [PATCH 51/58] Fix ruff lint --- test/test_other.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_other.py b/test/test_other.py index a00a7d90dba28..8131c03b1fffd 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7739,7 +7739,7 @@ def _build(rpath_flag, expected, **kwds): self.do_runf('main.c', expected, emcc_args=args, **kwds) # case 1) without rpath: fail to locate the library - _build([], "no such file or directory, open '.*libhello_dep\.so'", regex=True, assert_returncode=NON_ZERO) + _build([], r"no such file or directory, open '.*libhello_dep\.so'", regex=True, assert_returncode=NON_ZERO) # case 2) with rpath: success _build(['-Wl,-rpath,$ORIGIN/subdir'], "Hello\nHello_dep\nOk\n") From 61e93e6371db2f7f9f2cbef6c44c9369aa49dd3c Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 20:17:40 -0400 Subject: [PATCH 52/58] Address some review comments --- src/lib/libdylink.js | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index a62320ec5b6e4..11f0fc651fcf5 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -57,7 +57,7 @@ var LibraryDylink = { return rpath.replace('$ORIGIN', origin); } - return rpath + return rpath; }, #endif // FILESYSTEM @@ -947,6 +947,7 @@ var LibraryDylink = { return dso; }, +#if FILESYSTEM $findLibraryFS__deps: [ '$replaceORIGIN', '_emscripten_find_dylib', @@ -956,6 +957,7 @@ var LibraryDylink = { '$stringToUTF8OnStack', '$stringToUTF8', '$FS', + '$PATH', #if WASMFS '_wasmfs_identify', '_wasmfs_read_file', @@ -971,7 +973,7 @@ var LibraryDylink = { if (!runtimeInitialized) { return undefined; } - if (libName.startsWith("/")) { + if (PATH.isAbs(libName)) { #if WASMFS var result = withStackSave(() => __wasmfs_identify(stringToUTF8OnStack(libName))); return result === {{{ cDefs.EEXIST }}} ? libName : undefined; @@ -984,28 +986,19 @@ var LibraryDylink = { } #endif } - var runtimePathsAbs = (rpath?.paths || []).map((p) => replaceORIGIN(rpath?.parentLibPath, p)); + var rpathResolved = (rpath?.paths || []).map((p) => replaceORIGIN(rpath?.parentLibPath, p)); return withStackSave(() => { // In dylink.c we use: `char buf[2*NAME_MAX+2];` and NAME_MAX is 255. // So we use the same size here. var bufSize = 2*255 + 2; var buf = stackAlloc(bufSize); - var size = 0; - for (var str of runtimePathsAbs) { - size += lengthBytesUTF8(str) + 1; - } - var rpathC = stackAlloc(size); - var cur = rpathC - for (var str of runtimePathsAbs) { - cur += stringToUTF8(str, cur, size); - HEAP8[cur] = ':'.charCodeAt(0); - } - HEAP8[cur] = 0; + var rpathC = stringToUTF8OnStack(rpathResolved.join(':')); var libNameC = stringToUTF8OnStack(libName); var resLibNameC = __emscripten_find_dylib(buf, rpathC, libNameC, bufSize); return (resLibNameC !== libNameC) ? UTF8ToString(resLibNameC) : undefined; }); }, +#endif // FILESYSTEM // loadDynamicLibrary loads dynamic library @ lib URL / path and returns // handle for loaded DSO. From d5bf161b77b3a3b28dc6230ece8585b936ae8c44 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 20:28:26 -0400 Subject: [PATCH 53/58] Simplify path_find --- system/lib/libc/dynlink.c | 69 ++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/system/lib/libc/dynlink.c b/system/lib/libc/dynlink.c index b105a08d95212..d8736ec318588 100644 --- a/system/lib/libc/dynlink.c +++ b/system/lib/libc/dynlink.c @@ -484,58 +484,51 @@ static void dlopen_onerror(struct dso* dso, void* user_data) { } // Modified version of path_open from musl/ldso/dynlink.c -static int path_find(const char *name, int ncandidates, const char **candidates, char *buf, size_t buf_size) { +static int path_find(const char *name, const char *s, char *buf, size_t buf_size) { + if (s == NULL) { + return -1; + } size_t l; int fd; - for (int c = 0; c < ncandidates; c ++) { - const char* s = candidates[c]; - if (s == NULL) { - dbg("Candidate %d is null, skipping\n", c); - continue; - } - dbg("Candidate %d...\n", c); - for (;;) { - s += strspn(s, ":\n"); - l = strcspn(s, ":\n"); - if (l-1 >= INT_MAX) return -1; - if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { - dbg("dlopen: path_find: %s", buf); - struct stat statbuf; - dbg("Checking file: %s\n", buf); - if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { - dbg(" .. found\n"); - return 0; - } - dbg(" .. not found\n"); - switch (errno) { - case ENOENT: - case ENOTDIR: - case EACCES: - case ENAMETOOLONG: - break; - default: - dbg("dlopen: path_find failed: %s", strerror(errno)); - /* Any negative value but -1 will inhibit - * futher path search. */ - return -2; - } + for (;;) { + s += strspn(s, ":\n"); + l = strcspn(s, ":\n"); + if (l-1 >= INT_MAX) return -1; + if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { + dbg("dlopen: path_find: %s", buf); + struct stat statbuf; + if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + return 0; + } + switch (errno) { + case ENOENT: + case ENOTDIR: + case EACCES: + case ENAMETOOLONG: + break; + default: + dbg("dlopen: path_find failed: %s", strerror(errno)); + /* Any negative value but -1 will inhibit + * futher path search. */ + return -2; } - s += l; } + s += l; } - return -1; } // Resolve filename using LD_LIBRARY_PATH const char* _emscripten_find_dylib(char* buf, const char* rpath, const char* file, size_t buflen) { if (!strchr(file, '/')) { const char* env_path = getenv("LD_LIBRARY_PATH"); - int ncandidates = 2; - const char* candidates[2] = {env_path, rpath}; - if (path_find(file, ncandidates, candidates, buf, buflen) == 0) { + if (path_find(file, env_path, buf, buflen) == 0) { dbg("dlopen: found in LD_LIBRARY_PATH: %s", buf); return buf; } + if (path_find(file, rpath, buf, buflen) == 0) { + dbg("dlopen: found in RPATH: %s", buf); + return buf; + } } return file; } From e3a2ff8e11979205d639608307224cf05998bb09 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 20:33:21 -0400 Subject: [PATCH 54/58] Indentation --- test/test_other.py | 66 +++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index 8131c03b1fffd..b14a6e969e81a 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7684,48 +7684,48 @@ def test_ld_library_path(self, args): @also_with_wasmfs def test_dlopen_rpath(self): create_file('hello_dep.c', r''' -#include <stdio.h> + #include <stdio.h> -void hello_dep() { - printf("Hello_dep\n"); - return; -} -''') + void hello_dep() { + printf("Hello_dep\n"); + return; + } + ''') create_file('hello.c', r''' -#include <stdio.h> + #include <stdio.h> -void hello_dep(); + void hello_dep(); -void hello() { - printf("Hello\n"); - hello_dep(); - return; -} -''') + void hello() { + printf("Hello\n"); + hello_dep(); + return; + } + ''') create_file('main.c', r''' -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <dlfcn.h> + #include <assert.h> + #include <stdio.h> + #include <stdlib.h> + #include <string.h> + #include <dlfcn.h> -int main() { - void *h; - void (*f)(); - double (*f2)(double); + int main() { + void *h; + void (*f)(); + double (*f2)(double); - h = dlopen("/usr/lib/libhello.wasm", RTLD_NOW); - assert(h); - f = dlsym(h, "hello"); - assert(f); - f(); - dlclose(h); + h = dlopen("/usr/lib/libhello.wasm", RTLD_NOW); + assert(h); + f = dlsym(h, "hello"); + assert(f); + f(); + dlclose(h); - printf("Ok\n"); + printf("Ok\n"); - return 0; -} -''') + return 0; + } + ''') os.mkdir('subdir') def _build(rpath_flag, expected, **kwds): From aa851927f17d41e6a8b28d50a2289c6df7889c6b Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 20:44:30 -0400 Subject: [PATCH 55/58] Make `_emscripten_resolve_path` return `NULL` if it didn't resolve the path --- src/lib/libdylink.js | 2 +- src/lib/libfs_shared.js | 1 + system/lib/libc/dynlink.c | 34 ++++++++++++++++++++++------------ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 11f0fc651fcf5..b1e70178286f6 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -995,7 +995,7 @@ var LibraryDylink = { var rpathC = stringToUTF8OnStack(rpathResolved.join(':')); var libNameC = stringToUTF8OnStack(libName); var resLibNameC = __emscripten_find_dylib(buf, rpathC, libNameC, bufSize); - return (resLibNameC !== libNameC) ? UTF8ToString(resLibNameC) : undefined; + return resLibNameC ? UTF8ToString(resLibNameC) : undefined; }); }, #endif // FILESYSTEM diff --git a/src/lib/libfs_shared.js b/src/lib/libfs_shared.js index db6f68af9dde5..30d5185c441d7 100644 --- a/src/lib/libfs_shared.js +++ b/src/lib/libfs_shared.js @@ -186,6 +186,7 @@ addToLibrary({ $FS_createDevice__deps: ['$FS'], $FS_createDevice: 'FS.createDevice', + $FS_readFile__proxy: 'sync', $FS_readFile__deps: ['$FS'], $FS_readFile: 'FS.readFile', }); diff --git a/system/lib/libc/dynlink.c b/system/lib/libc/dynlink.c index d8736ec318588..71d9e14b98455 100644 --- a/system/lib/libc/dynlink.c +++ b/system/lib/libc/dynlink.c @@ -519,16 +519,26 @@ static int path_find(const char *name, const char *s, char *buf, size_t buf_size // Resolve filename using LD_LIBRARY_PATH const char* _emscripten_find_dylib(char* buf, const char* rpath, const char* file, size_t buflen) { - if (!strchr(file, '/')) { - const char* env_path = getenv("LD_LIBRARY_PATH"); - if (path_find(file, env_path, buf, buflen) == 0) { - dbg("dlopen: found in LD_LIBRARY_PATH: %s", buf); - return buf; - } - if (path_find(file, rpath, buf, buflen) == 0) { - dbg("dlopen: found in RPATH: %s", buf); - return buf; - } + if (strchr(file, '/')) { + // Absolute path, leave it alone + return NULL; + } + const char* env_path = getenv("LD_LIBRARY_PATH"); + if (path_find(file, env_path, buf, buflen) == 0) { + dbg("dlopen: found in LD_LIBRARY_PATH: %s", buf); + return buf; + } + if (path_find(file, rpath, buf, buflen) == 0) { + dbg("dlopen: found in RPATH: %s", buf); + return buf; + } + return NULL; +} + +static const char* find_dylib(char* buf, const char* file, size_t buflen) { + const char* res = _emscripten_find_dylib(buf, NULL, file, buflen); + if (res) { + return res; } return file; } @@ -560,7 +570,7 @@ static struct dso* _dlopen(const char* file, int flags) { do_write_lock(); char buf[2*NAME_MAX+2]; - file = _emscripten_find_dylib(buf, NULL, file, sizeof buf); + file = find_dylib(buf, file, sizeof buf); struct dso* p = find_existing(file); if (p) { @@ -600,7 +610,7 @@ void emscripten_dlopen(const char* filename, int flags, void* user_data, } do_write_lock(); char buf[2*NAME_MAX+2]; - filename = _emscripten_find_dylib(buf, NULL, filename, sizeof buf); + filename = find_dylib(buf, filename, sizeof buf); struct dso* p = find_existing(filename); if (p) { onsuccess(user_data, p); From 5d3620ebb6dbbcdaf072120ea1cf54013417706f Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 20:49:29 -0400 Subject: [PATCH 56/58] adjust test_ld_library_path --- test/test_other.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test_other.py b/test/test_other.py index b14a6e969e81a..2cf71747f61eb 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -7564,10 +7564,13 @@ def test_RUNTIME_LINKED_LIBS(self): @parameterized({ '': ([],), + 'wasmfs': (['-sWASMFS'],), 'pthread': (['-g', '-pthread', '-Wno-experimental', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'],), }) def test_ld_library_path(self, args): - if args: + if '-pthread' in args: + self.skipTest('Problems with readFile from pthread') + if '-pthread' in args: self.setup_node_pthreads() create_file('hello1_dep.c', r''' #include <stdio.h> From e66a37279ff824b2c773850f02cf879ff69ef963 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 20:51:31 -0400 Subject: [PATCH 57/58] Revert unneeded change --- src/lib/libfs_shared.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/libfs_shared.js b/src/lib/libfs_shared.js index 30d5185c441d7..db6f68af9dde5 100644 --- a/src/lib/libfs_shared.js +++ b/src/lib/libfs_shared.js @@ -186,7 +186,6 @@ addToLibrary({ $FS_createDevice__deps: ['$FS'], $FS_createDevice: 'FS.createDevice', - $FS_readFile__proxy: 'sync', $FS_readFile__deps: ['$FS'], $FS_readFile: 'FS.readFile', }); From 2e41541ba5478b454eb2d912d474810fa4ca2896 Mon Sep 17 00:00:00 2001 From: Hood Chatham <roberthoodchatham@gmail.com> Date: Tue, 15 Apr 2025 21:19:25 -0400 Subject: [PATCH 58/58] Fix codesize_hello_dylink again --- test/other/codesize/test_codesize_hello_dylink.funcs | 1 + test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- test/other/codesize/test_codesize_hello_dylink.size | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.funcs b/test/other/codesize/test_codesize_hello_dylink.funcs index 22bdbdc3c939e..ca9eb3ea2d71b 100644 --- a/test/other/codesize/test_codesize_hello_dylink.funcs +++ b/test/other/codesize/test_codesize_hello_dylink.funcs @@ -22,6 +22,7 @@ $getint $main $out $pad +$path_find $pop_arg $pop_arg_long_double $printf_core diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index 4a430ae938670..27f49eac23ee3 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11790 +11753 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index 6bf78962170cf..8c789d48edc34 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -27855 +27782 diff --git a/test/other/codesize/test_codesize_hello_dylink.size b/test/other/codesize/test_codesize_hello_dylink.size index 8b1fad7e5d462..912b7ba8cf298 100644 --- a/test/other/codesize/test_codesize_hello_dylink.size +++ b/test/other/codesize/test_codesize_hello_dylink.size @@ -1 +1 @@ -18603 +18550