Skip to content

Commit 831f8dd

Browse files
authored
Apply data relocation before calling static constructors. (#17308)
Until now we have applied data reloctions at the beginning of `__wasm_call_ctors`. However, in #17295, it was observed that this is not valid, since relocation need to be applied to all loaded libraries before any static constructor can be run. To deal with this issue we now export `__wasm_apply_data_relocs` separately and call this function on all libraries before calling any `__wasm_call_ctors` function. This change must land before the corresponding llvm-side change: https://reviews.llvm.org/D128515. The tests for this change are temporarily disabled until the llvm change gets rolled in.
1 parent e5a14ac commit 831f8dd

File tree

4 files changed

+47
-3
lines changed

4 files changed

+47
-3
lines changed

emcc.py

+5
Original file line numberDiff line numberDiff line change
@@ -2094,6 +2094,11 @@ def phase_linker_setup(options, state, newargs, user_settings):
20942094
# in standalone mode, crt1 will call the constructors from inside the wasm
20952095
settings.REQUIRED_EXPORTS.append('__wasm_call_ctors')
20962096

2097+
if settings.RELOCATABLE:
2098+
# TODO(https://reviews.llvm.org/D128515): Make this mandatory once
2099+
# llvm change lands
2100+
settings.EXPORT_IF_DEFINED.append('__wasm_apply_data_relocs')
2101+
20972102
if settings.RELOCATABLE and not settings.DYNAMIC_EXECUTION:
20982103
exit_with_error('cannot have both DYNAMIC_EXECUTION=0 and RELOCATABLE enabled at the same time, since RELOCATABLE needs to eval()')
20992104

src/library_dylink.js

+8
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,14 @@ var LibraryDylink = {
654654
__ATINIT__.push(init);
655655
}
656656
}
657+
var applyRelocs = moduleExports['__wasm_apply_data_relocs'];
658+
if (applyRelocs) {
659+
if (runtimeInitialized) {
660+
applyRelocs();
661+
} else {
662+
__RELOC_FUNCS__.push(applyRelocs);
663+
}
664+
}
657665
#if USE_PTHREADS
658666
}
659667
#endif

src/preamble.js

+11
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,10 @@ var __ATMAIN__ = []; // functions called when main() is to be run
338338
var __ATEXIT__ = []; // functions called during shutdown
339339
var __ATPOSTRUN__ = []; // functions called after the main() is called
340340

341+
#if RELOCATABLE
342+
var __RELOC_FUNCS__ = [];
343+
#endif
344+
341345
var runtimeInitialized = false;
342346

343347
#if EXIT_RUNTIME
@@ -393,6 +397,9 @@ function initRuntime() {
393397
err('__set_stack_limits: ' + _emscripten_stack_get_base() + ', ' + _emscripten_stack_get_end());
394398
#endif
395399
___set_stack_limits(_emscripten_stack_get_base(), _emscripten_stack_get_end());
400+
#endif
401+
#if RELOCATABLE
402+
callRuntimeCallbacks(__RELOC_FUNCS__);
396403
#endif
397404
<<< ATINITS >>>
398405
callRuntimeCallbacks(__ATINIT__);
@@ -1051,6 +1058,10 @@ function createWasm() {
10511058
addOnInit(Module['asm']['__wasm_call_ctors']);
10521059
#endif
10531060

1061+
#if hasExportedFunction('___wasm_apply_data_relocs')
1062+
__RELOC_FUNCS__.push(Module['asm']['__wasm_apply_data_relocs']);
1063+
#endif
1064+
10541065
#if ABORT_ON_WASM_EXCEPTIONS
10551066
instrumentWasmTableWithAbort();
10561067
#endif

tests/test_other.py

+23-3
Original file line numberDiff line numberDiff line change
@@ -1808,11 +1808,18 @@ def test_dylink_pthread_bigint_em_js(self):
18081808
self.do_runf(test_file('core/test_em_js.cpp'))
18091809

18101810
@node_pthreads
1811-
def test_dylink_pthread_comdat(self):
1811+
@parameterized({
1812+
'': (False,),
1813+
'flipped': (True,),
1814+
})
1815+
def test_dylink_pthread_comdat(self, flipped):
18121816
# Test that the comdat info for `Foo`, which is defined in the side module,
18131817
# is visible to the main module.
18141818
create_file('foo.h', r'''
18151819
struct Foo {
1820+
Foo() {
1821+
method();
1822+
}
18161823
// Making this method virtual causes the comdat group for the
18171824
// class to only be defined in the side module.
18181825
virtual void method() const;
@@ -1823,6 +1830,12 @@ def test_dylink_pthread_comdat(self):
18231830
#include <typeinfo>
18241831
#include <emscripten/console.h>
18251832
1833+
// Foo constructor calls a virtual function, with the vtable defined
1834+
// in the side module. This verifies that the side module's data
1835+
// reloctions are applied before calling static constructors in the
1836+
// main module.
1837+
Foo g_foo;
1838+
18261839
int main() {
18271840
_emscripten_outf("main: Foo typeid: %s", typeid(Foo).name());
18281841
@@ -1839,14 +1852,21 @@ def test_dylink_pthread_comdat(self):
18391852
_emscripten_outf("side: Foo typeid: %s", typeid(Foo).name());
18401853
}
18411854
''')
1855+
if flipped:
1856+
side = 'main.cpp'
1857+
main = 'side.cpp'
1858+
else:
1859+
self.skipTest('https://reviews.llvm.org/D128515')
1860+
side = 'side.cpp'
1861+
main = 'main.cpp'
18421862
self.run_process([
18431863
EMCC,
18441864
'-o', 'libside.wasm',
1845-
'side.cpp',
1865+
side,
18461866
'-pthread', '-Wno-experimental',
18471867
'-sSIDE_MODULE=1'])
18481868
self.do_runf(
1849-
'main.cpp',
1869+
main,
18501870
'main: Foo typeid: 3Foo\nside: Foo typeid: 3Foo\n',
18511871
emcc_args=[
18521872
'-pthread', '-Wno-experimental',

0 commit comments

Comments
 (0)