#if !RELOCATABLE
#error "library_dylink.js requires RELOCATABLE"
#endif
var LibraryDylink = {
#if FILESYSTEM
$registerWasmPlugin__deps: ['$preloadPlugins'],
$registerWasmPlugin: () => {
var wasmPlugin = {
promiseChainEnd: Promise.resolve(),
'canHandle': (name) => {
return !Module['noWasmDecoding'] && name.endsWith('.so')
},
'handle': async (byteArray, name) =>
wasmPlugin.promiseChainEnd = wasmPlugin.promiseChainEnd.then(async () => {
try {
var exports = await loadWebAssemblyModule(byteArray, {loadAsync: true, nodelete: true}, name, {});
} catch (error) {
throw new Error(`failed to instantiate wasm: ${name}: ${error}`);
}
#if DYLINK_DEBUG
dbg('registering preloadedWasm:', name);
#endif
preloadedWasm[name] = exports;
return byteArray;
})
};
preloadPlugins.push(wasmPlugin);
},
$preloadedWasm__deps: ['$registerWasmPlugin'],
$preloadedWasm__postset: `
registerWasmPlugin();
`,
$preloadedWasm: {},
$replaceORIGIN__deps: ['$PATH'],
$replaceORIGIN: (parentLibName, rpath) => {
if (rpath.startsWith('$ORIGIN')) {
var origin = PATH.dirname(parentLibName);
return rpath.replace('$ORIGIN', origin);
}
return rpath;
},
#endif
$isSymbolDefined: (symName) => {
var existing = wasmImports[symName];
if (!existing || existing.stub) {
return false;
}
#if ASYNCIFY
if (symName in asyncifyStubs && !asyncifyStubs[symName]) {
return false;
}
#endif
return true;
},
#if !DISABLE_EXCEPTION_CATCHING || SUPPORT_LONGJMP == 'emscripten'
$createInvokeFunction__internal: true,
$createInvokeFunction__deps: ['$dynCall', 'setThrew', '$stackSave', '$stackRestore'],
$createInvokeFunction: (sig) => (ptr, ...args) => {
var sp = stackSave();
try {
return dynCall(sig, ptr, args);
} catch(e) {
stackRestore(sp);
#if EXCEPTION_STACK_TRACES
if (!(e instanceof EmscriptenEH)) throw e;
#else
if (e !== e+0) throw e;
#endif
_setThrew(1, 0);
#if WASM_BIGINT
if (sig[0] == "j") return 0n;
#endif
}
},
#endif
$resolveGlobalSymbol__deps: ['$isSymbolDefined',
#if !DISABLE_EXCEPTION_CATCHING || SUPPORT_LONGJMP == 'emscripten'
'$createInvokeFunction',
#endif
],
$resolveGlobalSymbol__internal: true,
$resolveGlobalSymbol: (symName, direct = false) => {
var sym;
#if !WASM_BIGINT
if (direct && ('orig$' + symName in wasmImports)) {
symName = 'orig$' + symName;
}
#endif
if (isSymbolDefined(symName)) {
sym = wasmImports[symName];
}
#if !DISABLE_EXCEPTION_CATCHING || SUPPORT_LONGJMP == 'emscripten'
else if (symName.startsWith('invoke_')) {
sym = wasmImports[symName] = createInvokeFunction(symName.split('_')[1]);
}
#endif
#if !DISABLE_EXCEPTION_CATCHING
else if (symName.startsWith('__cxa_find_matching_catch_')) {
sym = wasmImports[symName] = (...args) => {
#if MEMORY64
args = args.map(Number);
#endif
var rtn = findMatchingCatch(args);
return {{{ to64('rtn') }}};
}
}
#endif
return {sym, name: symName};
},
$GOT: {},
$currentModuleWeakSymbols: '=new Set({{{ JSON.stringify(Array.from(WEAK_IMPORTS)) }}})',
$GOTHandler__internal: true,
$GOTHandler__deps: ['$GOT', '$currentModuleWeakSymbols'],
$GOTHandler: {
get(obj, symName) {
var rtn = GOT[symName];
if (!rtn) {
rtn = GOT[symName] = new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true});
#if DYLINK_DEBUG == 2
dbg("new GOT entry: " + symName);
#endif
}
if (!currentModuleWeakSymbols.has(symName)) {
rtn.required = true;
}
return rtn;
}
},
$isInternalSym__internal: true,
$isInternalSym: (symName) => {
return [
'__cpp_exception',
'__c_longjmp',
'__wasm_apply_data_relocs',
'__dso_handle',
'__tls_size',
'__tls_align',
'__set_stack_limits',
'_emscripten_tls_init',
'__wasm_init_tls',
'__wasm_call_ctors',
'__start_em_asm',
'__stop_em_asm',
'__start_em_js',
'__stop_em_js',
].includes(symName) || symName.startsWith('__em_js__')
#if SPLIT_MODULE
|| symName[0] == '%'
#endif
;
},
$updateGOT__internal: true,
$updateGOT__deps: ['$GOT', '$isInternalSym', '$addFunction'],
$updateGOT: (exports, replace) => {
#if DYLINK_DEBUG
dbg(`updateGOT: adding ${Object.keys(exports).length} symbols`);
#endif
for (var symName in exports) {
if (isInternalSym(symName)) {
continue;
}
var value = exports[symName];
#if !WASM_BIGINT
if (symName.startsWith('orig$')) {
symName = symName.split('$')[1];
replace = true;
}
#endif
GOT[symName] ||= new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true});
if (replace || GOT[symName].value == 0) {
#if DYLINK_DEBUG == 2
dbg(`updateGOT: before: ${symName} : ${GOT[symName].value}`);
#endif
if (typeof value == 'function') {
GOT[symName].value = {{{ to64('addFunction(value)') }}};
#if DYLINK_DEBUG == 2
dbg(`updateGOT: FUNC: ${symName} : ${GOT[symName].value}`);
#endif
} else if (typeof value == {{{ POINTER_JS_TYPE }}}) {
GOT[symName].value = value;
} else {
err(`unhandled export type for '${symName}': ${typeof value}`);
}
#if DYLINK_DEBUG == 2
dbg(`updateGOT: after: ${symName} : ${GOT[symName].value} (${value})`);
#endif
}
#if DYLINK_DEBUG
else if (GOT[symName].value != value) {
dbg(`updateGOT: EXISTING SYMBOL: ${symName} : ${GOT[symName].value} (${value})`);
}
#endif
}
#if DYLINK_DEBUG
dbg("done updateGOT");
#endif
},
$relocateExports__internal: true,
$relocateExports__deps: ['$updateGOT'],
$relocateExports__docs: '/** @param {boolean=} replace */',
$relocateExports: (exports, memoryBase, replace) => {
var relocated = {};
for (var e in exports) {
var value = exports[e];
#if SPLIT_MODULE
if (e.startsWith('%')) {
relocated[e] = value
continue;
}
#endif
if (typeof value == 'object') {
value = value.value;
}
if (typeof value == {{{ POINTER_JS_TYPE }}}) {
value += {{{ to64('memoryBase') }}};
}
relocated[e] = value;
}
updateGOT(relocated, replace);
return relocated;
},
$reportUndefinedSymbols__internal: true,
$reportUndefinedSymbols__deps: ['$GOT', '$resolveGlobalSymbol'],
$reportUndefinedSymbols: () => {
#if DYLINK_DEBUG
dbg('reportUndefinedSymbols');
#endif
for (var [symName, entry] of Object.entries(GOT)) {
if (entry.value == 0) {
var value = resolveGlobalSymbol(symName, true).sym;
if (!value && !entry.required) {
#if DYLINK_DEBUG
dbg('ignoring undefined weak symbol:', symName);
#endif
continue;
}
#if ASSERTIONS
assert(value, `undefined symbol '${symName}'. perhaps a side module was not linked in? if this global was expected to arrive from a system library, try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment`);
#endif
#if DYLINK_DEBUG == 2
dbg(`assigning dynamic symbol from main module: ${symName} -> ${prettyPrint(value)}`);
#endif
if (typeof value == 'function') {
entry.value = {{{ to64('addFunction(value, value.sig)') }}};
#if DYLINK_DEBUG == 2
dbg(`assigning table entry for : ${symName} -> ${entry.value}`);
#endif
} else if (typeof value == 'number') {
entry.value = {{{ to64('value') }}};
#if MEMORY64
} else if (typeof value == 'bigint') {
entry.value = value;
#endif
} else {
throw new Error(`bad export type for '${symName}': ${typeof value}`);
}
}
}
#if DYLINK_DEBUG
dbg('done reportUndefinedSymbols');
#endif
},
$LDSO__deps: ['$newDSO'],
$LDSO: {
loadedLibsByName: {},
loadedLibsByHandle: {},
init() {
#if ASSERTIONS
assert(wasmImports);
#endif
newDSO('__main__', {{{ cDefs.RTLD_DEFAULT }}}, wasmImports);
},
},
$dlSetError__internal: true,
$dlSetError__deps: ['__dl_seterr', '$stringToUTF8OnStack', '$stackSave', '$stackRestore'],
$dlSetError: (msg) => {
#if DYLINK_DEBUG
dbg('dlSetError:', msg);
#endif
var sp = stackSave();
var cmsg = stringToUTF8OnStack(msg);
___dl_seterr(cmsg, 0);
stackRestore(sp);
},
$getMemory__noleakcheck: true,
$getMemory__deps: ['$GOT', '__heap_base', '$alignMemory', 'calloc'],
$getMemory: (size) => {
#if DYLINK_DEBUG
dbg("getMemory: " + size + " runtimeInitialized=" + runtimeInitialized);
#endif
if (runtimeInitialized) {
return _calloc(size, 1);
}
var ret = ___heap_base;
var end = ret + alignMemory(size, {{{ STACK_ALIGN }}});
#if ASSERTIONS
assert(end <= HEAP8.length, 'failure to getMemory - memory growth etc. is not supported there, call malloc/sbrk directly or increase INITIAL_MEMORY');
#endif
___heap_base = end;
GOT['__heap_base'].value = {{{ to64('end') }}};
return ret;
},
$getDylinkMetadata__deps: ['$UTF8ArrayToString'],
$getDylinkMetadata__internal: true,
$getDylinkMetadata: (binary) => {
var offset = 0;
var end = 0;
function getU8() {
return binary[offset++];
}
function getLEB() {
var ret = 0;
var mul = 1;
while (1) {
var byte = binary[offset++];
ret += ((byte & 0x7f) * mul);
mul *= 0x80;
if (!(byte & 0x80)) break;
}
return ret;
}
function getString() {
var len = getLEB();
offset += len;
return UTF8ArrayToString(binary, offset - len, len);
}
function getStringList() {
var count = getLEB();
var rtn = []
while (count--) rtn.push(getString());
return rtn;
}
function failIf(condition, message) {
if (condition) throw new Error(message);
}
if (binary instanceof WebAssembly.Module) {
var dylinkSection = WebAssembly.Module.customSections(binary, 'dylink.0');
failIf(dylinkSection.length === 0, 'need dylink section');
binary = new Uint8Array(dylinkSection[0]);
end = binary.length
} else {
var int32View = new Uint32Array(new Uint8Array(binary.subarray(0, 24)).buffer);
#if SUPPORT_BIG_ENDIAN
var magicNumberFound = int32View[0] == 0x6d736100 || int32View[0] == 0x0061736d;
#else
var magicNumberFound = int32View[0] == 0x6d736100;
#endif
failIf(!magicNumberFound, 'need to see wasm magic number');
failIf(binary[8] !== 0, 'need the dylink section to be first')
offset = 9;
var section_size = getLEB();
end = offset + section_size;
var name = getString();
failIf(name !== 'dylink.0');
}
var customSection = { neededDynlibs: [], tlsExports: new Set(), weakImports: new Set(), runtimePaths: [] };
var WASM_DYLINK_MEM_INFO = 0x1;
var WASM_DYLINK_NEEDED = 0x2;
var WASM_DYLINK_EXPORT_INFO = 0x3;
var WASM_DYLINK_IMPORT_INFO = 0x4;
var WASM_DYLINK_RUNTIME_PATH = 0x5;
var WASM_SYMBOL_TLS = 0x100;
var WASM_SYMBOL_BINDING_MASK = 0x3;
var WASM_SYMBOL_BINDING_WEAK = 0x1;
while (offset < end) {
var subsectionType = getU8();
var subsectionSize = getLEB();
if (subsectionType === WASM_DYLINK_MEM_INFO) {
customSection.memorySize = getLEB();
customSection.memoryAlign = getLEB();
customSection.tableSize = getLEB();
customSection.tableAlign = getLEB();
} else if (subsectionType === WASM_DYLINK_NEEDED) {
customSection.neededDynlibs = getStringList();
} else if (subsectionType === WASM_DYLINK_EXPORT_INFO) {
var count = getLEB();
while (count--) {
var symname = getString();
var flags = getLEB();
if (flags & WASM_SYMBOL_TLS) {
customSection.tlsExports.add(symname);
}
}
} else if (subsectionType === WASM_DYLINK_IMPORT_INFO) {
var count = getLEB();
while (count--) {
var modname = getString();
var symname = getString();
var flags = getLEB();
if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
customSection.weakImports.add(symname);
}
}
} else if (subsectionType === WASM_DYLINK_RUNTIME_PATH) {
customSection.runtimePaths = getStringList();
} else {
#if ASSERTIONS
err('unknown dylink.0 subsection:', subsectionType)
#endif
offset += subsectionSize;
}
}
#if ASSERTIONS
var tableAlign = Math.pow(2, customSection.tableAlign);
assert(tableAlign === 1, `invalid tableAlign ${tableAlign}`);
assert(offset == end);
#endif
#if DYLINK_DEBUG
dbg('dylink needed:', customSection.neededDynlibs);
#endif
return customSection;
},
#if DYNCALLS || !WASM_BIGINT
$registerDynCallSymbols: (exports) => {
for (var [sym, exp] of Object.entries(exports)) {
if (sym.startsWith('dynCall_')) {
var sig = sym.substring(8);
if (!dynCalls.hasOwnProperty(sig)) {
dynCalls[sig] = exp;
}
}
}
},
#endif
$mergeLibSymbols__deps: ['$isSymbolDefined'],
$mergeLibSymbols: (exports, libName) => {
#if DYNCALLS || !WASM_BIGINT
registerDynCallSymbols(exports);
#endif
for (var [sym, exp] of Object.entries(exports)) {
#if ASSERTIONS == 2
if (isSymbolDefined(sym)) {
var curr = wasmImports[sym], next = exp;
if (!(typeof curr == 'function' && typeof next == 'function')) {
err(`warning: symbol '${sym}' from '${libName}' already exists (duplicate symbol? or weak linking, which isn't supported yet?)`);
}
}
#endif
const setImport = (target) => {
#if ASYNCIFY
if (target in asyncifyStubs) {
asyncifyStubs[target] = exp;
}
#endif
if (!isSymbolDefined(target)) {
wasmImports[target] = exp;
}
}
setImport(sym);
#if !hasExportedSymbol('main')
const main_alias = '__main_argc_argv';
if (sym == 'main') {
setImport(main_alias)
}
if (sym == main_alias) {
setImport('main')
}
#endif
}
},
#if DYLINK_DEBUG
$dumpTable__deps: ['$wasmTable'],
$dumpTable: () => {
var len = wasmTable.length;
for (var i = {{{ toIndexType(0) }}} ; i < len; i++) {
dbg(`table: ${i} : ${wasmTable.get(i)}`);
}
},
#endif
$loadWebAssemblyModule__docs: `
/**
* @param {string=} libName
* @param {Object=} localScope
* @param {number=} handle
*/`,
$loadWebAssemblyModule__deps: [
'$loadDynamicLibrary', '$getMemory',
'$relocateExports', '$resolveGlobalSymbol', '$GOTHandler',
'$getDylinkMetadata', '$alignMemory',
'$currentModuleWeakSymbols',
'$updateTableMap',
'$wasmTable',
'$addOnPostCtor',
],
$loadWebAssemblyModule: (binary, flags, libName, localScope, handle) => {
#if DYLINK_DEBUG
dbg('loadWebAssemblyModule:', libName);
#endif
var metadata = getDylinkMetadata(binary);
currentModuleWeakSymbols = metadata.weakImports;
#if ASSERTIONS
var originalTable = wasmTable;
#endif
function loadModule() {
#if PTHREADS
var firstLoad = !handle || !{{{ makeGetValue('handle', C_STRUCTS.dso.mem_allocated, 'i8') }}};
if (firstLoad) {
#endif
var memAlign = Math.pow(2, metadata.memoryAlign);
var memoryBase = metadata.memorySize ? alignMemory(getMemory(metadata.memorySize + memAlign), memAlign) : 0;
var tableBase = metadata.tableSize ? {{{ from64Expr('wasmTable.length') }}} : 0;
if (handle) {
{{{ makeSetValue('handle', C_STRUCTS.dso.mem_allocated, '1', 'i8') }}};
{{{ makeSetValue('handle', C_STRUCTS.dso.mem_addr, 'memoryBase', '*') }}};
{{{ makeSetValue('handle', C_STRUCTS.dso.mem_size, 'metadata.memorySize', 'i32') }}};
{{{ makeSetValue('handle', C_STRUCTS.dso.table_addr, 'tableBase', '*') }}};
{{{ makeSetValue('handle', C_STRUCTS.dso.table_size, 'metadata.tableSize', 'i32') }}};
}
#if PTHREADS
} else {
memoryBase = {{{ makeGetValue('handle', C_STRUCTS.dso.mem_addr, '*') }}};
tableBase = {{{ makeGetValue('handle', C_STRUCTS.dso.table_addr, '*') }}};
}
#endif
if (metadata.tableSize) {
#if ASSERTIONS
assert({{{ from64Expr('wasmTable.length') }}} == tableBase, `unexpected table size while loading ${libName}: ${wasmTable.length}`);
#endif
#if DYLINK_DEBUG
dbg("loadModule: growing table by: " + metadata.tableSize);
#endif
wasmTable.grow({{{ toIndexType('metadata.tableSize') }}});
}
#if DYLINK_DEBUG
dbg(`loadModule: memory[${memoryBase}:${memoryBase + metadata.memorySize}]` +
` table[${tableBase}:${tableBase + metadata.tableSize}]`);
#endif
var moduleExports;
function resolveSymbol(sym) {
var resolved = resolveGlobalSymbol(sym).sym;
if (!resolved && localScope) {
resolved = localScope[sym];
}
if (!resolved) {
resolved = moduleExports[sym];
}
#if ASSERTIONS
assert(resolved, `undefined symbol '${sym}'. perhaps a side module was not linked in? if this global was expected to arrive from a system library, try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment`);
#endif
return resolved;
}
var proxyHandler = {
get(stubs, prop) {
switch (prop) {
case '__memory_base':
return {{{ to64('memoryBase') }}};
case '__table_base':
return {{{ to64('tableBase') }}};
#if MEMORY64
#if MEMORY64 == 2
case '__memory_base32':
return memoryBase;
#endif
case '__table_base32':
return tableBase;
#endif
}
if (prop in wasmImports && !wasmImports[prop].stub) {
var res = wasmImports[prop];
#if ASYNCIFY
if (res.orig) {
res = res.orig;
}
#endif
return res;
}
if (!(prop in stubs)) {
var resolved;
stubs[prop] = (...args) => {
resolved ||= resolveSymbol(prop);
return resolved(...args);
};
}
return stubs[prop];
}
};
var proxy = new Proxy({}, proxyHandler);
var info = {
'GOT.mem': new Proxy({}, GOTHandler),
'GOT.func': new Proxy({}, GOTHandler),
'env': proxy,
'{{{ WASI_MODULE_NAME }}}': proxy,
};
function postInstantiation(module, instance) {
#if ASSERTIONS
assert(wasmTable === originalTable);
#endif
#if PTHREADS
if (!ENVIRONMENT_IS_PTHREAD && libName) {
#if DYLINK_DEBUG
dbg('registering sharedModules:', libName)
#endif
sharedModules[libName] = module;
}
#endif
updateTableMap(tableBase, metadata.tableSize);
moduleExports = relocateExports(instance.exports, memoryBase);
#if ASYNCIFY
moduleExports = Asyncify.instrumentWasmExports(moduleExports);
#endif
if (!flags.allowUndefined) {
reportUndefinedSymbols();
}
#if STACK_OVERFLOW_CHECK >= 2
if (moduleExports['__set_stack_limits'] && runtimeInitialized) {
moduleExports['__set_stack_limits']({{{ to64('_emscripten_stack_get_base()') }}}, {{{ to64('_emscripten_stack_get_end()') }}});
}
#endif
#if MAIN_MODULE
function addEmAsm(addr, body) {
var args = [];
var arity = 0;
for (; arity < 16; arity++) {
if (body.indexOf('$' + arity) != -1) {
args.push('$' + arity);
} else {
break;
}
}
args = args.join(',');
var func = `(${args}) => { ${body} };`;
#if DYLINK_DEBUG
dbg('adding new EM_ASM constant at:', ptrToString(start));
#endif
{{{ makeEval('ASM_CONSTS[start] = eval(func)') }}};
}
if ('__start_em_asm' in moduleExports) {
var start = moduleExports['__start_em_asm'];
var stop = moduleExports['__stop_em_asm'];
{{{ from64('start') }}}
{{{ from64('stop') }}}
while (start < stop) {
var jsString = UTF8ToString(start);
addEmAsm(start, jsString);
start = HEAPU8.indexOf(0, start) + 1;
}
}
function addEmJs(name, cSig, body) {
var jsArgs = [];
cSig = cSig.slice(1, -1)
if (cSig != 'void') {
cSig = cSig.split(',');
for (var i in cSig) {
var jsArg = cSig[i].split(' ').pop();
jsArgs.push(jsArg.replace('*', ''));
}
}
var func = `(${jsArgs}) => ${body};`;
#if DYLINK_DEBUG
dbg(`adding new EM_JS function: ${jsArgs} = ${func}`);
#endif
{{{ makeEval('moduleExports[name] = eval(func)') }}};
}
for (var name in moduleExports) {
if (name.startsWith('__em_js__')) {
var start = moduleExports[name]
var jsString = UTF8ToString({{{ from64Expr('start') }}});
var parts = jsString.split('<::>');
addEmJs(name.replace('__em_js__', ''), parts[0], parts[1]);
delete moduleExports[name];
}
}
#endif
#if PTHREADS
registerTLSInit(moduleExports['_emscripten_tls_init'], instance.exports, metadata)
if (firstLoad) {
#endif
var applyRelocs = moduleExports['__wasm_apply_data_relocs'];
if (applyRelocs) {
if (runtimeInitialized) {
#if DYLINK_DEBUG
dbg('applyRelocs');
#endif
applyRelocs();
} else {
__RELOC_FUNCS__.push(applyRelocs);
}
}
var init = moduleExports['__wasm_call_ctors'];
if (init) {
if (runtimeInitialized) {
init();
} else {
addOnPostCtor(init);
}
}
#if PTHREADS
}
#endif
return moduleExports;
}
if (flags.loadAsync) {
return (async () => {
var instance;
if (binary instanceof WebAssembly.Module) {
instance = new WebAssembly.Instance(binary, info);
} else {
({ module: binary, instance } = await WebAssembly.instantiate(binary, info));
}
return postInstantiation(binary, instance);
})();
}
var module = binary instanceof WebAssembly.Module ? binary : new WebAssembly.Module(binary);
var instance = new WebAssembly.Instance(module, info);
return postInstantiation(module, instance);
}
flags = {...flags, rpath: { parentLibPath: libName, paths: metadata.runtimePaths }}
if (flags.loadAsync) {
return metadata.neededDynlibs
.reduce((chain, dynNeeded) => chain.then(() =>
loadDynamicLibrary(dynNeeded, flags, localScope)
), Promise.resolve())
.then(loadModule);
}
metadata.neededDynlibs.forEach((needed) => loadDynamicLibrary(needed, flags, localScope));
return loadModule();
},
#if STACK_OVERFLOW_CHECK >= 2
$setDylinkStackLimits: (stackTop, stackMax) => {
for (var name in LDSO.loadedLibsByName) {
#if DYLINK_DEBUG
dbg(`setDylinkStackLimits for '${name}'`);
#endif
var lib = LDSO.loadedLibsByName[name];
lib.exports['__set_stack_limits']?.({{{ to64("stackTop") }}}, {{{ to64("stackMax") }}});
}
},
#endif
$newDSO: (name, handle, syms) => {
var dso = {
refcount: Infinity,
name,
exports: syms,
global: true,
};
LDSO.loadedLibsByName[name] = dso;
if (handle != undefined) {
LDSO.loadedLibsByHandle[handle] = dso;
}
return dso;
},
#if FILESYSTEM
$findLibraryFS__deps: [
'$replaceORIGIN',
'_emscripten_find_dylib',
'$withStackSave',
'$stackAlloc',
'$lengthBytesUTF8',
'$stringToUTF8OnStack',
'$stringToUTF8',
'$FS',
'$PATH',
#if WASMFS
'_wasmfs_identify',
'_wasmfs_read_file',
#endif
],
$findLibraryFS: (libName, rpath) => {
if (!runtimeInitialized) {
return undefined;
}
if (PATH.isAbs(libName)) {
#if WASMFS
var result = withStackSave(() => __wasmfs_identify(stringToUTF8OnStack(libName)));
return result === {{{ cDefs.EEXIST }}} ? libName : undefined;
#else
try {
FS.lookupPath(libName);
return libName;
} catch (e) {
return undefined;
}
#endif
}
var rpathResolved = (rpath?.paths || []).map((p) => replaceORIGIN(rpath?.parentLibPath, p));
return withStackSave(() => {
var bufSize = 2*255 + 2;
var buf = stackAlloc(bufSize);
var rpathC = stringToUTF8OnStack(rpathResolved.join(':'));
var libNameC = stringToUTF8OnStack(libName);
var resLibNameC = __emscripten_find_dylib(buf, rpathC, libNameC, bufSize);
return resLibNameC ? UTF8ToString(resLibNameC) : undefined;
});
},
#endif
$loadDynamicLibrary__deps: ['$LDSO', '$loadWebAssemblyModule',
'$mergeLibSymbols', '$newDSO',
'$asyncLoad',
#if FILESYSTEM
'$preloadedWasm',
'$findLibraryFS',
#endif
#if DYNCALLS || !WASM_BIGINT
'$registerDynCallSymbols',
#endif
],
$loadDynamicLibrary__docs: `
/**
* @param {number=} handle
* @param {Object=} localScope
*/`,
$loadDynamicLibrary: function(libName, flags = {global: true, nodelete: true}, localScope, handle) {
#if DYLINK_DEBUG
dbg(`loadDynamicLibrary: ${libName} handle: ${handle}`);
dbg('existing:', Object.keys(LDSO.loadedLibsByName));
#endif
var dso = LDSO.loadedLibsByName[libName];
if (dso) {
#if ASSERTIONS
assert(dso.exports !== 'loading', `Attempt to load '${libName}' twice before the first load completed`);
#endif
if (!flags.global) {
if (localScope) {
Object.assign(localScope, dso.exports);
}
#if DYNCALLS || !WASM_BIGINT
registerDynCallSymbols(dso.exports);
#endif
} else if (!dso.global) {
dso.global = true;
mergeLibSymbols(dso.exports, libName)
}
if (flags.nodelete && dso.refcount !== Infinity) {
dso.refcount = Infinity;
}
dso.refcount++
if (handle) {
LDSO.loadedLibsByHandle[handle] = dso;
}
return flags.loadAsync ? Promise.resolve(true) : true;
}
dso = newDSO(libName, handle, 'loading');
dso.refcount = flags.nodelete ? Infinity : 1;
dso.global = flags.global;
function loadLibData() {
#if PTHREADS
var sharedMod = sharedModules[libName];
#if DYLINK_DEBUG
dbg(`checking sharedModules: ${libName}: ${sharedMod ? 'found' : 'not found'}`);
#endif
if (sharedMod) {
return flags.loadAsync ? Promise.resolve(sharedMod) : sharedMod;
}
#endif
if (handle) {
var data = {{{ makeGetValue('handle', C_STRUCTS.dso.file_data, '*') }}};
var dataSize = {{{ makeGetValue('handle', C_STRUCTS.dso.file_data_size, '*') }}};
if (data && dataSize) {
var libData = HEAP8.slice(data, data + dataSize);
return flags.loadAsync ? Promise.resolve(libData) : libData;
}
}
#if FILESYSTEM
var f = findLibraryFS(libName, flags.rpath);
#if DYLINK_DEBUG
dbg(`checking filesystem: ${libName}: ${f ? 'found' : 'not found'}`);
#endif
if (f) {
var libData = FS.readFile(f, {encoding: 'binary'});
return flags.loadAsync ? Promise.resolve(libData) : libData;
}
#endif
var libFile = locateFile(libName);
if (flags.loadAsync) {
return asyncLoad(libFile);
}
if (!readBinary) {
throw new Error(`${libFile}: file not found, and synchronous loading of external files is not available`);
}
return readBinary(libFile);
}
function getExports() {
#if FILESYSTEM
var preloaded = preloadedWasm[libName];
#if DYLINK_DEBUG
dbg(`checking preloadedWasm: ${libName}: ${preloaded ? 'found' : 'not found'}`);
#endif
if (preloaded) {
return flags.loadAsync ? Promise.resolve(preloaded) : preloaded;
}
#endif
if (flags.loadAsync) {
return loadLibData().then((libData) => loadWebAssemblyModule(libData, flags, libName, localScope, handle));
}
return loadWebAssemblyModule(loadLibData(), flags, libName, localScope, handle);
}
function moduleLoaded(exports) {
if (dso.global) {
mergeLibSymbols(exports, libName);
} else if (localScope) {
Object.assign(localScope, exports);
#if DYNCALLS || !WASM_BIGINT
registerDynCallSymbols(exports);
#endif
}
dso.exports = exports;
}
if (flags.loadAsync) {
#if DYLINK_DEBUG
dbg("loadDynamicLibrary: done (async)");
#endif
return getExports().then((exports) => {
moduleLoaded(exports);
return true;
});
}
moduleLoaded(getExports());
#if DYLINK_DEBUG
dbg("loadDynamicLibrary: done");
#endif
return true;
},
$loadDylibs__internal: true,
$loadDylibs__deps: ['$loadDynamicLibrary', '$reportUndefinedSymbols', '$addRunDependency', '$removeRunDependency'],
$loadDylibs: async () => {
if (!dynamicLibraries.length) {
#if DYLINK_DEBUG
dbg('loadDylibs: no libraries to preload');
#endif
reportUndefinedSymbols();
return;
}
#if DYLINK_DEBUG
dbg('loadDylibs:', dynamicLibraries);
#endif
addRunDependency('loadDylibs');
for (var lib of dynamicLibraries) {
await loadDynamicLibrary(lib, {loadAsync: true, global: true, nodelete: true, allowUndefined: true})
}
reportUndefinedSymbols();
#if DYLINK_DEBUG
dbg('loadDylibs done!');
#endif
removeRunDependency('loadDylibs');
},
$dlopenInternal__deps: ['$dlSetError', '$PATH'],
$dlopenInternal: (handle, jsflags) => {
var filename = UTF8ToString(handle + {{{ C_STRUCTS.dso.name }}});
var flags = {{{ makeGetValue('handle', C_STRUCTS.dso.flags, 'i32') }}};
#if DYLINK_DEBUG
dbg('dlopenInternal:', filename);
#endif
filename = PATH.normalize(filename);
var searchpaths = [];
var global = Boolean(flags & {{{ cDefs.RTLD_GLOBAL }}});
var localScope = global ? null : {};
var combinedFlags = {
global,
nodelete: Boolean(flags & {{{ cDefs.RTLD_NODELETE }}}),
loadAsync: jsflags.loadAsync,
}
if (jsflags.loadAsync) {
return loadDynamicLibrary(filename, combinedFlags, localScope, handle);
}
try {
return loadDynamicLibrary(filename, combinedFlags, localScope, handle)
} catch (e) {
#if ASSERTIONS
err(`Error in loading dynamic library ${filename}: ${e}`);
#endif
dlSetError(`Could not load dynamic lib: ${filename}\n${e}`);
return 0;
}
},
_dlopen_js__deps: ['$dlopenInternal'],
#if ASYNCIFY
_dlopen_js__async: true,
#endif
_dlopen_js: {{{ asyncIf(ASYNCIFY == 2) }}} (handle) =>
#if ASYNCIFY
Asyncify.handleSleep((wakeUp) =>
dlopenInternal(handle, { loadAsync: true })
.then(wakeUp)
.catch(() => wakeUp(0))
)
#else
dlopenInternal(handle, { loadAsync: false })
#endif
,
_emscripten_dlopen_js__deps: ['$dlopenInternal', '$callUserCallback', '$dlSetError'],
_emscripten_dlopen_js: (handle, onsuccess, onerror, user_data) => {
function errorCallback(e) {
var filename = UTF8ToString(handle + {{{ C_STRUCTS.dso.name }}});
dlSetError(`'Could not load dynamic lib: ${filename}\n${e}`);
{{{ runtimeKeepalivePop() }}}
callUserCallback(() => {{{ makeDynCall('vpp', 'onerror') }}}(handle, user_data));
}
function successCallback() {
{{{ runtimeKeepalivePop() }}}
callUserCallback(() => {{{ makeDynCall('vpp', 'onsuccess') }}}(handle, user_data));
}
{{{ runtimeKeepalivePush() }}}
var promise = dlopenInternal(handle, { loadAsync: true });
if (promise) {
promise.then(successCallback, errorCallback);
} else {
errorCallback();
}
},
_dlsym_catchup_js: (handle, symbolIndex) => {
#if DYLINK_DEBUG
dbg("_dlsym_catchup: handle=" + ptrToString(handle) + " symbolIndex=" + symbolIndex);
#endif
var lib = LDSO.loadedLibsByHandle[handle];
var symDict = lib.exports;
var symName = Object.keys(symDict)[symbolIndex];
var sym = symDict[symName];
var result = addFunction(sym, sym.sig);
#if DYLINK_DEBUG
dbg(`_dlsym_catchup: result=${result}`);
#endif
return result;
},
_dlsym_js__deps: ['$dlSetError', '$getFunctionAddress', '$addFunction'],
_dlsym_js: (handle, symbol, symbolIndex) => {
symbol = UTF8ToString(symbol);
#if DYLINK_DEBUG
dbg('dlsym_js:', symbol);
#endif
var result;
var newSymIndex;
var lib = LDSO.loadedLibsByHandle[handle];
#if ASSERTIONS
assert(lib, `Tried to dlsym() from an unopened handle: ${handle}`);
#endif
if (!lib.exports.hasOwnProperty(symbol) || lib.exports[symbol].stub) {
dlSetError(`Tried to lookup unknown symbol "${symbol}" in dynamic lib: ${lib.name}`)
return 0;
}
newSymIndex = Object.keys(lib.exports).indexOf(symbol);
#if !WASM_BIGINT
var origSym = 'orig$' + symbol;
result = lib.exports[origSym];
if (result) {
newSymIndex = Object.keys(lib.exports).indexOf(origSym);
}
else
#endif
result = lib.exports[symbol];
if (typeof result == 'function') {
#if DYLINK_DEBUG
dbg(`dlsym_js: ${symbol} getting table slot for: ${result}`);
#endif
#if ASYNCIFY
if (result.orig) {
result = result.orig;
}
#endif
var addr = getFunctionAddress(result);
if (addr) {
#if DYLINK_DEBUG
dbg('symbol already exists in table:', symbol);
#endif
result = addr;
} else {
result = addFunction(result, result.sig);
#if DYLINK_DEBUG
dbg('adding symbol to table:', symbol);
#endif
{{{ makeSetValue('symbolIndex', 0, 'newSymIndex', '*') }}};
}
}
#if DYLINK_DEBUG
dbg(`dlsym_js: ${symbol} -> ${result}`);
#endif
return result;
},
};
addToLibrary(LibraryDylink);