Skip to content

Commit

Permalink
Apply relocations before static constructor (#17628)
Browse files Browse the repository at this point in the history
This bug applied to libraries loaded after the runtime initialized.

Fixes: #17601
  • Loading branch information
sbc100 authored Aug 12, 2022
1 parent c8b81d9 commit 9e7a17c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
16 changes: 8 additions & 8 deletions src/library_dylink.js
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,14 @@ var LibraryDylink = {
registerTLSInit(moduleExports['_emscripten_tls_init'], instance.exports, metadata)
if (!ENVIRONMENT_IS_PTHREAD) {
#endif
var applyRelocs = moduleExports['__wasm_apply_data_relocs'];
if (applyRelocs) {
if (runtimeInitialized) {
applyRelocs();
} else {
__RELOC_FUNCS__.push(applyRelocs);
}
}
var init = moduleExports['__wasm_call_ctors'];
if (init) {
if (runtimeInitialized) {
Expand All @@ -657,14 +665,6 @@ var LibraryDylink = {
__ATINIT__.push(init);
}
}
var applyRelocs = moduleExports['__wasm_apply_data_relocs'];
if (applyRelocs) {
if (runtimeInitialized) {
applyRelocs();
} else {
__RELOC_FUNCS__.push(applyRelocs);
}
}
#if USE_PTHREADS
}
#endif
Expand Down
42 changes: 42 additions & 0 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -6107,6 +6107,48 @@ def test_dlopen_bad_flags(self):
out = self.run_js('a.out.js')
self.assertContained('invalid mode for dlopen(): Either RTLD_LAZY or RTLD_NOW is required', out)

def test_dlopen_contructors(self):
create_file('side.c', r'''
#include <stdio.h>
#include <assert.h>
static int foo;
static int* ptr = &foo;
void check_relocations(void) {
assert(ptr == &foo);
}
__attribute__((constructor)) void ctor(void) {
printf("foo address: %p\n", ptr);
// Check that relocations have already been applied by the time
// contructor functions run.
check_relocations();
printf("done ctor\n");
}
''')
create_file('main.c', r'''
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>
int main() {
void (*check) (void);
void* h = dlopen("libside.wasm", RTLD_NOW|RTLD_GLOBAL);
assert(h);
check = dlsym(h, "check_relocations");
assert(check);
check();
printf("done\n");
return 0;
}''')
self.run_process([EMCC, '-g', '-o', 'libside.wasm', 'side.c', '-sSIDE_MODULE'])
self.run_process([EMCC, '-g', '-sMAIN_MODULE=2', 'main.c', 'libside.wasm', '-sNO_AUTOLOAD_DYLIBS'])
self.assertContained('done', self.run_js('a.out.js'))
# Repeat the test without NO_AUTOLOAD_DYLIBS
self.run_process([EMCC, '-g', '-sMAIN_MODULE=2', 'main.c', 'libside.wasm'])
self.assertContained('done', self.run_js('a.out.js'))

def test_dlopen_rtld_global(self):
# This test checks RTLD_GLOBAL where a module is loaded
# before the module providing a global it needs is. in asm.js we use JS
Expand Down

0 comments on commit 9e7a17c

Please sign in to comment.