Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ def phase_setup(options, state):
'unused-command-line-argument',
"linker flag ignored during compilation: '%s'" % arg)

if settings.MAIN_MODULE or settings.SIDE_MODULE:
if settings.SIDE_MODULE:
settings.RELOCATABLE = 1

if 'USE_PTHREADS' in user_settings:
Expand Down
12 changes: 6 additions & 6 deletions src/jsifier.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function isDefined(symName) {
}
// 'invoke_' symbols are created at runtime in library_dylink.py so can
// always be considered as defined.
if (RELOCATABLE && symName.startsWith('invoke_')) {
if ((MAIN_MODULE || RELOCATABLE) && symName.startsWith('invoke_')) {
return true;
}
return false;
Expand Down Expand Up @@ -572,7 +572,7 @@ function(${args}) {
if (!LibraryManager.library.hasOwnProperty(symbol)) {
const isWeakImport = WEAK_IMPORTS.has(symbol);
if (!isDefined(symbol) && !isWeakImport) {
if (PROXY_TO_PTHREAD && !MAIN_MODULE && symbol == '__main_argc_argv') {
if (PROXY_TO_PTHREAD && !(MAIN_MODULE || RELOCATABLE) && symbol == '__main_argc_argv') {
error('PROXY_TO_PTHREAD proxies main() for you, but no main exists');
return;
}
Expand Down Expand Up @@ -603,7 +603,7 @@ function(${args}) {

// emit a stub that will fail at runtime
var stubFunctionBody = `abort('missing function: ${symbol}');`
if (RELOCATABLE) {
if (RELOCATABLE || MAIN_MODULE) {
// Create a stub for this symbol which can later be replaced by the
// dynamic linker. If this stub is called before the symbol is
// resolved assert in debug builds or trap in release builds.
Expand Down Expand Up @@ -762,8 +762,8 @@ function(${args}) {
contentText = 'export ' + contentText;
}

// Relocatable code needs signatures to create proper wrappers.
if (sig && RELOCATABLE) {
// Dynamic linking needs signatures to create proper wrappers.
if (sig && (MAIN_MODULE || RELOCATABLE)) {
if (!WASM_BIGINT) {
sig = sig[0].replace('j', 'i') + sig.slice(1).replace(/j/g, 'ii');
}
Expand All @@ -774,7 +774,7 @@ function(${args}) {
}
if (isStub) {
contentText += `\n${mangled}.stub = true;`;
if (ASYNCIFY && MAIN_MODULE) {
if (ASYNCIFY && (MAIN_MODULE || RELOCATABLE)) {
contentText += `\nasyncifyStubs['${symbol}'] = undefined;`;
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/lib/libcore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2210,11 +2210,12 @@ addToLibrary({
__stack_high: '{{{ STACK_HIGH }}}',
__stack_low: '{{{ STACK_LOW }}}',
__global_base: '{{{ GLOBAL_BASE }}}',
#if ASYNCIFY == 1
#endif // RELOCATABLE

#if (MAIN_MODULE || RELOCATABLE) && ASYNCIFY == 1
__asyncify_state: "new WebAssembly.Global({'value': 'i32', 'mutable': true}, 0)",
__asyncify_data: "new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true}, {{{ to64(0) }}})",
#endif
#endif // RELOCATABLE

_emscripten_fs_load_embedded_files__deps: ['$FS', '$PATH'],
_emscripten_fs_load_embedded_files: (ptr) => {
Expand Down
74 changes: 51 additions & 23 deletions src/lib/libdylink.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* Dynamic library loading
*/

#if !RELOCATABLE
#error "library_dylink.js requires RELOCATABLE"
#if !MAIN_MODULE && !RELOCATABLE
#error "library_dylink.js requires MAIN_MODULE or RELOCATABLE"
#endif

var LibraryDylink = {
Expand Down Expand Up @@ -170,10 +170,10 @@ var LibraryDylink = {
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);
dbg(`new GOT entry: ${symName}`);
#endif
rtn = GOT[symName] = new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true}, {{{ to64(-1) }}});
}
if (!currentModuleWeakSymbols.has(symName)) {
// Any non-weak reference to a symbol marks it as `required`, which
Expand All @@ -189,6 +189,11 @@ var LibraryDylink = {
$isInternalSym: (symName) => {
// TODO: find a way to mark these in the binary or avoid exporting them.
return [
'memory',
'__memory_base',
'__table_base',
'__stack_pointer',
'__indirect_function_table',
'__cpp_exception',
'__c_longjmp',
'__wasm_apply_data_relocs',
Expand All @@ -213,6 +218,7 @@ var LibraryDylink = {

$updateGOT__internal: true,
$updateGOT__deps: ['$GOT', '$isInternalSym', '$addFunction'],
$updateGOT__docs: '/** @param {boolean=} replace */',
$updateGOT: (exports, replace) => {
#if DYLINK_DEBUG
dbg(`updateGOT: adding ${Object.keys(exports).length} symbols`);
Expand All @@ -230,18 +236,14 @@ var LibraryDylink = {
}
#endif


var existingEntry = GOT[symName] && GOT[symName].value != 0;
var existingEntry = GOT[symName] && GOT[symName].value != {{{ to64(-1) }}};
if (replace || !existingEntry) {
#if DYLINK_DEBUG == 2
dbg(`updateGOT: before: ${symName} : ${GOT[symName].value}`);
dbg(`updateGOT: before: ${symName} : ${GOT[symName]?.value}`);
#endif
var newValue;
if (typeof value == 'function') {
newValue = {{{ to64('addFunction(value)') }}};
#if DYLINK_DEBUG == 2
dbg(`updateGOT: FUNC: ${symName} : ${GOT[symName].value}`);
#endif
} else if (typeof value == {{{ POINTER_JS_TYPE }}}) {
newValue = value;
} else {
Expand All @@ -255,7 +257,7 @@ var LibraryDylink = {
#if DYLINK_DEBUG == 2
dbg(`updateGOT: after: ${symName} : ${newValue} (${value})`);
#endif
GOT[symName] ||= new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true});
GOT[symName] ??= new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true});
GOT[symName].value = newValue;
}
#if DYLINK_DEBUG
Expand Down Expand Up @@ -283,9 +285,12 @@ var LibraryDylink = {

// Applies relocations to exported things.
$relocateExports__internal: true,
$relocateExports__deps: ['$updateGOT', '$isImmutableGlobal'],
$relocateExports__docs: '/** @param {boolean=} replace */',
$relocateExports: (exports, memoryBase, replace) => {
$relocateExports__deps: ['$isImmutableGlobal'],
$relocateExports: (exports, memoryBase = 0) => {
#if DYLINK_DEBUG
dbg(`relocateExports memoryBase=${memoryBase} count=${Object.keys(exports).length}`);
#endif

function relocateExport(name, value) {
#if SPLIT_MODULE
// Do not modify exports synthesized by wasm-split
Expand All @@ -307,7 +312,6 @@ var LibraryDylink = {
for (var e in exports) {
relocated[e] = relocateExport(e, exports[e])
}
updateGOT(relocated, replace);
return relocated;
},

Expand All @@ -318,13 +322,17 @@ var LibraryDylink = {
dbg('reportUndefinedSymbols');
#endif
for (var [symName, entry] of Object.entries(GOT)) {
if (entry.value == 0) {
if (entry.value == {{{ to64(-1) }}}) {
#if DYLINK_DEBUG
dbg(`undef GOT entry: ${symName}`);
#endif
var value = resolveGlobalSymbol(symName, true).sym;
if (!value && !entry.required) {
// Ignore undefined symbols that are imported as weak.
#if DYLINK_DEBUG
dbg('ignoring undefined weak symbol:', symName);
#endif
entry.value = 0;
continue;
}
#if ASSERTIONS
Expand All @@ -346,7 +354,7 @@ var LibraryDylink = {
entry.value = value;
#endif
} else {
throw new Error(`bad export type for '${symName}': ${typeof value}`);
throw new Error(`bad export type for '${symName}': ${typeof value} (${value})`);
}
}
}
Expand Down Expand Up @@ -393,7 +401,7 @@ var LibraryDylink = {
// Allocate memory even if malloc isn't ready yet. The allocated memory here
// must be zero initialized since its used for all static data, including bss.
$getMemory__noleakcheck: true,
$getMemory__deps: ['$GOT', '__heap_base', '$alignMemory', 'calloc'],
$getMemory__deps: ['$GOT', 'emscripten_get_sbrk_ptr', '__heap_base', '$alignMemory', 'calloc'],
$getMemory: (size) => {
// After the runtime is initialized, we must only use sbrk() normally.
#if DYLINK_DEBUG
Expand All @@ -411,8 +419,15 @@ var LibraryDylink = {
#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') }}};
___heap_base = {{{ to64('end') }}};
#if PTHREADS
if (!ENVIRONMENT_IS_PTHREAD) {
#endif
var sbrk_ptr = _emscripten_get_sbrk_ptr();
{{{ makeSetValue('sbrk_ptr', 0, 'end', '*') }}}
#if PTHREADS
}
#endif
return ret;
},

Expand Down Expand Up @@ -625,7 +640,7 @@ var LibraryDylink = {
* @param {number=} handle
*/`,
$loadWebAssemblyModule__deps: [
'$loadDynamicLibrary', '$getMemory',
'$loadDynamicLibrary', '$getMemory', '$updateGOT',
'$relocateExports', '$resolveGlobalSymbol', '$GOTHandler',
'$getDylinkMetadata', '$alignMemory',
'$currentModuleWeakSymbols',
Expand All @@ -635,7 +650,7 @@ var LibraryDylink = {
],
$loadWebAssemblyModule: (binary, flags, libName, localScope, handle) => {
#if DYLINK_DEBUG
dbg('loadWebAssemblyModule:', libName);
dbg('loadWebAssemblyModule:', libName, handle);
#endif
var metadata = getDylinkMetadata(binary);

Expand All @@ -654,6 +669,9 @@ var LibraryDylink = {
// exclusive access to it for the duration of this function. See the
// locking in `dynlink.c`.
var firstLoad = !handle || !{{{ makeGetValue('handle', C_STRUCTS.dso.mem_allocated, 'i8') }}};
#if DYLINK_DEBUG
dbg('firstLoad:', firstLoad);
#endif
if (firstLoad) {
#endif
// alignments are powers of 2
Expand Down Expand Up @@ -790,6 +808,7 @@ var LibraryDylink = {
// add new entries to functionsInTableMap
updateTableMap(tableBase, metadata.tableSize);
moduleExports = relocateExports(instance.exports, memoryBase);
updateGOT(moduleExports);
#if ASYNCIFY
moduleExports = Asyncify.instrumentWasmExports(moduleExports);
#endif
Expand Down Expand Up @@ -881,18 +900,27 @@ var LibraryDylink = {
if (applyRelocs) {
if (runtimeInitialized) {
#if DYLINK_DEBUG
dbg('applyRelocs');
dbg('running __wasm_apply_data_relocs');
#endif
applyRelocs();
} else {
#if DYLINK_DEBUG
dbg('delaying __wasm_apply_data_relocs');
#endif
__RELOC_FUNCS__.push(applyRelocs);
}
}
var init = moduleExports['__wasm_call_ctors'];
if (init) {
if (runtimeInitialized) {
#if DYLINK_DEBUG
dbg('running __wasm_call_ctors');
#endif
init();
} else {
#if DYLINK_DEBUG
dbg('delaying __wasm_call_ctors');
#endif
// we aren't ready to run compiled code yet
addOnPostCtor(init);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/libglemu.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ assert(!FULL_ES3, 'cannot emulate both ES3 and legacy GL');

{{{
const copySigs = (func) => {
if (!RELOCATABLE) return '';
if (!MAIN_MODULE) return '';
return ` _${func}.sig = _emscripten_${func}.sig = orig_${func}.sig;`;
};
const fromPtr = (arg) => {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/libpthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ var LibraryPThread = {
#if MAIN_MODULE
$registerTLSInit: (tlsInitFunc, moduleExports, metadata) => {
#if DYLINK_DEBUG
dbg("registerTLSInit: " + tlsInitFunc);
dbg('registerTLSInit:', tlsInitFunc, metadata?.tlsExports);
#endif
// In relocatable builds, we use the result of calling tlsInitFunc
// (`_emscripten_tls_init`) to relocate the TLS exports of the module
Expand All @@ -613,7 +613,7 @@ var LibraryPThread = {
}
var tlsExports = {};
metadata.tlsExports.forEach((s) => tlsExports[s] = moduleExports[s]);
relocateExports(tlsExports, __tls_base, /*replace=*/true);
updateGOT(relocateExports(tlsExports, __tls_base), /*replace=*/true);
}

// Register this function so that its gets called for each thread on
Expand Down
2 changes: 1 addition & 1 deletion src/lib/libwasm_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#if LINKABLE
#error "-sLINKABLE is not supported with -sWASM_WORKERS"
#endif
#if RELOCATABLE
#if RELOCATABLE || MAIN_MODULE
#error "dynamic linking is not supported with -sWASM_WORKERS"
#endif
#if PROXY_TO_WORKER
Expand Down
2 changes: 1 addition & 1 deletion src/modules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ function calculateLibraries() {
libraries.push('libsyscall.js');
}

if (RELOCATABLE) {
if (MAIN_MODULE || RELOCATABLE) {
libraries.push('libdylink.js');
}

Expand Down
Loading