Skip to content

Commit 1ddccf1

Browse files
authored
Don't abort on dlopen/dlsym when dynamic linking is not available (#19527)
Instead simply return failure with a error message in `dlerror`. This matches the bahaviour of other libc/syscall functions and allows the behaviour to be controlled via the existing ALLOW_UNIMPLEMENTED_SYSCALLS setting. The only downside (IIUC) is that emscripten is a little less helpful/magical in advising of what to do if these functions are used without `-sMAIN_MODULE`. Fixes: #19411
1 parent e30699f commit 1ddccf1

File tree

8 files changed

+36
-56
lines changed

8 files changed

+36
-56
lines changed

ChangeLog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ See docs/process.md for more on how version tagging works.
2323
- The log message that emcc will sometime print (for example when auto-building
2424
system libraries) can now be completely supressed by running with
2525
`EMCC_LOGGING=0`.
26+
- Runtime dynamic linking symbols such as dlopen and dlsym will no longer cause
27+
a linker error when building without `-sMAIN_MODULE`. Instead stub functions
28+
will be included that fail at runtime. This matches the behaviour of other
29+
libc functions that we don't implement. For those that prefer to get a linker
30+
error we have the `-sALLOW_UNIMPLEMENTED_SYSCALLS` settings. (#19527)
2631

2732
3.1.41 - 06/06/23
2833
-----------------

src/library_dylink.js

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
* Dynamic library loading
77
*/
88

9-
var dlopenMissingError = "'To use dlopen, you need enable dynamic linking, see https://emscripten.org/docs/compiling/Dynamic-Linking.html'"
9+
#if !RELOCATABLE
10+
#error "library_dylink.js requires RELOCATABLE"
11+
#endif
1012

1113
var LibraryDylink = {
12-
#if RELOCATABLE
1314
#if FILESYSTEM
1415
$registerWasmPlugin__deps: ['$preloadPlugins'],
1516
$registerWasmPlugin: function() {
@@ -309,49 +310,7 @@ var LibraryDylink = {
309310
dbg('done reportUndefinedSymbols');
310311
#endif
311312
},
312-
#endif
313313

314-
#if !MAIN_MODULE
315-
#if !ALLOW_UNIMPLEMENTED_SYSCALLS
316-
_dlopen_js__deps: [function() { error(dlopenMissingError); }],
317-
_emscripten_dlopen_js__deps: [function() { error(dlopenMissingError); }],
318-
_dlsym_js__deps: [function() { error(dlopenMissingError); }],
319-
_dlsym_catchup_js__deps: [function() { error(dlopenMissingError); }],
320-
dlopen__deps: [function() { error(dlopenMissingError); }],
321-
emscripten_dlopen__deps: [function() { error(dlopenMissingError); }],
322-
__dlsym__deps: [function() { error(dlopenMissingError); }],
323-
#else
324-
$dlopenMissingError: `= ${dlopenMissingError}`,
325-
_dlopen_js__deps: ['$dlopenMissingError'],
326-
_emscripten_dlopen_js__deps: ['$dlopenMissingError'],
327-
_dlsym_js__deps: ['$dlopenMissingError'],
328-
_dlsym_catchup_js__deps: ['$dlopenMissingError'],
329-
dlopen__deps: ['$dlopenMissingError'],
330-
emscripten_dlopen__deps: ['$dlopenMissingError'],
331-
__dlsym__deps: ['$dlopenMissingError'],
332-
#endif
333-
_dlopen_js: function(handle) {
334-
abort(dlopenMissingError);
335-
},
336-
_emscripten_dlopen_js: function(handle, onsuccess, onerror, user_data) {
337-
abort(dlopenMissingError);
338-
},
339-
_dlsym_js: function(handle, symbol) {
340-
abort(dlopenMissingError);
341-
},
342-
_dlsym_catchup_js: function(handle, symbolIndex) {
343-
abort(dlopenMissingError);
344-
},
345-
dlopen: function(filename, flags) {
346-
abort(dlopenMissingError);
347-
},
348-
emscripten_dlopen: function(handle, onsuccess, onerror, user_data) {
349-
abort(dlopenMissingError);
350-
},
351-
__dlsym: function(handle, symbol, ra) {
352-
abort(dlopenMissingError);
353-
},
354-
#else // MAIN_MODULE != 0
355314
// dynamic linker/loader (a-la ld.so on ELF systems)
356315
$LDSO__deps: ['$newDSO'],
357316
$LDSO: {
@@ -1255,7 +1214,6 @@ var LibraryDylink = {
12551214
#endif
12561215
return result;
12571216
},
1258-
#endif // MAIN_MODULE != 0
12591217
};
12601218

12611219
mergeInto(LibraryManager.library, LibraryDylink);

src/library_sigs.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ sigs = {
211211
__asctime_r__sig: 'ppp',
212212
__assert_fail__sig: 'vppip',
213213
__call_sighandler__sig: 'vpi',
214-
__dlsym__sig: 'pppp',
215214
__emscripten_init_main_thread_js__sig: 'vp',
216215
__emscripten_thread_cleanup__sig: 'vp',
217216
__handle_stack_overflow__sig: 'vp',
@@ -512,7 +511,6 @@ sigs = {
512511
boxRGBA__sig: 'ipiiiiiiii',
513512
clock_res_get__sig: 'iip',
514513
clock_time_get__sig: 'iijp',
515-
dlopen__sig: 'ppi',
516514
eglBindAPI__sig: 'ii',
517515
eglChooseConfig__sig: 'ipppip',
518516
eglCreateContext__sig: 'ppppp',
@@ -593,7 +591,6 @@ sigs = {
593591
emscripten_destroy_audio_context__sig: 'vi',
594592
emscripten_destroy_web_audio_node__sig: 'vi',
595593
emscripten_destroy_worker__sig: 'vi',
596-
emscripten_dlopen__sig: 'vpippp',
597594
emscripten_enter_soft_fullscreen__sig: 'ipp',
598595
emscripten_err__sig: 'vp',
599596
emscripten_errn__sig: 'vpp',

src/modules.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ global.LibraryManager = {
4949
'library_html5.js',
5050
'library_stack_trace.js',
5151
'library_wasi.js',
52-
'library_dylink.js',
5352
'library_makeDynCall.js',
5453
'library_eventloop.js',
5554
'library_promise.js',
@@ -80,6 +79,10 @@ global.LibraryManager = {
8079
libraries.push('library_syscall.js');
8180
}
8281

82+
if (RELOCATABLE) {
83+
libraries.push('library_dylink.js');
84+
}
85+
8386
if (FILESYSTEM) {
8487
libraries.push('library_fs_shared.js');
8588
if (WASMFS) {

system/lib/libc/emscripten_libc_stubs.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,17 @@ weak int sigaltstack(const stack_t *restrict ss, stack_t *restrict old_ss) {
213213
errno = ENOSYS;
214214
return -1;
215215
}
216+
217+
#ifndef __PIC__
218+
void __dl_seterr(const char*, ...);
219+
220+
weak void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra) {
221+
__dl_seterr("dynamic linking not enabled");
222+
return NULL;
223+
}
224+
225+
weak void* dlopen(const char* file, int flags) {
226+
__dl_seterr("dynamic linking not enabled");
227+
return NULL;
228+
}
229+
#endif

test/other/test_dlopen_blocking.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55

66
int main() {
77
void* handle = dlopen("libside.so", RTLD_NOW);
8-
printf("handle: %p\n", handle);
98
if (!handle) {
10-
printf("%s\n", dlerror());
9+
printf("dlopen failed: %s\n", dlerror());
1110
return 1;
1211
}
12+
printf("handle: %p\n", handle);
1313
int* foo = (int*)dlsym(handle, "foo");
1414
if (!foo) {
15-
printf("%s\n", dlerror());
15+
printf("dlsym failed: %s\n", dlerror());
1616
return 1;
1717
}
1818
printf("foo = %d\n", *foo);

test/test_other.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12209,13 +12209,13 @@ def test_unimplemented_syscalls_dlopen(self):
1220912209
cmd = [EMCC, test_file('other/test_dlopen_blocking.c')] + self.get_emcc_args()
1221012210
self.run_process(cmd)
1221112211
err = self.run_js('a.out.js', assert_returncode=NON_ZERO)
12212-
self.assertContained('Aborted(To use dlopen, you need enable dynamic linking, see https://emscripten.org/docs/compiling/Dynamic-Linking.html)', err)
12212+
self.assertContained('dlopen failed: dynamic linking not enabled', err)
1221312213

1221412214
# If we build the same thing with ALLOW_UNIMPLEMENTED_SYSCALLS=0 we
1221512215
# expect a link-time failure rather than a runtime one.
1221612216
cmd += ['-sALLOW_UNIMPLEMENTED_SYSCALLS=0']
1221712217
err = self.expect_fail(cmd)
12218-
self.assertContained('To use dlopen, you need enable dynamic linking, see https://emscripten.org/docs/compiling/Dynamic-Linking.html', err)
12218+
self.assertContained('undefined symbol: dlopen', err)
1221912219

1222012220
def test_unimplemented_syscalls_dladdr(self):
1222112221
create_file('main.c', '''

tools/gen_sig_info.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,10 @@ def ignore_symbol(s, cxx):
169169
return True
170170
if s.startswith('gl') and any(s.endswith(x) for x in ('NV', 'EXT', 'WEBGL', 'ARB', 'ANGLE')):
171171
return True
172-
if cxx and s in ('__dlsym', '__asctime_r'):
172+
if s in ('__stack_base', '__memory_base', '__table_base', '__global_base', '__heap_base',
173+
'__stack_pointer', '__stack_high', '__stack_low'):
174+
return True
175+
if cxx and s in ('__asctime_r',):
173176
return True
174177
return False
175178

@@ -381,7 +384,7 @@ def main(args):
381384
extract_sig_info(sig_info, {'LEGACY_GL_EMULATION': 1}, ['-DGLES'])
382385
extract_sig_info(sig_info, {'USE_GLFW': 2, 'FULL_ES3': 1, 'MAX_WEBGL_VERSION': 2})
383386
extract_sig_info(sig_info, {'STANDALONE_WASM': 1})
384-
extract_sig_info(sig_info, {'MAIN_MODULE': 2, 'USE_WEBGPU': 1})
387+
extract_sig_info(sig_info, {'MAIN_MODULE': 2, 'RELOCATABLE': 1, 'USE_WEBGPU': 1})
385388

386389
write_sig_library(args.output, sig_info)
387390
if args.update:

0 commit comments

Comments
 (0)