From c1d7d037ae40653cd2e9c8261f34d9cde3da1e52 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 16 Dec 2022 10:45:31 -0800 Subject: [PATCH] Allow taking address of EM_JS functions with dynamic linking Fixes: #18370 --- emscripten.py | 14 +++++++++----- test/core/test_em_js_address_taken.c | 11 +++++++++++ test/core/test_em_js_address_taken.out | 2 ++ test/test_core.py | 5 +++++ 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 test/core/test_em_js_address_taken.c create mode 100644 test/core/test_em_js_address_taken.out diff --git a/emscripten.py b/emscripten.py index bb53b81f34b76..16f973bc1b095 100644 --- a/emscripten.py +++ b/emscripten.py @@ -135,6 +135,8 @@ def update_settings_glue(wasm_file, metadata): get_weak_imports(wasm_file) settings.WASM_EXPORTS = metadata.exports + list(metadata.namedGlobals.keys()) + settings.WASM_EXPORTS += list(metadata.emJsFuncs.keys()) + # Store function exports so that Closure and metadce can track these even in # -sDECLARE_ASM_MODULE_EXPORTS=0 builds. settings.WASM_FUNCTION_EXPORTS = metadata.exports @@ -328,7 +330,8 @@ def emscript(in_wasm, out_wasm, outfile_js, memfile): with webassembly.Module(in_wasm) as module: types = module.get_types() for imp in module.get_imports(): - import_map[imp.field] = imp + if imp.module not in ('GOT.mem', 'GOT.func'): + import_map[imp.field] = imp for em_js_func, raw in metadata.emJsFuncs.items(): c_sig = raw.split('<::>')[0].strip('()') @@ -613,10 +616,11 @@ def create_em_js(metadata): args = args.split(',') arg_names = [arg.split()[-1].replace("*", "") for arg in args if arg] args = ','.join(arg_names) - func = f'function {name}({args}) {body}' - if settings.ASYNCIFY == 2 and name in metadata.emJsFuncTypes: + mangled = asmjs_mangle(name) + func = f'function {mangled}({args}) {body}' + if (settings.MAIN_MODULE or settings.ASYNCIFY == 2) and name in metadata.emJsFuncTypes: sig = func_type_to_sig(metadata.emJsFuncTypes[name]) - func = func + f'\n{name}.sig = \'{sig}\';' + func = func + f'\n{mangled}.sig = \'{sig}\';' em_js_funcs.append(func) return em_js_funcs @@ -676,7 +680,7 @@ def create_sending(invoke_funcs, metadata): send_items_map = {} for name in metadata.emJsFuncs: - send_items_map[name] = name + send_items_map[name] = asmjs_mangle(name) for name in invoke_funcs: send_items_map[name] = name for name in metadata.imports: diff --git a/test/core/test_em_js_address_taken.c b/test/core/test_em_js_address_taken.c new file mode 100644 index 0000000000000..7ce2f057a4971 --- /dev/null +++ b/test/core/test_em_js_address_taken.c @@ -0,0 +1,11 @@ +#include + +EM_JS(void, foobar, (), {console.error("foobar called");}); + +void(*func_ptr)() = &foobar; + +int main() { + foobar(); + func_ptr(); + return 0; +} diff --git a/test/core/test_em_js_address_taken.out b/test/core/test_em_js_address_taken.out new file mode 100644 index 0000000000000..ea0ccd82ebf9d --- /dev/null +++ b/test/core/test_em_js_address_taken.out @@ -0,0 +1,2 @@ +foobar called +foobar called diff --git a/test/test_core.py b/test/test_core.py index c541c54934c93..bd624bad0ea93 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -2294,6 +2294,11 @@ def test_em_js_i64(self): self.node_args += shared.node_bigint_flags() self.do_core_test('test_em_js_i64.c') + def test_em_js_address_taken(self): + self.do_core_test('test_em_js_address_taken.c') + self.set_setting('MAIN_MODULE', 2) + self.do_core_test('test_em_js_address_taken.c') + def test_runtime_stacksave(self): self.do_runf(test_file('core/test_runtime_stacksave.c'), 'success')