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