Skip to content

Commit fb4a23b

Browse files
authored
[dylink] Fix rpath calculation in nested dependencies (#24234)
This fixes a bug in rpath calculation in nested dependencies. Basically, it fixes a case when a relative path is passed to the `loadDynamicLibrary`. Think of the following scenario: 0. libhello.wasm depends on libhello_dep.so depends on libhello_nested_dep.so 1. [main.c] calls dlopen('/usr/lib/libhello.wasm') 2. [dynlink.c] calls `loadDynamicLibrary('/usr/lib/libhello.wasm')` (_dlopen_js ==> dlopenInternal ==> loadDynamicLibrary) 3. [libdylink.js] inside `loadDynamicLibrary('/usr/lib/libhello.wasm')`, it loads the dependency `libhello_dep.so`. When locating `libhello_dep.so`, it uses `parentLibPath: /usr/lib/libhello.wasm` it locates the library correctly from `/usr/lib/libhello_dep.so`. 5. [libdylink.js] Now we call `loadDynamicLibrary('libhello_dep.so')`, and it loads its dependency 'libhello_nested_dep.so' first. In this case it uses `parentLibPath: libhello_dep.so` so it fails to locate the library.
1 parent 49a5c1d commit fb4a23b

File tree

4 files changed

+35
-16
lines changed

4 files changed

+35
-16
lines changed

src/lib/libdylink.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -977,13 +977,19 @@ var LibraryDylink = {
977977
// now load needed libraries and the module itself.
978978
if (flags.loadAsync) {
979979
return metadata.neededDynlibs
980-
.reduce((chain, dynNeeded) => chain.then(() =>
981-
loadDynamicLibrary(dynNeeded, flags, localScope)
982-
), Promise.resolve())
980+
.reduce((chain, needed) => chain.then(() => {
981+
#if FILESYSTEM
982+
needed = findLibraryFS(needed, flags.rpath) ?? needed;
983+
#endif
984+
return loadDynamicLibrary(needed, flags, localScope);
985+
}), Promise.resolve())
983986
.then(loadModule);
984987
}
985988

986989
for (var needed of metadata.neededDynlibs) {
990+
#if FILESYSTEM
991+
needed = findLibraryFS(needed, flags.rpath) ?? needed;
992+
#endif
987993
loadDynamicLibrary(needed, flags, localScope)
988994
}
989995
return loadModule();

test/codesize/test_codesize_hello_dylink.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
2-
"a.out.js": 26672,
3-
"a.out.js.gz": 11377,
2+
"a.out.js": 26712,
3+
"a.out.js.gz": 11400,
44
"a.out.nodebug.wasm": 17751,
55
"a.out.nodebug.wasm.gz": 8984,
6-
"total": 44423,
7-
"total_gz": 20361,
6+
"total": 44463,
7+
"total_gz": 20384,
88
"sent": [
99
"__syscall_stat64",
1010
"emscripten_resize_heap",

test/codesize/test_codesize_hello_dylink_all.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"a.out.js": 245679,
2+
"a.out.js": 245720,
33
"a.out.nodebug.wasm": 574007,
4-
"total": 819686,
4+
"total": 819727,
55
"sent": [
66
"IMG_Init",
77
"IMG_Load",

test/test_other.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6773,11 +6773,22 @@ def test_ld_library_path(self, args):
67736773

67746774
@also_with_wasmfs
67756775
def test_dlopen_rpath(self):
6776+
create_file('hello_nested_dep.c', r'''
6777+
#include <stdio.h>
6778+
6779+
void hello_nested_dep() {
6780+
printf("Hello_nested_dep\n");
6781+
return;
6782+
}
6783+
''')
67766784
create_file('hello_dep.c', r'''
67776785
#include <stdio.h>
67786786

6787+
void hello_nested_dep();
6788+
67796789
void hello_dep() {
67806790
printf("Hello_dep\n");
6791+
hello_nested_dep();
67816792
return;
67826793
}
67836794
''')
@@ -6804,7 +6815,7 @@ def test_dlopen_rpath(self):
68046815
void (*f)();
68056816
double (*f2)(double);
68066817

6807-
h = dlopen("/usr/lib/libhello.wasm", RTLD_NOW);
6818+
h = dlopen("/usr/lib/libhello.so", RTLD_NOW);
68086819
assert(h);
68096820
f = dlsym(h, "hello");
68106821
assert(f);
@@ -6819,20 +6830,22 @@ def test_dlopen_rpath(self):
68196830
os.mkdir('subdir')
68206831

68216832
def _build(rpath_flag, expected, **kwds):
6822-
self.run_process([EMCC, '-o', 'subdir/libhello_dep.so', 'hello_dep.c', '-sSIDE_MODULE'])
6823-
self.run_process([EMCC, '-o', 'hello.wasm', 'hello.c', '-sSIDE_MODULE', 'subdir/libhello_dep.so'] + rpath_flag)
6833+
self.run_process([EMCC, '-o', 'subdir/libhello_nested_dep.so', 'hello_nested_dep.c', '-sSIDE_MODULE'])
6834+
self.run_process([EMCC, '-o', 'subdir/libhello_dep.so', 'hello_dep.c', '-sSIDE_MODULE', 'subdir/libhello_nested_dep.so'] + rpath_flag)
6835+
self.run_process([EMCC, '-o', 'hello.so', 'hello.c', '-sSIDE_MODULE', 'subdir/libhello_dep.so'] + rpath_flag)
68246836
args = ['--profiling-funcs', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb',
6825-
'--embed-file', 'hello.wasm@/usr/lib/libhello.wasm',
6837+
'--embed-file', 'hello.so@/usr/lib/libhello.so',
68266838
'--embed-file', 'subdir/libhello_dep.so@/usr/lib/subdir/libhello_dep.so',
6827-
'hello.wasm', '-sNO_AUTOLOAD_DYLIBS',
6828-
'-L./subdir', '-lhello_dep']
6839+
'--embed-file', 'subdir/libhello_nested_dep.so@/usr/lib/subdir/libhello_nested_dep.so',
6840+
'hello.so', '-sNO_AUTOLOAD_DYLIBS',
6841+
'-L./subdir', '-lhello_dep', '-lhello_nested_dep']
68296842
self.do_runf('main.c', expected, cflags=args, **kwds)
68306843

68316844
# case 1) without rpath: fail to locate the library
68326845
_build([], r"no such file or directory, open '.*libhello_dep\.so'", regex=True, assert_returncode=NON_ZERO)
68336846

68346847
# case 2) with rpath: success
6835-
_build(['-Wl,-rpath,$ORIGIN/subdir'], "Hello\nHello_dep\nOk\n")
6848+
_build(['-Wl,-rpath,$ORIGIN/subdir,-rpath,$ORIGIN'], "Hello\nHello_dep\nHello_nested_dep\nOk\n")
68366849

68376850
def test_dlopen_bad_flags(self):
68386851
create_file('main.c', r'''

0 commit comments

Comments
 (0)