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 @@ -421,7 +421,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 @@ -573,7 +573,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 @@ -604,7 +604,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 @@ -763,8 +763,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 @@ -775,7 +775,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
19 changes: 17 additions & 2 deletions src/lib/libcore.js
Original file line number Diff line number Diff line change
Expand Up @@ -1773,6 +1773,9 @@ addToLibrary({
},

$dynCall: (sig, ptr, args = [], promising = false) => {
#if ASSERTIONS
assert(ptr, `null function pointer in dynCall`);
#endif
#if ASSERTIONS && (DYNCALLS || !WASM_BIGINT || !JSPI)
assert(!promising, 'async dynCall is not supported in this mode')
#endif
Expand Down Expand Up @@ -2185,6 +2188,17 @@ addToLibrary({
#endif
},

#if MAIN_MODULE || RELOCATABLE
#if WASM_EXCEPTIONS
// In dynamic linking we define tags here and feed them to each module
__cpp_exception: "new WebAssembly.Tag({'parameters': ['{{{ POINTER_WASM_TYPE }}}']})",
#endif

#if SUPPORT_LONGJMP == 'wasm'
__c_longjmp: "new WebAssembly.Tag({'parameters': ['{{{ POINTER_WASM_TYPE }}}']})",
#endif
#endif

#if RELOCATABLE
// Globals that are normally exported from the wasm module but in relocatable
// mode are created here and imported by the module.
Expand All @@ -2208,11 +2222,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
86 changes: 59 additions & 27 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 Down Expand Up @@ -230,8 +235,8 @@ var LibraryDylink = {
}
#endif

GOT[symName] ||= new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true});
if (replace || GOT[symName].value == 0) {
if (replace || !GOT[symName] || GOT[symName].value == {{{ to64(-1) }}}) {
GOT[symName] ||= new WebAssembly.Global({'value': '{{{ POINTER_WASM_TYPE }}}', 'mutable': true}, {{{ to64(-1) }}});
#if DYLINK_DEBUG == 2
dbg(`updateGOT: before: ${symName} : ${GOT[symName].value}`);
#endif
Expand Down Expand Up @@ -265,26 +270,30 @@ var LibraryDylink = {
$relocateExports__deps: ['$updateGOT'],
$relocateExports__docs: '/** @param {boolean=} replace */',
$relocateExports: (exports, memoryBase, replace) => {
#if DYLINK_DEBUG
dbg('relocateExports', memoryBase);
#endif
var relocated = {};
var absSymbols = ['__stack_pointer'];

for (var e in exports) {
var value = exports[e];
if (!absSymbols.includes(e)
#if SPLIT_MODULE
// Do not modify exports synthesized by wasm-split
if (e.startsWith('%')) {
relocated[e] = value
continue;
}
#endif
if (typeof value?.value != 'undefined') {
// a breaking change in the wasm spec, globals are now objects
// https://github.com/WebAssembly/mutable-global/issues/1
value = value.value;
}
if (typeof value == {{{ POINTER_JS_TYPE }}}) {
value += {{{ to64('memoryBase') }}};
// Do not modify exports synthesized by wasm-split
&& !e.startsWith('%')
#endif
) {
if (typeof value?.value != 'undefined') {
// a breaking change in the wasm spec, globals are now objects
// https://github.com/WebAssembly/mutable-global/issues/1
value = value.value;
}
if (memoryBase && typeof value == {{{ POINTER_JS_TYPE }}}) {
value += {{{ to64('memoryBase') }}};
}
}
relocated[e] = value;
relocated[e] = value
}
updateGOT(relocated, replace);
return relocated;
Expand All @@ -297,13 +306,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 @@ -325,7 +338,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 @@ -372,7 +385,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 @@ -384,14 +397,21 @@ var LibraryDylink = {
// avoid having this reported as leak.
return _calloc(size, 1);
}
var ret = ___heap_base;
var ret = GOT['__heap_base'].value;
// Keep __heap_base stack aligned.
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') }}};
#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 @@ -614,7 +634,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 @@ -633,6 +653,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 @@ -860,18 +883,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
2 changes: 1 addition & 1 deletion src/lib/libpthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,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 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
Loading