Skip to content

Commit 73fc816

Browse files
authored
Exclude __cxa_atexit definition from LTO (#16923)
See #16836
1 parent cab99e5 commit 73fc816

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

tests/other/test_lto_atexit.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <stdio.h>
2+
3+
// In Wasm destructors get lowered to constructors that call `__cxa_atexit`.
4+
//
5+
// Because this lowering happens during compilation this symbol cannot itself be
6+
// compiled as LTO (since generated new references to LTO symbols at LTO time
7+
// results int link failure). We had a bug where this symbol was itself LTO
8+
// which can cause link failures.
9+
//
10+
// See: https://github.com/emscripten-core/emscripten/issues/16836
11+
void my_dtor() __attribute__((destructor));
12+
13+
void my_dtor() {
14+
printf("my_dtor\n");
15+
}
16+
17+
int main() {
18+
printf("main done\n");
19+
return 0;
20+
}

tests/test_other.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11963,3 +11963,14 @@ def test_no_cfi(self):
1196311963
@also_with_wasm_bigint
1196411964
def test_parseTools(self):
1196511965
self.do_other_test('test_parseTools.c', emcc_args=['--js-library', test_file('other/test_parseTools.js')])
11966+
11967+
def test_lto_atexit(self):
11968+
self.emcc_args.append('-flto')
11969+
11970+
# Without EXIT_RUNTIME we don't expect the dtor to run at all
11971+
output = self.do_runf(test_file('other/test_lto_atexit.c'), 'main done')
11972+
self.assertNotContained('my_dtor', output)
11973+
11974+
# With EXIT_RUNTIME we expect to see the dtor running.
11975+
self.set_setting('EXIT_RUNTIME')
11976+
self.do_runf(test_file('other/test_lto_atexit.c'), 'main done\nmy_dtor\n')

tools/system_libs.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,9 @@ class libcompiler_rt(MTLibrary, SjLjLibrary):
714714

715715
class libnoexit(Library):
716716
name = 'libnoexit'
717+
# __cxa_atexit calls can be generated during LTO the implemenation cannot
718+
# itself be LTO. See `get_libcall_files` below for more details.
719+
force_object_files = True
717720
src_dir = 'system/lib/libc'
718721
src_files = ['atexit_dummy.c']
719722

@@ -780,6 +783,10 @@ def get_libcall_files(self):
780783
]
781784
math_files = files_in_path(path='system/lib/libc/musl/src/math', filenames=math_files)
782785

786+
exit_files = files_in_path(
787+
path='system/lib/libc/musl/src/exit',
788+
filenames=['atexit.c'])
789+
783790
other_files = files_in_path(
784791
path='system/lib/libc',
785792
filenames=['emscripten_memcpy.c', 'emscripten_memset.c',
@@ -802,7 +809,7 @@ def get_libcall_files(self):
802809
iprintf_files += files_in_path(
803810
path='system/lib/libc/musl/src/string',
804811
filenames=['strlen.c'])
805-
return math_files + other_files + iprintf_files
812+
return math_files + exit_files + other_files + iprintf_files
806813

807814
def get_files(self):
808815
libc_files = []

0 commit comments

Comments
 (0)