Skip to content

Commit aae3ad8

Browse files
kripkenbelraquib
authored andcommitted
Fix i64-using function pointers in upstream dynamic linking (emscripten-core#9810)
The dynamic loader needs to place the original wasm functions in the table, so that other modules can call them. The JS-legalized versions will have the wrong types for indirect calls. To implement this, binaryen's legalization pass exports illegal functions twice, once legalized for JS, and once as orig$ plus the original name. This PR makes the loader use those. Fixes emscripten-core#9562
1 parent 41bcf84 commit aae3ad8

File tree

6 files changed

+245
-9
lines changed

6 files changed

+245
-9
lines changed

emscripten.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,18 +1798,26 @@ def create_fp_accessors(metadata):
17981798
'perhaps a side module was not linked in? if this symbol was expected to arrive '
17991799
'from a system library, try to build the MAIN_MODULE with '
18001800
'EMCC_FORCE_STDLIBS=XX in the environment");')
1801+
# the name of the original function is generally the normal function
1802+
# name, unless it is legalized, in which case the export is the legalized
1803+
# version, and the original provided by orig$X
1804+
if shared.Settings.LEGALIZE_JS_FFI and not shared.JS.is_legal_sig(sig):
1805+
name = 'orig$' + name
18011806

18021807
accessors.append('''
18031808
Module['%(full)s'] = function() {
18041809
%(assert)s
1805-
var func = Module['%(mangled)s'];
1806-
if (!func)
1807-
func = %(mangled)s;
1810+
// Use the wasm function itself, for the table.
1811+
var func = Module['asm']['%(original)s'];
1812+
// If there is no wasm function, this may be a JS library function or
1813+
// something from another module.
1814+
if (!func) func = Module['%(mangled)s'];
1815+
if (!func) func = %(mangled)s;
18081816
var fp = addFunction(func, '%(sig)s');
18091817
Module['%(full)s'] = function() { return fp };
18101818
return fp;
18111819
}
1812-
''' % {'full': asmjs_mangle(fullname), 'mangled': mangled, 'assert': assertion, 'sig': sig})
1820+
''' % {'full': asmjs_mangle(fullname), 'mangled': mangled, 'original': name, 'assert': assertion, 'sig': sig})
18131821

18141822
return '\n'.join(accessors)
18151823

@@ -2319,6 +2327,11 @@ def debug_copy(src, dst):
23192327
args.append('--check-stack-overflow')
23202328
if shared.Settings.STANDALONE_WASM:
23212329
args.append('--standalone-wasm')
2330+
# When we dynamically link our JS loader adds functions from wasm modules to
2331+
# the table. It must add the original versions of them, not legalized ones,
2332+
# so that indirect calls have the right type, so export those.
2333+
if shared.Settings.RELOCATABLE:
2334+
args.append('--pass-arg=legalize-js-interface-export-originals')
23222335
stdout = shared.Building.run_binaryen_command('wasm-emscripten-finalize',
23232336
infile=base_wasm,
23242337
outfile=wasm,

src/support.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,10 @@ function loadWebAssemblyModule(binary, flags) {
436436
// b) Symbols from loaded modules are not always added to the global Module.
437437
var moduleLocal = {};
438438

439-
var resolveSymbol = function(sym, type) {
439+
var resolveSymbol = function(sym, type, legalized) {
440+
if (legalized) {
441+
sym = 'orig$' + sym;
442+
}
440443
#if WASM_BACKEND
441444
sym = '_' + sym;
442445
#endif
@@ -496,10 +499,11 @@ function loadWebAssemblyModule(binary, flags) {
496499
assert(parts.length == 3)
497500
var name = parts[1];
498501
var sig = parts[2];
502+
var legalized = sig.indexOf('j') >= 0; // check for i64s
499503
var fp = 0;
500504
return obj[prop] = function() {
501505
if (!fp) {
502-
var f = resolveSymbol(name, 'function');
506+
var f = resolveSymbol(name, 'function', legalized);
503507
fp = addFunction(f, sig);
504508
}
505509
return fp;

tests/other/metadce/hello_world_O3_MAIN_MODULE.exports

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,215 @@ opterr
11151115
optind
11161116
optopt
11171117
optreset
1118+
orig$__addtf3
1119+
orig$__ashldi3
1120+
orig$__ashlti3
1121+
orig$__ashrdi3
1122+
orig$__ashrti3
1123+
orig$__atomic_compare_exchange_16
1124+
orig$__atomic_compare_exchange_8
1125+
orig$__atomic_exchange_16
1126+
orig$__atomic_exchange_8
1127+
orig$__atomic_fetch_add_16
1128+
orig$__atomic_fetch_add_8
1129+
orig$__atomic_fetch_and_16
1130+
orig$__atomic_fetch_and_8
1131+
orig$__atomic_fetch_or_16
1132+
orig$__atomic_fetch_or_8
1133+
orig$__atomic_fetch_sub_16
1134+
orig$__atomic_fetch_sub_8
1135+
orig$__atomic_fetch_xor_16
1136+
orig$__atomic_fetch_xor_8
1137+
orig$__atomic_load_8
1138+
orig$__atomic_store_16
1139+
orig$__atomic_store_8
1140+
orig$__clzti2
1141+
orig$__cosl
1142+
orig$__divdi3
1143+
orig$__divmoddi4
1144+
orig$__divtf3
1145+
orig$__divti3
1146+
orig$__eqtf2
1147+
orig$__fixdfdi
1148+
orig$__fixtfdi
1149+
orig$__fixtfsi
1150+
orig$__fixtfti
1151+
orig$__fixunsdfdi
1152+
orig$__fixunstfdi
1153+
orig$__fixunstfsi
1154+
orig$__fixunstfti
1155+
orig$__floatdidf
1156+
orig$__floatditf
1157+
orig$__floattidf
1158+
orig$__floattisf
1159+
orig$__floattitf
1160+
orig$__floatunditf
1161+
orig$__floatuntidf
1162+
orig$__floatuntisf
1163+
orig$__fpclassifyl
1164+
orig$__fseeko
1165+
orig$__fseeko_unlocked
1166+
orig$__ftello
1167+
orig$__ftello_unlocked
1168+
orig$__getf2
1169+
orig$__gttf2
1170+
orig$__intscan
1171+
orig$__invtrigl_R
1172+
orig$__letf2
1173+
orig$__lgammal_r
1174+
orig$__lshrdi3
1175+
orig$__lshrti3
1176+
orig$__lttf2
1177+
orig$__mmap
1178+
orig$__moddi3
1179+
orig$__modti3
1180+
orig$__muldi3
1181+
orig$__multc3
1182+
orig$__multf3
1183+
orig$__multi3
1184+
orig$__netf2
1185+
orig$__p1evll
1186+
orig$__polevll
1187+
orig$__rand48_step
1188+
orig$__rem_pio2l
1189+
orig$__shlim
1190+
orig$__signbitl
1191+
orig$__sinl
1192+
orig$__stdio_seek
1193+
orig$__strtoimax_internal
1194+
orig$__strtoll_internal
1195+
orig$__strtoull_internal
1196+
orig$__strtoumax_internal
1197+
orig$__subtf3
1198+
orig$__tanl
1199+
orig$__trunctfdf2
1200+
orig$__trunctfsf2
1201+
orig$__udivdi3
1202+
orig$__udivmoddi4
1203+
orig$__udivmodti4
1204+
orig$__udivti3
1205+
orig$__umoddi3
1206+
orig$__umodti3
1207+
orig$__unordtf2
1208+
orig$__uremdi3
1209+
orig$_emscripten_atomic_fetch_and_add_u64
1210+
orig$_emscripten_atomic_fetch_and_and_u64
1211+
orig$_emscripten_atomic_fetch_and_or_u64
1212+
orig$_emscripten_atomic_fetch_and_sub_u64
1213+
orig$_emscripten_atomic_fetch_and_xor_u64
1214+
orig$acoshl
1215+
orig$acosl
1216+
orig$asinhl
1217+
orig$asinl
1218+
orig$atan2l
1219+
orig$atanhl
1220+
orig$atanl
1221+
orig$atoll
1222+
orig$cbrtl
1223+
orig$copysignl
1224+
orig$coshl
1225+
orig$cosl
1226+
orig$emscripten_atomic_add_u64
1227+
orig$emscripten_atomic_and_u64
1228+
orig$emscripten_atomic_cas_u64
1229+
orig$emscripten_atomic_exchange_u64
1230+
orig$emscripten_atomic_load_u64
1231+
orig$emscripten_atomic_or_u64
1232+
orig$emscripten_atomic_store_u64
1233+
orig$emscripten_atomic_sub_u64
1234+
orig$emscripten_atomic_xor_u64
1235+
orig$erfcl
1236+
orig$erfl
1237+
orig$exp10l
1238+
orig$exp2l
1239+
orig$expl
1240+
orig$expm1l
1241+
orig$fdiml
1242+
orig$ffsll
1243+
orig$fmal
1244+
orig$fmaxl
1245+
orig$fminl
1246+
orig$fmodl
1247+
orig$frexpl
1248+
orig$fseeko
1249+
orig$fseeko64
1250+
orig$ftello
1251+
orig$ftello64
1252+
orig$ftruncate
1253+
orig$ftruncate64
1254+
orig$hypotl
1255+
orig$ilogbl
1256+
orig$imaxabs
1257+
orig$imaxdiv
1258+
orig$ldexpl
1259+
orig$lgammal
1260+
orig$lgammal_r
1261+
orig$llabs
1262+
orig$lldiv
1263+
orig$llrint
1264+
orig$llrintf
1265+
orig$llrintl
1266+
orig$llround
1267+
orig$llroundf
1268+
orig$llroundl
1269+
orig$lockf
1270+
orig$lockf64
1271+
orig$log10l
1272+
orig$log1pl
1273+
orig$log2l
1274+
orig$logbl
1275+
orig$logl
1276+
orig$lrintl
1277+
orig$lroundl
1278+
orig$lseek
1279+
orig$lseek64
1280+
orig$mmap
1281+
orig$mmap64
1282+
orig$modfl
1283+
orig$nearbyintl
1284+
orig$nextafterl
1285+
orig$nexttoward
1286+
orig$nexttowardf
1287+
orig$nexttowardl
1288+
orig$posix_fadvise
1289+
orig$posix_fadvise64
1290+
orig$posix_fallocate
1291+
orig$posix_fallocate64
1292+
orig$pow10l
1293+
orig$powl
1294+
orig$pread
1295+
orig$pread64
1296+
orig$preadv
1297+
orig$preadv64
1298+
orig$pwrite
1299+
orig$pwrite64
1300+
orig$pwritev
1301+
orig$pwritev64
1302+
orig$remainderl
1303+
orig$remquol
1304+
orig$rintl
1305+
orig$roundl
1306+
orig$scalblnl
1307+
orig$scalbnl
1308+
orig$sincosl
1309+
orig$sinhl
1310+
orig$sinl
1311+
orig$strtoimax
1312+
orig$strtoll
1313+
orig$strtoll_l
1314+
orig$strtoull
1315+
orig$strtoull_l
1316+
orig$strtoumax
1317+
orig$tanhl
1318+
orig$tanl
1319+
orig$tgammal
1320+
orig$truncate
1321+
orig$truncate64
1322+
orig$truncl
1323+
orig$wcstoimax
1324+
orig$wcstoll
1325+
orig$wcstoull
1326+
orig$wcstoumax
11181327
pause
11191328
pclose
11201329
perror

tests/test_core.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3893,9 +3893,15 @@ def test_dylink_i64_b(self):
38933893
#include <stdio.h>
38943894
#include <stdint.h>
38953895
extern int64_t sidey();
3896+
int64_t testAdd(int64_t a) {
3897+
return a + 1;
3898+
}
3899+
typedef int64_t (*testAddHandler)(int64_t);
3900+
testAddHandler h = &testAdd;
38963901
int main() {
38973902
printf("other says %lld.\n", sidey());
3898-
return 0;
3903+
int64_t r = h(42);
3904+
printf("my fp says: %lld.\n", r);
38993905
}
39003906
''', '''
39013907
#include <stdint.h>
@@ -3905,7 +3911,7 @@ def test_dylink_i64_b(self):
39053911
x = 18 - x;
39063912
return x;
39073913
}
3908-
''', 'other says -1311768467750121224.')
3914+
''', 'other says -1311768467750121224.\nmy fp says: 43.')
39093915

39103916
@needs_dlfcn
39113917
def test_dylink_class(self):

tests/test_other.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8171,7 +8171,7 @@ def test_metadce_cxx_fastcomp(self, *args):
81718171
# don't compare the # of functions in a main module, which changes a lot
81728172
# TODO(sbc): Investivate why the number of exports is order of magnitude
81738173
# larger for wasm backend.
8174-
'main_module_1': (['-O3', '-s', 'MAIN_MODULE=1'], 174, [], [], 517336, None, 1520, None), # noqa
8174+
'main_module_1': (['-O3', '-s', 'MAIN_MODULE=1'], 174, [], [], 517336, None, 1729, None), # noqa
81758175
'main_module_2': (['-O3', '-s', 'MAIN_MODULE=2'], 12, [], [], 10770, 12, 10, None), # noqa
81768176
})
81778177
@no_fastcomp()

tools/shared.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3025,6 +3025,10 @@ def legalize_sig(sig):
30253025
ret.append('i')
30263026
return ''.join(ret)
30273027

3028+
@staticmethod
3029+
def is_legal_sig(sig):
3030+
return sig == JS.legalize_sig(sig)
3031+
30283032
@staticmethod
30293033
def make_extcall(sig, named=True):
30303034
args = ','.join(['a' + str(i) for i in range(1, len(sig))])

0 commit comments

Comments
 (0)