66 * Dynamic library loading
77 */
88
9- #if ! RELOCATABLE
10- #error "library_dylink.js requires RELOCATABLE"
9+ #if ! MAIN_MODULE && ! RELOCATABLE
10+ #error "library_dylink.js requires MAIN_MODULE or RELOCATABLE"
1111#endif
1212
13+ { { {
14+ const UNDEFINED_ADDR = to64 ( - 1 ) ;
15+ } } }
16+
1317var LibraryDylink = {
1418#if FILESYSTEM
1519 $registerWasmPlugin__deps : [ '$preloadPlugins' ] ,
@@ -170,10 +174,10 @@ var LibraryDylink = {
170174 get ( obj , symName ) {
171175 var rtn = GOT [ symName ] ;
172176 if ( ! rtn ) {
173- rtn = GOT [ symName ] = new WebAssembly . Global ( { 'value' : '{{{ POINTER_WASM_TYPE }}}' , 'mutable' : true } ) ;
174177#if DYLINK_DEBUG == 2
175- dbg ( " new GOT entry: " + symName ) ;
178+ dbg ( ` new GOT entry: ${ symName } ` ) ;
176179#endif
180+ rtn = GOT [ symName ] = new WebAssembly . Global ( { 'value' : '{{{ POINTER_WASM_TYPE }}}' , 'mutable' : true } , { { { UNDEFINED_ADDR } } } ) ;
177181 }
178182 if ( ! currentModuleWeakSymbols . has ( symName ) ) {
179183 // Any non-weak reference to a symbol marks it as `required`, which
@@ -189,6 +193,11 @@ var LibraryDylink = {
189193 $isInternalSym : ( symName ) => {
190194 // TODO: find a way to mark these in the binary or avoid exporting them.
191195 return [
196+ 'memory' ,
197+ '__memory_base' ,
198+ '__table_base' ,
199+ '__stack_pointer' ,
200+ '__indirect_function_table' ,
192201 '__cpp_exception' ,
193202 '__c_longjmp' ,
194203 '__wasm_apply_data_relocs' ,
@@ -213,6 +222,7 @@ var LibraryDylink = {
213222
214223 $updateGOT__internal : true ,
215224 $updateGOT__deps : [ '$GOT' , '$isInternalSym' , '$addFunction' ] ,
225+ $updateGOT__docs : '/** @param {boolean=} replace */' ,
216226 $updateGOT : ( exports , replace ) => {
217227#if DYLINK_DEBUG
218228 dbg ( `updateGOT: adding ${ Object . keys ( exports ) . length } symbols` ) ;
@@ -230,8 +240,7 @@ var LibraryDylink = {
230240 }
231241#endif
232242
233-
234- var existingEntry = GOT [ symName ] && GOT [ symName ] . value != 0 ;
243+ var existingEntry = GOT [ symName ] && GOT [ symName ] . value != { { { UNDEFINED_ADDR } } } ;
235244 if ( replace || ! existingEntry ) {
236245#if DYLINK_DEBUG == 2
237246 dbg ( `updateGOT: before: ${ symName } : ${ GOT [ symName ] ?. value } ` ) ;
@@ -252,7 +261,7 @@ var LibraryDylink = {
252261#if DYLINK_DEBUG == 2
253262 dbg ( `updateGOT: after: ${ symName } : ${ newValue } (${ value } )` ) ;
254263#endif
255- GOT [ symName ] || = new WebAssembly . Global ( { 'value' : '{{{ POINTER_WASM_TYPE }}}' , 'mutable' : true } ) ;
264+ GOT [ symName ] ?? = new WebAssembly . Global ( { 'value' : '{{{ POINTER_WASM_TYPE }}}' , 'mutable' : true } ) ;
256265 GOT [ symName ] . value = newValue ;
257266 }
258267#if DYLINK_DEBUG
@@ -280,9 +289,12 @@ var LibraryDylink = {
280289
281290 // Applies relocations to exported things.
282291 $relocateExports__internal : true ,
283- $relocateExports__deps : [ '$updateGOT' , '$isImmutableGlobal' ] ,
284- $relocateExports__docs : '/** @param {boolean=} replace */' ,
285- $relocateExports : ( exports , memoryBase , replace ) = > {
292+ $relocateExports__deps : [ '$isImmutableGlobal' ] ,
293+ $relocateExports : ( exports , memoryBase = 0 ) = > {
294+ #if DYLINK_DEBUG
295+ dbg ( `relocateExports memoryBase=${ memoryBase } count=${ Object . keys ( exports ) . length } ` ) ;
296+ #endif
297+
286298 function relocateExport ( name , value ) {
287299#if SPLIT_MODULE
288300 // Do not modify exports synthesized by wasm-split
@@ -304,7 +316,6 @@ var LibraryDylink = {
304316 for ( var e in exports ) {
305317 relocated [ e ] = relocateExport ( e , exports [ e ] )
306318 }
307- updateGOT ( relocated , replace ) ;
308319 return relocated ;
309320 } ,
310321
@@ -315,13 +326,17 @@ var LibraryDylink = {
315326 dbg ( 'reportUndefinedSymbols' ) ;
316327#endif
317328 for ( var [ symName , entry ] of Object . entries ( GOT ) ) {
318- if ( entry . value == 0 ) {
329+ if ( entry . value == { { { UNDEFINED_ADDR } } } ) {
330+ #if DYLINK_DEBUG
331+ dbg ( `undef GOT entry: ${ symName } ` ) ;
332+ #endif
319333 var value = resolveGlobalSymbol ( symName , true ) . sym ;
320334 if ( ! value && ! entry . required ) {
321335 // Ignore undefined symbols that are imported as weak.
322336#if DYLINK_DEBUG
323337 dbg ( 'ignoring undefined weak symbol:' , symName ) ;
324338#endif
339+ entry . value = { { { to64 ( 0 ) } } } ;
325340 continue ;
326341 }
327342#if ASSERTIONS
@@ -343,7 +358,7 @@ var LibraryDylink = {
343358 entry . value = value ;
344359#endif
345360 } else {
346- throw new Error ( `bad export type for '${ symName } ': ${ typeof value } ` ) ;
361+ throw new Error ( `bad export type for '${ symName } ': ${ typeof value } ( ${ value } ) ` ) ;
347362 }
348363 }
349364 }
@@ -390,7 +405,7 @@ var LibraryDylink = {
390405 // Allocate memory even if malloc isn't ready yet. The allocated memory here
391406 // must be zero initialized since its used for all static data, including bss.
392407 $getMemory__noleakcheck: true ,
393- $getMemory__deps : [ '$GOT' , '__heap_base' , '$alignMemory' , 'calloc' ] ,
408+ $getMemory__deps : [ '$GOT' , 'emscripten_get_sbrk_ptr' , ' __heap_base', '$alignMemory' , 'calloc' ] ,
394409 $getMemory : ( size ) => {
395410 // After the runtime is initialized, we must only use sbrk() normally.
396411#if DYLINK_DEBUG
@@ -409,7 +424,27 @@ var LibraryDylink = {
409424 assert ( end <= HEAP8 . length , 'failure to getMemory - memory growth etc. is not supported there, call malloc/sbrk directly or increase INITIAL_MEMORY' ) ;
410425#endif
411426 ___heap_base = end ;
427+
428+ // After allocating the memory from the start of the heap we need to ensure
429+ // that once the program starts it doesn't use this region. In relocatable
430+ // mode we can just update the __heap_base symbol that we are exporting to
431+ // the main module.
432+ // When not relocatable `__heap_base` is fixed and exported by the main
433+ // module, but we can update the `sbrk_ptr` value instead. We call
434+ // `_emscripten_get_sbrk_ptr` knowing that it is safe to call prior to
435+ // runtime initialization (unlike, the higher level sbrk function)
436+ #if RELOCATABLE
412437 GOT [ '__heap_base' ] . value = { { { to64 ( 'end' ) } } } ;
438+ #else
439+ #if PTHREADS
440+ if ( ! ENVIRONMENT_IS_PTHREAD ) {
441+ #endif
442+ var sbrk_ptr = _emscripten_get_sbrk_ptr ( ) ;
443+ { { { makeSetValue ( 'sbrk_ptr' , 0 , 'end' , '*' ) } } }
444+ #if PTHREADS
445+ }
446+ #endif
447+ #endif
413448 return ret ;
414449 } ,
415450
@@ -622,7 +657,7 @@ var LibraryDylink = {
622657 * @param {number=} handle
623658 */` ,
624659 $loadWebAssemblyModule__deps : [
625- '$loadDynamicLibrary' , '$getMemory' ,
660+ '$loadDynamicLibrary' , '$getMemory' , '$updateGOT' ,
626661 '$relocateExports' , '$resolveGlobalSymbol' , '$GOTHandler' ,
627662 '$getDylinkMetadata' , '$alignMemory' ,
628663 '$currentModuleWeakSymbols' ,
@@ -632,7 +667,7 @@ var LibraryDylink = {
632667 ] ,
633668 $loadWebAssemblyModule : ( binary , flags , libName , localScope , handle ) = > {
634669#if DYLINK_DEBUG
635- dbg ( 'loadWebAssemblyModule:' , libName ) ;
670+ dbg ( 'loadWebAssemblyModule:' , libName, handle ) ;
636671#endif
637672 var metadata = getDylinkMetadata ( binary ) ;
638673
@@ -651,6 +686,9 @@ var LibraryDylink = {
651686 // exclusive access to it for the duration of this function. See the
652687 // locking in `dynlink.c`.
653688 var firstLoad = ! handle || ! { { { makeGetValue ( 'handle' , C_STRUCTS . dso . mem_allocated , 'i8' ) } } } ;
689+ #if DYLINK_DEBUG
690+ dbg ( 'firstLoad :', firstLoad ) ;
691+ #endif
654692 if ( firstLoad ) {
655693#endif
656694 // alignments are powers of 2
@@ -787,6 +825,7 @@ var LibraryDylink = {
787825 // add new entries to functionsInTableMap
788826 updateTableMap ( tableBase , metadata . tableSize ) ;
789827 moduleExports = relocateExports ( instance . exports , memoryBase ) ;
828+ updateGOT ( moduleExports ) ;
790829#if ASYNCIFY
791830 moduleExports = Asyncify . instrumentWasmExports ( moduleExports ) ;
792831#endif
@@ -875,18 +914,27 @@ var LibraryDylink = {
875914 if ( applyRelocs ) {
876915 if ( runtimeInitialized ) {
877916#if DYLINK_DEBUG
878- dbg ( 'applyRelocs ' ) ;
917+ dbg ( 'running __wasm_apply_data_relocs ' ) ;
879918#endif
880919 applyRelocs ( ) ;
881920 } else {
921+ #if DYLINK_DEBUG
922+ dbg ( 'delaying __wasm_apply_data_relocs' ) ;
923+ #endif
882924 __RELOC_FUNCS__ . push ( applyRelocs ) ;
883925 }
884926 }
885927 var init = moduleExports [ '__wasm_call_ctors' ] ;
886928 if ( init ) {
887929 if ( runtimeInitialized ) {
930+ #if DYLINK_DEBUG
931+ dbg ( 'running __wasm_call_ctors' ) ;
932+ #endif
888933 init ( ) ;
889934 } else {
935+ #if DYLINK_DEBUG
936+ dbg ( 'delaying __wasm_call_ctors' ) ;
937+ #endif
890938 // we aren't ready to run compiled code yet
891939 addOnPostCtor ( init ) ;
892940 }
0 commit comments