From 6a681749fa4b3b25c6d6c25355b4b4fe84fdb346 Mon Sep 17 00:00:00 2001 From: Vidya Date: Tue, 17 Feb 2026 12:07:45 -0500 Subject: [PATCH 1/9] Updated dynamic loading documentation --- docs/internal/dynamicloading.md | 131 ++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 docs/internal/dynamicloading.md diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md new file mode 100644 index 000000000..ffa07afb4 --- /dev/null +++ b/docs/internal/dynamicloading.md @@ -0,0 +1,131 @@ +# Dynamic Loading in wasmtime + +- Have implemented dynamic loading support in Wasmtime. For applications that are compiled as dynamically linked executables or shared libraries, we are able to support both capabilities below: + - Launch the application while injecting all required dependent libraries using the `--preload` option (similar to `LD_PRELOAD`). + - Ensure that `dlopen()`, `dlsym()`, and `dlclose()` are properly resolved at runtime and corresponding libraries loaded. + + +- Additional Features to be added: + - Support for fork, threads and signals within the shared libraries + +- Changes Made to wasm: + - rawposix is added as a submodule to wasmtime. Systems calls like `mmap` are redirected to rawposix. + +- Dynamic loading changes: + - Parse the `dylink.0` section within shared libraries (load_module). load_module is responsible for parsing the WASM binary to extract its section contents including code, data, imports, exports etc. + - Instantiate the dynamic libraries which are passed using `--preload` + - Allocate memory for the shared libraries by invoking mmap within rawposix + - Relocations are applied by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` which are functions within the wasm binary added in the compilation/linking phase. + - Global Offset Table (GOT) is created and stored in wasmtime. Implemented using a Hash Table which maps symbols to their addresses. + - Once all modules are loaded into memory, resolve the final address for all functions (GOT.func) and data (GOT.mem) within the GOT table. This is done by the Linker which is part of wasmtime. + - Handling dynamic libraries which are loaded via dlopen() + - When dlopen(), dlsym() and dlclose() with glibc invokes their respective implementations within Lind. + - when lind dlopen is invoked, it does the following: + - Gets the full path of the library by prepending LIND_ROOT to the library name + - Loads the module/library which involves parsing the wasm file and extracting its section contents including code, data, imports, exports etc. + - Appends the table with the table of main_module. table refers to indirect function call table. + - Instantiate the library which involves + - Allocate memory for the shared library by invoking mmap within rawposix + - Relocations are applied by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` which are functions within the wasm binary added in the compilation/linking phase. + - Resolve the final address for all functions (GOT.func) and data (GOT.mem) within the GOT table. + - Linear Memory Changes + - For statically linked binary which has fixed addresses, the memory layout is fixed. stack comes first, followed by dta and heap. + - In dynamically linked binary, since the code is compiled as position-independent, the memory layout can be determined at runtime. The memory layout is as follows: + +# Generating a WASM Binary for C/C++ applications (Static build) +Let us first explore a WASM binary and steps required to create a WASM binary (build) and then run it. + +Programs written in higher level programming languages like C/C++/Rust can be compiled to WASM binaries. A .wasm file is a binary encoding of instructions for a virtual stack-based machine. It must be JIT compiled or AOT compiled or interpreted. + +A C/C++ program can be compiled using clang with a WebAssembly target to produce a WASM binary. + +``` +clang --target=wasm32-unknown-wasi --sysroot=$SYSROOT_FOLDER -O2 gcd.c -o gcd.wasm +``` +1. Preprocessing - The C preprocessor handled macros and header expansion +2. Compilation (Frontend) - Clang parses C into LLVM IR +3. Code Generation (LLVM Backend) - Converts LLVM IR into Webassembly instructions as Webassembly object file +4. Linking using `wasm-ld` : + The object file contains WebAssembly code with unresolved symbols. During linking, `wasm-ld` combines the object file with startup files and static libraries, resolving undefined symbols by pulling in only the required object files from those archives within the `sysroot/` directory. The linker then merges all code, data, memory definitions, and remaining imports into a single final .wasm file + +## WASM Binary contents +A `.wasm` binary contains [1] [2] [3]: +- Magic Header - Identifies the file as a WebAssembly binary +- Version number - Specifies the WebAssembly binary format version +- Sections (Each section contains a section ID, section size, section contents) + - Type - Defines all functional signatures (parameter and return types) used in the module + - Import - Declares functions (incl module name), memories, tables or globals that must be provided by the host + - Function - Lists the type indices of functions defined inside the module + - Memory - Declares linear memory regions (lower limit and upper limit(optional) required for running the module) + - Global - Stores internal (non-imported) global variable information including type, whether it is read-only, initialization bytecode + - Table - Declares indirect function call table + - Export - Specifies which functions, memories, tables or globals are visible to the host + - Start - Identifies a function that is automatically executed upon instantiation + - Element - Initializes table entries + - Code - Contains the local variables info and bytecode of internal functions (WebAssembly instructions) + - Data - Contains memory initialization information. Each entry includes memory index, the starting position (bytecode and much be a constant expression) and initial data + +WebAssembly by default just produces a single data section. But when using clang/LLVM to compile C/C++ to wasm, it allocate separate sections for different types of data to support programs written in these languages. +- data (Initialized data) +- tdata (Thread related data) +- .rodata (Read-only data) + + +## Building a shared WASM library + +A WebAssembly dynamic/shared library is a WebAssembly binary with a special custom section that indicates this is a dynamic library and contains additional information needed by the loader. + +During **compilation**, `-fPIC` flag produces position-independent code whose final address is known only at runtime. Hence, all symbols that is not guaranteed to be local to this shared object will be accessed via `GOT.mem` and `GOT.func` in the generated object code. + +During **linking**, `-shared` produces a shared library and `-pie` produces a dynamically linked executable. + +To generate **a shared WASM library,** the following compiler and linker flags should be used. +``` +CFLAGS=-fPIC +LDFLAGS=-Wl,-shared +``` +Additional linker flags that can be used +``` +. -Wl,--import-memory \ + -Wl,--shared-memory \ + -Wl,--export-dynamic \ + -Wl,--experimental-pic \ + -Wl,--unresolved-symbols=import-dynamic \ +``` + +## Metadata added by linker to the shared WASM binary +- The generated shared WASM library binary will have a custom section called **`dynlink.0`** with the following information: +1. WASM_DYNLINK_MEM_INFO which specifies the memory and table space requirements of the module (memory size, memory alignment, table size, table alignment) +2. WASM_DYLINK_NEEDED - Specifies external modules that this library depends on +3. WASM_DYLINK_EXPORT_INFO - Specify additional metadata about exports +4. WASM_DYLINK_IMPORT_INFO - Specify additional metadata about imports +5. WASM_DYLINK_RUNTIME_PATH = Specify the runtime path, corresponding to DT_RUNPATH in ELF binaries + + - `wasm-ld` will add `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` functions to the final WASM binary which contain hardcoded information about relocation. + +# Running the .wasm file +This .wasm file has to be interpreted and converted to native code and then run within a VM. + +The steps involved are : +1. Read the .wasm file +2. Parse the structured sections (types, imports, functions, memory etc) of .wasm binary file +3. Validate the module - The module is validated for type safety, structural correctness, and sandbox rules +4. Compile to native code - Wasmtime translates WebAssembly bytecode into native machine code +5. Create a Store and Link Imports - A store is created to hold runtime state, and all declared imports (eg : WASI functions) are resolved to host implementations +6. Instantiate the Module - Transform the static module into a live execution instance. This involves **allocating** all of the module's Linear Memory, tables, globals in the store, creating separate runtime representations for each function, and **linking them to their resolved imports**. and function instances are allocated memory and initialized inside a new instance +7. Initialize Memory and Tables -After allocation, Wasmtime sets up the module’s initial state by populating memory and tables. Data segments from the Data Section of the module are copied into the linear memory at the offsets specified by the module, often including static strings, arrays, or other constants. Similarly, element segments from the Element Section are used to initialize tables, typically mapping function references for indirect calls. +8. Run the start function + + +# References +[1]: https://webassembly.github.io/spec/core/binary/modules.html +[2]:https://www.w3.org/TR/wasm-core-1/ +[3]: https://coinexsmartchain.medium.com/wasm-introduction-part-1-binary-format-57895d851580 +[4]:https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md +[5]:https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md +[6]:https://emscripten.org/docs/compiling/Dynamic-Linking.html +[7]:https://github.com/bytecodealliance/wasm-tools/blob/main/crates/wit-component/src/linking.rs +[8]:https://www.usenix.org/system/files/sec20-lehmann.pdf + + + From 0d763e32e2c82c6cadce07aff017ffee7486c02f Mon Sep 17 00:00:00 2001 From: Vidya Date: Tue, 17 Feb 2026 12:37:29 -0500 Subject: [PATCH 2/9] Changed format and added memory layout image --- docs/internal/dynamicloading.md | 63 +++++++++++++++++++------------- docs/internal/linear_memory.png | Bin 0 -> 74940 bytes 2 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 docs/internal/linear_memory.png diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md index ffa07afb4..48048d411 100644 --- a/docs/internal/dynamicloading.md +++ b/docs/internal/dynamicloading.md @@ -1,37 +1,48 @@ # Dynamic Loading in wasmtime -- Have implemented dynamic loading support in Wasmtime. For applications that are compiled as dynamically linked executables or shared libraries, we are able to support both capabilities below: - - Launch the application while injecting all required dependent libraries using the `--preload` option (similar to `LD_PRELOAD`). - - Ensure that `dlopen()`, `dlsym()`, and `dlclose()` are properly resolved at runtime and corresponding libraries loaded. +## Current Status +Have implemented dynamic loading support in Wasmtime. For applications that are compiled as dynamically linked executables or shared libraries, we are able to support both capabilities below: +1. Launch the application while injecting all required dependent libraries using the `--preload` option (similar to `LD_PRELOAD`). +2. Ensure that `dlopen()`, `dlsym()`, and `dlclose()` are properly resolved at runtime and corresponding libraries loaded. -- Additional Features to be added: - - Support for fork, threads and signals within the shared libraries +## Additional Features to be added: +Support for fork, threads and signals within the shared libraries have to be added. -- Changes Made to wasm: - - rawposix is added as a submodule to wasmtime. Systems calls like `mmap` are redirected to rawposix. - -- Dynamic loading changes: - - Parse the `dylink.0` section within shared libraries (load_module). load_module is responsible for parsing the WASM binary to extract its section contents including code, data, imports, exports etc. - - Instantiate the dynamic libraries which are passed using `--preload` - - Allocate memory for the shared libraries by invoking mmap within rawposix - - Relocations are applied by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` which are functions within the wasm binary added in the compilation/linking phase. - - Global Offset Table (GOT) is created and stored in wasmtime. Implemented using a Hash Table which maps symbols to their addresses. - - Once all modules are loaded into memory, resolve the final address for all functions (GOT.func) and data (GOT.mem) within the GOT table. This is done by the Linker which is part of wasmtime. - - Handling dynamic libraries which are loaded via dlopen() - - When dlopen(), dlsym() and dlclose() with glibc invokes their respective implementations within Lind. - - when lind dlopen is invoked, it does the following: - - Gets the full path of the library by prepending LIND_ROOT to the library name - - Loads the module/library which involves parsing the wasm file and extracting its section contents including code, data, imports, exports etc. - - Appends the table with the table of main_module. table refers to indirect function call table. - - Instantiate the library which involves - - Allocate memory for the shared library by invoking mmap within rawposix - - Relocations are applied by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` which are functions within the wasm binary added in the compilation/linking phase. - - Resolve the final address for all functions (GOT.func) and data (GOT.mem) within the GOT table. - - Linear Memory Changes +## Changes made to implement dynamic loading: + +In general, to load and instantiate and run wasm applications with Lind, wasmtime is modified to interact with rawposix for invoking system calls like `mmap.` + +Following changes are done to wasmtime, to implement dynamic loading. + +### Parsing the dynamic section +The `dylink.0` section within WASM shared libraries is parsed and its contents are stored. load_module is responsible for parsing the WASM binary to extract its section cont ents including code, data, imports, exports etc. + +### Instantiate the dynamic libraries which are passed using `--preload` +1. Allocate memory for the shared libraries by invoking mmap within rawposix +2. Relocations are applied by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` which are functions within the wasm binary added in the compilation/linking phase. +3. Global Offset Table (GOT) is created and stored in wasmtime. Implemented using a Hash Table which maps symbols to their addresses. +4. Once all modules are loaded into memory, resolve the final address for all functions (GOT.func) and data (GOT.mem) within the GOT table. This is done by the Linker which is part of wasmtime. +### Handling dynamic libraries which are loaded via dlopen() +1. When dlopen(), dlsym() and dlclose() with glibc invokes their respective implementations within Lind. +2. when lind dlopen is invoked, it does the following: + - Gets the full path of the library by prepending LIND_ROOT to the library name + - Loads the module/library which involves parsing the wasm file and extracting its section contents including code, data, imports, exports etc. + - Appends the table with the table of main_module. table refers to indirect function call table. + - Instantiate the library which involves + - Allocate memory for the shared library by invoking mmap within rawposix + - Relocations are applied by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` which are functions within the wasm binary added in the compilation/linking phase. + - Resolve the final address for all functions (GOT.func) and data (GOT.mem) within the GOT table. + +3. When dlsym() is invoked, correspond lind function, fetches the address of the function passed as argument, and invokes it. + +### Linear Memory Changes - For statically linked binary which has fixed addresses, the memory layout is fixed. stack comes first, followed by dta and heap. - In dynamically linked binary, since the code is compiled as position-independent, the memory layout can be determined at runtime. The memory layout is as follows: + ![Alt text for the image](linear_memory.jpg "Memory Layout (linear memory) in case of wasm binaries with dynamic loading") + + # Generating a WASM Binary for C/C++ applications (Static build) Let us first explore a WASM binary and steps required to create a WASM binary (build) and then run it. diff --git a/docs/internal/linear_memory.png b/docs/internal/linear_memory.png new file mode 100644 index 0000000000000000000000000000000000000000..6d3dc47a062ca025793230eb5ad62b036490ba7f GIT binary patch literal 74940 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

b0mwpcPA32dS4HF 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 literal 0 HcmV?d00001 From c98bae84824c5f78968a0abd69953cafb0f1a8ff Mon Sep 17 00:00:00 2001 From: Vidya Date: Tue, 17 Feb 2026 12:41:21 -0500 Subject: [PATCH 3/9] Updated image --- docs/internal/dynamicloading.md | 5 ++--- docs/internal/{ => images}/linear_memory.png | Bin 2 files changed, 2 insertions(+), 3 deletions(-) rename docs/internal/{ => images}/linear_memory.png (100%) diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md index 48048d411..fe4928988 100644 --- a/docs/internal/dynamicloading.md +++ b/docs/internal/dynamicloading.md @@ -37,10 +37,9 @@ The `dylink.0` section within WASM shared libraries is parsed and its contents a 3. When dlsym() is invoked, correspond lind function, fetches the address of the function passed as argument, and invokes it. ### Linear Memory Changes - - For statically linked binary which has fixed addresses, the memory layout is fixed. stack comes first, followed by dta and heap. - - In dynamically linked binary, since the code is compiled as position-independent, the memory layout can be determined at runtime. The memory layout is as follows: +For statically linked binary which has fixed addresses, the memory layout is fixed. stack comes first, followed by dta and heap. In dynamically linked binary, since the code is compiled as position-independent, the memory layout can be determined at runtime. The memory layout is as follows: - ![Alt text for the image](linear_memory.jpg "Memory Layout (linear memory) in case of wasm binaries with dynamic loading") + ![Memory Layout (linear memory) in case of wasm binaries with dynamic loading](images/linear_memory.jpg) # Generating a WASM Binary for C/C++ applications (Static build) diff --git a/docs/internal/linear_memory.png b/docs/internal/images/linear_memory.png similarity index 100% rename from docs/internal/linear_memory.png rename to docs/internal/images/linear_memory.png From 6831cca9d3f4376658a2e8a80521094cf800e40b Mon Sep 17 00:00:00 2001 From: Vidya Date: Tue, 17 Feb 2026 14:46:34 -0500 Subject: [PATCH 4/9] Added motivation and design decisions --- docs/internal/dynamicloading.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md index fe4928988..0c39af5a2 100644 --- a/docs/internal/dynamicloading.md +++ b/docs/internal/dynamicloading.md @@ -1,5 +1,17 @@ # Dynamic Loading in wasmtime +## Motivation +Dynamic loading reduces the memory footprint by allowing libraries to be loaded only when needed, rather than linking them statically at compile time. It also eliminates the need to recompile the application when a dependent library changes, provided the interface remains compatible. Additonally, in the applications we test, libraries are loaded at runtime using `dlopen()` and `dlsym()`. Therefore, to correctly support these applications, dynamic loading functionality is required. + +## Design Decisions +### How Dynamic Loading works in Linux + +When a program is executed on Linux, the kernel creates a new process image using execve() and maps the ELF executable into the process’s virtual address space. For statically linked binaries, the kernel sets up the stack and auxiliary data structures and transfers control directly to the program’s entry point. For dynamically linked binaries, the ELF header contains a PT_INTERP segment specifying the dynamic loader (typically `/lib64/ld-linux-x86-64.so.2`). The kernel maps this loader into the same process, transfers control to it, and the loader then loads required shared libraries, resolves symbols, performs relocations, and finally jumps to the program entry point. Crucially, the dynamic loader and the main executable share the same virtual address space and execute within the same process; the loader is not a separate process. + +In contrast, WebAssembly (WASM) binaries are not executed directly by the operating system. They run inside a runtime such as Wasmtime, which parses and validates the module, JIT-compiles the code, and instantiates the module. Instantiation involves allocating linear memory—a contiguous, sandboxed memory region —initializing globals and tables, and copying data segments into memory. Unlike ELF binaries, WASM modules do not rely on OS-level virtual memory mapping for code or libraries. Instead, execution and memory management are handled entirely within the runtime, which enforces isolation, bounds checking, and memory safety. + +In the Lind system, dynamic loading support is implemented by extending Wasmtime’s parsing and instantiation mechanisms. Calls such as `dlopen`, `dlsym`, and `dlclose` from glibc are redirected to runtime-provided implementations. The runtime then loads additional WASM modules, allocates memory, resolves symbols, and performs relocation handling—all within the sandboxed environment. Integrating the dynamic loader inside the runtime is necessary because WebAssembly linking requires direct, synchronous modification of internal runtime state, such as function tables and memory bounds, which an external process cannot access without prohibitive serialization overhead. Keeping the dynamic loader internal also avoids the latency of inter-process communication, ensuring that module instantiation remains fast, secure, and fully within the trusted computing base. + ## Current Status Have implemented dynamic loading support in Wasmtime. For applications that are compiled as dynamically linked executables or shared libraries, we are able to support both capabilities below: 1. Launch the application while injecting all required dependent libraries using the `--preload` option (similar to `LD_PRELOAD`). @@ -11,12 +23,10 @@ Support for fork, threads and signals within the shared libraries have to be add ## Changes made to implement dynamic loading: -In general, to load and instantiate and run wasm applications with Lind, wasmtime is modified to interact with rawposix for invoking system calls like `mmap.` - -Following changes are done to wasmtime, to implement dynamic loading. +"To execute WebAssembly applications within Lind, Wasmtime is modified to interface with RawPOSIX for handling system calls such as `mmap`. Specifically, the following changes were implemented in Wasmtime to support dynamic loading:" ### Parsing the dynamic section -The `dylink.0` section within WASM shared libraries is parsed and its contents are stored. load_module is responsible for parsing the WASM binary to extract its section cont ents including code, data, imports, exports etc. +The `dylink.0` custom section within WASM shared libraries is parsed to retrieve dynamic linking metadata. The `load_module` function is responsible for parsing the entire WASM binary to extract all section contents, including code, data, imports, exports, and the dynamic linking information. ### Instantiate the dynamic libraries which are passed using `--preload` 1. Allocate memory for the shared libraries by invoking mmap within rawposix @@ -37,9 +47,8 @@ The `dylink.0` section within WASM shared libraries is parsed and its contents a 3. When dlsym() is invoked, correspond lind function, fetches the address of the function passed as argument, and invokes it. ### Linear Memory Changes -For statically linked binary which has fixed addresses, the memory layout is fixed. stack comes first, followed by dta and heap. In dynamically linked binary, since the code is compiled as position-independent, the memory layout can be determined at runtime. The memory layout is as follows: - - ![Memory Layout (linear memory) in case of wasm binaries with dynamic loading](images/linear_memory.jpg) +For statically linked binary which has fixed addresses, the memory layout is fixed. Stack comes first, followed by data and heap. In dynamically linked binary, since the code is compiled as position-independent, the memory layout can be determined at runtime. The memory layout for current implementation is as follows: +![Memory Layout (linear memory) in case of wasm binaries with dynamic loading](images/linear_memory.png) # Generating a WASM Binary for C/C++ applications (Static build) From 620d67b3206d1927e71a8ac5679b1bddd4dd541a Mon Sep 17 00:00:00 2001 From: Vidya Date: Wed, 25 Feb 2026 01:33:50 -0500 Subject: [PATCH 5/9] Updated section heading and additional features --- docs/internal/dynamicloading.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md index 0c39af5a2..af5a8cd41 100644 --- a/docs/internal/dynamicloading.md +++ b/docs/internal/dynamicloading.md @@ -4,7 +4,6 @@ Dynamic loading reduces the memory footprint by allowing libraries to be loaded only when needed, rather than linking them statically at compile time. It also eliminates the need to recompile the application when a dependent library changes, provided the interface remains compatible. Additonally, in the applications we test, libraries are loaded at runtime using `dlopen()` and `dlsym()`. Therefore, to correctly support these applications, dynamic loading functionality is required. ## Design Decisions -### How Dynamic Loading works in Linux When a program is executed on Linux, the kernel creates a new process image using execve() and maps the ELF executable into the process’s virtual address space. For statically linked binaries, the kernel sets up the stack and auxiliary data structures and transfers control directly to the program’s entry point. For dynamically linked binaries, the ELF header contains a PT_INTERP segment specifying the dynamic loader (typically `/lib64/ld-linux-x86-64.so.2`). The kernel maps this loader into the same process, transfers control to it, and the loader then loads required shared libraries, resolves symbols, performs relocations, and finally jumps to the program entry point. Crucially, the dynamic loader and the main executable share the same virtual address space and execute within the same process; the loader is not a separate process. @@ -12,14 +11,15 @@ In contrast, WebAssembly (WASM) binaries are not executed directly by the operat In the Lind system, dynamic loading support is implemented by extending Wasmtime’s parsing and instantiation mechanisms. Calls such as `dlopen`, `dlsym`, and `dlclose` from glibc are redirected to runtime-provided implementations. The runtime then loads additional WASM modules, allocates memory, resolves symbols, and performs relocation handling—all within the sandboxed environment. Integrating the dynamic loader inside the runtime is necessary because WebAssembly linking requires direct, synchronous modification of internal runtime state, such as function tables and memory bounds, which an external process cannot access without prohibitive serialization overhead. Keeping the dynamic loader internal also avoids the latency of inter-process communication, ensuring that module instantiation remains fast, secure, and fully within the trusted computing base. -## Current Status +## Current Implementation Status Have implemented dynamic loading support in Wasmtime. For applications that are compiled as dynamically linked executables or shared libraries, we are able to support both capabilities below: 1. Launch the application while injecting all required dependent libraries using the `--preload` option (similar to `LD_PRELOAD`). 2. Ensure that `dlopen()`, `dlsym()`, and `dlclose()` are properly resolved at runtime and corresponding libraries loaded. ## Additional Features to be added: -Support for fork, threads and signals within the shared libraries have to be added. +1. Support for fork, threads and signals within the shared libraries have to be added. +2. Should be integrated with lind-boot ## Changes made to implement dynamic loading: From 8b4129d57dd5e1e8ab1d24043a5f3bfa89c764ec Mon Sep 17 00:00:00 2001 From: Vidya Date: Wed, 25 Feb 2026 12:04:05 -0500 Subject: [PATCH 6/9] Improved motivation, design decisions and details about dlopen/dlsym etc --- docs/internal/dynamicloading.md | 252 +++++++++++++++++++++----------- 1 file changed, 163 insertions(+), 89 deletions(-) diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md index af5a8cd41..74545b05f 100644 --- a/docs/internal/dynamicloading.md +++ b/docs/internal/dynamicloading.md @@ -1,139 +1,213 @@ # Dynamic Loading in wasmtime ## Motivation -Dynamic loading reduces the memory footprint by allowing libraries to be loaded only when needed, rather than linking them statically at compile time. It also eliminates the need to recompile the application when a dependent library changes, provided the interface remains compatible. Additonally, in the applications we test, libraries are loaded at runtime using `dlopen()` and `dlsym()`. Therefore, to correctly support these applications, dynamic loading functionality is required. +Dynamic loading reduces the memory footprint by allowing shared libraries to be loaded only when they are actually needed at runtime, rather than being statically linked into the application at compile time. This leads to more efficient memory usage, especially when multiple programs share the same libraries. It also avoids code duplication across binaries, reducing overall storage requirements. + +Another important advantage is improved maintainability and flexibility. When a dependent library is updated, the application does not need to be recompiled, as long as the library’s interface (ABI) remains compatible. This simplifies deployment, enables independent updates, and facilitates security patches without rebuilding the entire application. + +Dynamic loading also supports modular and extensible system design. Applications can load optional components, plugins, or backends at runtime based on configuration or environment, making it possible to extend functionality without modifying the core executable. In the applications we evaluate, libraries are explicitly loaded at runtime using `dlopen()` and symbol resolution is performed via `dlsym()`. Therefore, proper support for dynamic loading is a functional requirement to ensure correctness and compatibility with these applications. ## Design Decisions -When a program is executed on Linux, the kernel creates a new process image using execve() and maps the ELF executable into the process’s virtual address space. For statically linked binaries, the kernel sets up the stack and auxiliary data structures and transfers control directly to the program’s entry point. For dynamically linked binaries, the ELF header contains a PT_INTERP segment specifying the dynamic loader (typically `/lib64/ld-linux-x86-64.so.2`). The kernel maps this loader into the same process, transfers control to it, and the loader then loads required shared libraries, resolves symbols, performs relocations, and finally jumps to the program entry point. Crucially, the dynamic loader and the main executable share the same virtual address space and execute within the same process; the loader is not a separate process. +### The Linux Native Execution Model + +When a program is executed on Linux, the kernel creates a new process image using `execve()` and maps the ELF executable into the process’s virtual address space. For statically linked binaries, the kernel sets up the stack and auxiliary data structures, then transfers control directly to the program’s entry point. + +For dynamically linked binaries, the execution model splits responsibilities: the trusted kernel handles the initial loading, but dynamic loading is managed in user space. The ELF header contains a `PT_INTERP` segment specifying an external dynamic loader (typically `/lib64/ld-linux-x86-64.so.2`). The kernel maps this loader into the same process and transfers control to it. The loader then pulls in required shared libraries, resolves symbols, and performs relocations before finally jumping to the program's entry point. Crucially, this dynamic loader operates entirely within the untrusted user-space environment, sharing the same virtual address space as the main executable. + +### The WebAssembly Execution Model + +In contrast, WebAssembly (WASM) binaries are not executed directly by the operating system. They run inside a trusted host runtime, such as Wasmtime, which parses and validates the module, JIT-compiles the code, and instantiates it. + +Instantiation involves allocating linear memory - a contiguous, sandboxed memory region - initializing globals and tables, and copying data segments into memory. Unlike native ELF binaries, WASM modules do not rely on OS-level virtual memory mapping. Instead, execution, memory management, and boundary mediation are handled entirely by the runtime, which enforces strict isolation and memory safety. -In contrast, WebAssembly (WASM) binaries are not executed directly by the operating system. They run inside a runtime such as Wasmtime, which parses and validates the module, JIT-compiles the code, and instantiates the module. Instantiation involves allocating linear memory—a contiguous, sandboxed memory region —initializing globals and tables, and copying data segments into memory. Unlike ELF binaries, WASM modules do not rely on OS-level virtual memory mapping for code or libraries. Instead, execution and memory management are handled entirely within the runtime, which enforces isolation, bounds checking, and memory safety. +### Dynamic Loading within the Lind System -In the Lind system, dynamic loading support is implemented by extending Wasmtime’s parsing and instantiation mechanisms. Calls such as `dlopen`, `dlsym`, and `dlclose` from glibc are redirected to runtime-provided implementations. The runtime then loads additional WASM modules, allocates memory, resolves symbols, and performs relocation handling—all within the sandboxed environment. Integrating the dynamic loader inside the runtime is necessary because WebAssembly linking requires direct, synchronous modification of internal runtime state, such as function tables and memory bounds, which an external process cannot access without prohibitive serialization overhead. Keeping the dynamic loader internal also avoids the latency of inter-process communication, ensuring that module instantiation remains fast, secure, and fully within the trusted computing base. +In the Lind system, dynamic loading support is implemented by fundamentally extending Wasmtime’s parsing and instantiation mechanisms. Calls from `glibc`, such as dlopen, dlsym, and dlclose, are redirected to runtime-provided implementations. The runtime then loads additional WASM modules, allocates memory, resolves symbols, and handles relocations natively. + +Unlike the traditional Linux model where dynamic linking is delegated to an external, untrusted user-space process, Lind integrates the dynamic loader directly into the trusted Wasmtime runtime. This architectural shift is necessary for several reasons: + +1. Architectural Consistency: An essential requirement of any dynamic loader is the ability to read memory contents, resolve symbols, and modify relocation targets. Because the WebAssembly runtime already maintains absolute control over module memory, function tables, and instantiation state, extending it to handle dynamic loading is a natural fit. + +2. Performance and Efficiency: WebAssembly linking requires direct, synchronous modification of internal runtime state, such as indirect function tables and memory bounds. Relying on an external loader process to manipulate these structures would introduce prohibitive overhead from inter-process communication (IPC) latency, data marshaling, and serialization. + +3. Security: By internalizing the dynamic loader, the system avoids context-switching to an untrusted environment, ensuring that the entire module instantiation and linking process remains fast, secure, and securely isolated within the trusted computing base. ## Current Implementation Status -Have implemented dynamic loading support in Wasmtime. For applications that are compiled as dynamically linked executables or shared libraries, we are able to support both capabilities below: -1. Launch the application while injecting all required dependent libraries using the `--preload` option (similar to `LD_PRELOAD`). -2. Ensure that `dlopen()`, `dlsym()`, and `dlclose()` are properly resolved at runtime and corresponding libraries loaded. +We have implemented dynamic loading support in Wasmtime. For applications that are compiled as dynamically linked executables or shared libraries, we are able to support both capabilities below: + +1. Launch the application while injecting all required dependent libraries using the `--preload` option (similar to `LD_PRELOAD`). +2. Ensure that `dlopen()`, `dlsym()`, and `dlclose()` are properly resolved at runtime and corresponding libraries loaded. ## Additional Features to be added: -1. Support for fork, threads and signals within the shared libraries have to be added. -2. Should be integrated with lind-boot - +1. Support for fork, threads, and signals within the shared libraries. + ## Changes made to implement dynamic loading: -"To execute WebAssembly applications within Lind, Wasmtime is modified to interface with RawPOSIX for handling system calls such as `mmap`. Specifically, the following changes were implemented in Wasmtime to support dynamic loading:" +To execute WebAssembly applications within Lind, Wasmtime is modified to interface with RawPOSIX for handling system calls such as `mmap`. Specifically, the following changes were implemented in Wasmtime to support dynamic loading: + ### Parsing the dynamic section -The `dylink.0` custom section within WASM shared libraries is parsed to retrieve dynamic linking metadata. The `load_module` function is responsible for parsing the entire WASM binary to extract all section contents, including code, data, imports, exports, and the dynamic linking information. - -### Instantiate the dynamic libraries which are passed using `--preload` -1. Allocate memory for the shared libraries by invoking mmap within rawposix -2. Relocations are applied by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` which are functions within the wasm binary added in the compilation/linking phase. -3. Global Offset Table (GOT) is created and stored in wasmtime. Implemented using a Hash Table which maps symbols to their addresses. -4. Once all modules are loaded into memory, resolve the final address for all functions (GOT.func) and data (GOT.mem) within the GOT table. This is done by the Linker which is part of wasmtime. -### Handling dynamic libraries which are loaded via dlopen() -1. When dlopen(), dlsym() and dlclose() with glibc invokes their respective implementations within Lind. -2. when lind dlopen is invoked, it does the following: - - Gets the full path of the library by prepending LIND_ROOT to the library name - - Loads the module/library which involves parsing the wasm file and extracting its section contents including code, data, imports, exports etc. - - Appends the table with the table of main_module. table refers to indirect function call table. - - Instantiate the library which involves - - Allocate memory for the shared library by invoking mmap within rawposix - - Relocations are applied by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` which are functions within the wasm binary added in the compilation/linking phase. - - Resolve the final address for all functions (GOT.func) and data (GOT.mem) within the GOT table. - -3. When dlsym() is invoked, correspond lind function, fetches the address of the function passed as argument, and invokes it. +The `dylink.0` custom section within WASM shared libraries is parsed to retrieve dynamic linking metadata. The `load_module` function is responsible for parsing the entire WASM binary to extract all section contents, including code, data, imports, exports, and dynamic linking information. As of now, `memory_size`, `memopry_alignment`, `table_size`, `table_alignment` and `importinfo` are parsed. We do not handle `needed` and `exportinfo` contents of `dylink.0`c section. + + +### Handling libraries passed via `--preload` + +1. Allocate memory for the shared libraries by invoking `mmap` within RawPOSIX. +2. Apply relocations by invoking `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs`. These are functions hardcoded into the Wasm binary by `wasm-ld` during the `-shared` compilation phase. +3. Populate `LindGOT` with symbol addresses. +4. Resolve the final address for all functions (`GOT.func`) and data (`GOT.mem`) within the GOT table using the Wasmtime Linker. + + +### Memory Initialization and Instantiation (`instance.rs`) + +Several low-level changes govern how Wasmtime allocates memory and recognizes module types during instantiation: + +* **`init_vmmap()`**: Initializes memory at RawPOSIX before `mmap` is called. +* **System Memory Allocation**: During instantiation, Wasmtime interacts directly with RawPOSIX to allocate system memory for the module (part of the `init_vmmap` step). +* **`InstantiateType::InstantiateLib` Instantiates dependent libraries + + +### Global Offset Table (`LindGOT`) and Linking (`linker.rs`) + +`LindGOT` is Lind’s thread-safe Global Offset Table helper utilized for dynamic linking and late binding of symbols across separately-loaded Wasm modules. + +* **Indirection Slots**: Instead of hard-wiring addresses, `LindGOT` maintains a concurrent-safe map from a symbol name (`String`) to a `u32` GOT slot. A value of `0` in the slot denotes an unresolved symbol. +* **Resolution Semantics**: Utilizes atomic reads/writes with a "first definition wins" approach. Conditional patching ensures a symbol is only updated if unresolved, preventing race conditions between multiple resolvers. +* **Linker Behavior**: The Wasmtime linker links imported functions to their actual targets. For dynamically linked binaries, compiler-assigned `.GOT.func` and `.GOT.mem` handles are utilized. The linker creates placeholder instances for libraries before they are fully instantiated, resolving final addresses once loaded into memory. + ### Linear Memory Changes For statically linked binary which has fixed addresses, the memory layout is fixed. Stack comes first, followed by data and heap. In dynamically linked binary, since the code is compiled as position-independent, the memory layout can be determined at runtime. The memory layout for current implementation is as follows: ![Memory Layout (linear memory) in case of wasm binaries with dynamic loading](images/linear_memory.png) -# Generating a WASM Binary for C/C++ applications (Static build) -Let us first explore a WASM binary and steps required to create a WASM binary (build) and then run it. +### Handling `dlopen` and `dlsym` -Programs written in higher level programming languages like C/C++/Rust can be compiled to WASM binaries. A .wasm file is a binary encoding of instructions for a virtual stack-based machine. It must be JIT compiled or AOT compiled or interpreted. +In the Lind environment, standard dynamic linking calls from the guest's glibc (`dlopen`, `dlsym`, `dlclose`) are intercepted and forwarded to custom host functions within the Wasmtime runtime. This bridges the sandboxed WebAssembly execution with the trusted host's module management. `SymbolMap` acts as a per-library symbol namespace to model a dynamically loaded library’s exports and lifecycle state. -A C/C++ program can be compiled using clang with a WebAssembly target to produce a WASM binary. -``` +#### `dlopen` (Loading & Instantiation) +When invoked from the WebAssembly guest, the host implementation of `dlopen` performs the following steps: +* **Pointer Translation:** Translates the raw pointer provided by the guest (which is merely an offset into the Wasm linear memory) into a valid host-side string representing the library path. +* **Delegation:** Delegates the actual loading and instantiation to a `loader` callback injected by the runtime. +* **Execution:** The `loader` receives a mutable `Caller` (granting access to internal runtime state), the resolved library path, and the `dlopen` mode flags. +* **Returns:** On success, it returns an integer handle that uniquely identifies the loaded library instance. + + + +#### `dlsym` (Symbol Resolution) +This host function is responsible for finding the memory address or function index of a requested symbol. Lind invokes `get_library_symbols()` to fetch the exact symbol address from the corresponding `SymbolMap` (using its handler) and executes it. + It resolves the symbol name based on POSIX-style scope rules: +* **`RTLD_DEFAULT`:** Searches for the symbol across the global namespace. +* **Specific Handle:** Searches exclusively within the library identified by the provided integer handle. +* *Note: `RTLD_NEXT` (searching the next object in the load order) is currently unsupported.* +* **Returns:** The resolved symbol's value (e.g., a function index or memory address handle) so the Wasm guest can interact with it. + +#### `dlclose` (Lifecycle Management) +This function manages the cleanup and unloading of libraries. +* **Reference Counting:** Decrements the reference count of the library identified by the provided `handle`. +* **Unloading:** If the reference count reaches zero and the library is flagged as deletable (i.e., it was not loaded with `RTLD_NODELETE`), the host removes it from the global symbol table and frees associated resources. +* **Returns:** `0` on success, strictly adhering to POSIX-compatible conventions. + + + + +# Generating a WASM Binary for C/C++ applications + +Programs written in higher-level programming languages like C, C++, or Rust can be compiled to WASM binaries. A `.wasm` file is a binary encoding of instructions for a virtual stack-based machine. It must be JIT compiled, AOT compiled, or interpreted. + +A C/C++ program can be compiled using `clang` with a WebAssembly target to produce a WASM binary: + +```bash clang --target=wasm32-unknown-wasi --sysroot=$SYSROOT_FOLDER -O2 gcd.c -o gcd.wasm + ``` -1. Preprocessing - The C preprocessor handled macros and header expansion -2. Compilation (Frontend) - Clang parses C into LLVM IR -3. Code Generation (LLVM Backend) - Converts LLVM IR into Webassembly instructions as Webassembly object file -4. Linking using `wasm-ld` : - The object file contains WebAssembly code with unresolved symbols. During linking, `wasm-ld` combines the object file with startup files and static libraries, resolving undefined symbols by pulling in only the required object files from those archives within the `sysroot/` directory. The linker then merges all code, data, memory definitions, and remaining imports into a single final .wasm file + +1. **Preprocessing:** The C preprocessor handles macros and header expansion. +2. **Compilation (Frontend):** Clang parses C into LLVM IR. +3. **Code Generation (LLVM Backend):** Converts LLVM IR into WebAssembly instructions as a WebAssembly object file. +4. **Linking (`wasm-ld`):** The object file contains WebAssembly code with unresolved symbols. `wasm-ld` combines the object file with startup files and static libraries, pulling in required object files from the `sysroot/` directory. The linker merges all code, data, memory definitions, and imports into a single `.wasm` file. ## WASM Binary contents A `.wasm` binary contains [1] [2] [3]: -- Magic Header - Identifies the file as a WebAssembly binary -- Version number - Specifies the WebAssembly binary format version -- Sections (Each section contains a section ID, section size, section contents) - - Type - Defines all functional signatures (parameter and return types) used in the module - - Import - Declares functions (incl module name), memories, tables or globals that must be provided by the host - - Function - Lists the type indices of functions defined inside the module - - Memory - Declares linear memory regions (lower limit and upper limit(optional) required for running the module) - - Global - Stores internal (non-imported) global variable information including type, whether it is read-only, initialization bytecode - - Table - Declares indirect function call table - - Export - Specifies which functions, memories, tables or globals are visible to the host - - Start - Identifies a function that is automatically executed upon instantiation - - Element - Initializes table entries - - Code - Contains the local variables info and bytecode of internal functions (WebAssembly instructions) - - Data - Contains memory initialization information. Each entry includes memory index, the starting position (bytecode and much be a constant expression) and initial data +* **Magic Header:** Identifies the file as a WebAssembly binary. +* **Version number:** Specifies the WebAssembly binary format version. +* **Sections:** (Each section contains a section ID, size, and contents) +* **Type:** Defines functional signatures used in the module. +* **Import:** Declares functions, memories, tables, or globals provided by the host. +* **Function:** Lists the type indices of functions defined inside the module. +* **Memory:** Declares linear memory regions. +* **Global:** Stores internal global variable information. +* **Table:** Declares the indirect function call table. +* **Export:** Specifies entities visible to the host. +* **Start:** Identifies a function executed automatically upon instantiation. +* **Element:** Initializes table entries. +* **Code:** Contains local variable info and internal function bytecode. +* **Data:** Contains memory initialization information (index, starting position, initial data). -WebAssembly by default just produces a single data section. But when using clang/LLVM to compile C/C++ to wasm, it allocate separate sections for different types of data to support programs written in these languages. -- data (Initialized data) -- tdata (Thread related data) -- .rodata (Read-only data) -## Building a shared WASM library +WebAssembly by default produces a single data section. However, when using clang/LLVM for C/C++, separate sections are allocated for different data types: -A WebAssembly dynamic/shared library is a WebAssembly binary with a special custom section that indicates this is a dynamic library and contains additional information needed by the loader. +* `.data` (Initialized data) +* `.tdata` (Thread-related data) +* `.rodata` (Read-only data) -During **compilation**, `-fPIC` flag produces position-independent code whose final address is known only at runtime. Hence, all symbols that is not guaranteed to be local to this shared object will be accessed via `GOT.mem` and `GOT.func` in the generated object code. -During **linking**, `-shared` produces a shared library and `-pie` produces a dynamically linked executable. +## Building a shared WASM library -To generate **a shared WASM library,** the following compiler and linker flags should be used. -``` +A WebAssembly dynamic/shared library is a WebAssembly binary with a special custom section indicating it is a dynamic library, alongside additional loader information. + +* **Compilation:** The `-fPIC` flag produces position-independent code whose final address is known only at runtime. Non-local symbols are accessed via `GOT.mem` and `GOT.func`. +* **Linking:** The `-shared` flag produces a shared library, while `-pie` produces a dynamically linked executable. + +To generate a shared WASM library, use the following flags: + +```bash CFLAGS=-fPIC LDFLAGS=-Wl,-shared + ``` -Additional linker flags that can be used -``` -. -Wl,--import-memory \ - -Wl,--shared-memory \ - -Wl,--export-dynamic \ - -Wl,--experimental-pic \ - -Wl,--unresolved-symbols=import-dynamic \ + +Additional linker flags that can be used: + +```bash +-Wl,--import-memory \ +-Wl,--shared-memory \ +-Wl,--export-dynamic \ +-Wl,--experimental-pic \ +-Wl,--unresolved-symbols=import-dynamic + ``` + ## Metadata added by linker to the shared WASM binary -- The generated shared WASM library binary will have a custom section called **`dynlink.0`** with the following information: -1. WASM_DYNLINK_MEM_INFO which specifies the memory and table space requirements of the module (memory size, memory alignment, table size, table alignment) -2. WASM_DYLINK_NEEDED - Specifies external modules that this library depends on -3. WASM_DYLINK_EXPORT_INFO - Specify additional metadata about exports -4. WASM_DYLINK_IMPORT_INFO - Specify additional metadata about imports -5. WASM_DYLINK_RUNTIME_PATH = Specify the runtime path, corresponding to DT_RUNPATH in ELF binaries - - `wasm-ld` will add `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` functions to the final WASM binary which contain hardcoded information about relocation. +The generated shared WASM library binary will have a custom section called `dynlink.0` containing: + +1. **`WASM_DYNLINK_MEM_INFO`**: Specifies memory and table space requirements. +2. **`WASM_DYLINK_NEEDED`**: Specifies external module dependencies. +3. **`WASM_DYLINK_EXPORT_INFO`**: Specifies export metadata. +4. **`WASM_DYLINK_IMPORT_INFO`**: Specifies import metadata. +5. **`WASM_DYLINK_RUNTIME_PATH`**: Specifies the runtime path (equivalent to `DT_RUNPATH` in ELF). + +Additionally, `wasm-ld` adds `__wasm_apply_data_relocs` and `__wasm_apply_tls_relocs` to the final binary to handle relocation during instantiation. + # Running the .wasm file -This .wasm file has to be interpreted and converted to native code and then run within a VM. - -The steps involved are : -1. Read the .wasm file -2. Parse the structured sections (types, imports, functions, memory etc) of .wasm binary file -3. Validate the module - The module is validated for type safety, structural correctness, and sandbox rules -4. Compile to native code - Wasmtime translates WebAssembly bytecode into native machine code -5. Create a Store and Link Imports - A store is created to hold runtime state, and all declared imports (eg : WASI functions) are resolved to host implementations -6. Instantiate the Module - Transform the static module into a live execution instance. This involves **allocating** all of the module's Linear Memory, tables, globals in the store, creating separate runtime representations for each function, and **linking them to their resolved imports**. and function instances are allocated memory and initialized inside a new instance -7. Initialize Memory and Tables -After allocation, Wasmtime sets up the module’s initial state by populating memory and tables. Data segments from the Data Section of the module are copied into the linear memory at the offsets specified by the module, often including static strings, arrays, or other constants. Similarly, element segments from the Element Section are used to initialize tables, typically mapping function references for indirect calls. -8. Run the start function + +This `.wasm` file must be interpreted, converted to native code, and run within a VM. The steps are: + +1. **Read the file:** Load the `.wasm` file into memory. +2. **Parse structured sections:** Extract types, imports, functions, and memory. +3. **Validate the module:** Ensure type safety, structural correctness, and sandbox compliance. +4. **Compile to native code:** Wasmtime translates WebAssembly bytecode into native machine code. +5. **Create a Store and Link Imports:** A store is created to hold runtime state. Declared imports (e.g., WASI functions) are resolved to host implementations. +6. **Instantiate the Module:** Transform the static module into a live execution instance. This involves allocating linear memory, tables, and globals in the store, and linking runtime representations to their resolved imports. +7. **Initialize Memory and Tables:** Wasmtime copies data segments from the Data Section into linear memory at specified offsets. Element segments are used to initialize tables for indirect calls. +8. **Run the start function:** Execute the module's entry point. # References From 82940b4d7585c560b5f9e9d2f9847440e94c7aec Mon Sep 17 00:00:00 2001 From: Vidya Date: Wed, 4 Mar 2026 11:51:31 -0500 Subject: [PATCH 7/9] Updated motivation and design sections of dynamic loading document --- docs/internal/dynamicloading.md | 52 +++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md index 74545b05f..d565d804b 100644 --- a/docs/internal/dynamicloading.md +++ b/docs/internal/dynamicloading.md @@ -1,37 +1,52 @@ -# Dynamic Loading in wasmtime +# Dynamic Linking and Dynamic Loading in wasmtime -## Motivation -Dynamic loading reduces the memory footprint by allowing shared libraries to be loaded only when they are actually needed at runtime, rather than being statically linked into the application at compile time. This leads to more efficient memory usage, especially when multiple programs share the same libraries. It also avoids code duplication across binaries, reducing overall storage requirements. +## Overview -Another important advantage is improved maintainability and flexibility. When a dependent library is updated, the application does not need to be recompiled, as long as the library’s interface (ABI) remains compatible. This simplifies deployment, enables independent updates, and facilitates security patches without rebuilding the entire application. +### Dynamic Linking +**Dynamic linking** refers to the process of loading the dependent libraries that an application needs at runtime, as opposed to linking them statically when the application is compiled. -Dynamic loading also supports modular and extensible system design. Applications can load optional components, plugins, or backends at runtime based on configuration or environment, making it possible to extend functionality without modifying the core executable. In the applications we evaluate, libraries are explicitly loaded at runtime using `dlopen()` and symbol resolution is performed via `dlsym()`. Therefore, proper support for dynamic loading is a functional requirement to ensure correctness and compatibility with these applications. -## Design Decisions +If a C program invokes `printf()`, in case of static linking, when the program is compiled and linked, the code corresponding to `printf` is a part of the final program executable and hence when the program runs, there is nothing to be explicitly loaded or resolved. -### The Linux Native Execution Model +While in case of dynamically linked program, when the program is compiled and linked, the call to `printf` is left as unresolved and also the final program executable only contains the code and data of the program. The dependent libraries that this program depends on is added to the metadata of the binary. When the program is run, at the beginning, the dynamic linker is given control and it determines the paths of all dependent libraries and loads them to the memory as well as resolve all references to data and code to these libraries. -When a program is executed on Linux, the kernel creates a new process image using `execve()` and maps the ELF executable into the process’s virtual address space. For statically linked binaries, the kernel sets up the stack and auxiliary data structures, then transfers control directly to the program’s entry point. +### Why Use Dynamic Linking +1. It reduces memory and storage footprints by loading shared libraries at runtime. Multiple programs can share the exact same library in memory, eliminating code duplication across binaries. -For dynamically linked binaries, the execution model splits responsibilities: the trusted kernel handles the initial loading, but dynamic loading is managed in user space. The ELF header contains a `PT_INTERP` segment specifying an external dynamic loader (typically `/lib64/ld-linux-x86-64.so.2`). The kernel maps this loader into the same process and transfers control to it. The loader then pulls in required shared libraries, resolves symbols, and performs relocations before finally jumping to the program's entry point. Crucially, this dynamic loader operates entirely within the untrusted user-space environment, sharing the same virtual address space as the main executable. +2. It allows shared libraries to be updated or patched for security without requiring the applications to be recompiled, provided the application binary interface (ABI) remains compatible. + + +### Dynamic loading +**Dynamic loading** refers to the loading of dependent libraries on the fly only when the application explicitly requests them (eg., via `dlopen()`) and resolving the symbols using `dlsym` + + +### Why Use Dynamic Loading +It enables applications to load optional components, plugins, or backends at runtime based on configuration or environment, making it possible to extend functionality without modifying the core executable. This supports modular and extensible system design of applications. + +**In a traditional Linux system, both of these responsibilities are managed by the dynamic linker/loader, `ld.so`.** -### The WebAssembly Execution Model -In contrast, WebAssembly (WASM) binaries are not executed directly by the operating system. They run inside a trusted host runtime, such as Wasmtime, which parses and validates the module, JIT-compiles the code, and instantiates it. -Instantiation involves allocating linear memory - a contiguous, sandboxed memory region - initializing globals and tables, and copying data segments into memory. Unlike native ELF binaries, WASM modules do not rely on OS-level virtual memory mapping. Instead, execution, memory management, and boundary mediation are handled entirely by the runtime, which enforces strict isolation and memory safety. +## Motivation for adding dynamic linking/loading in wasmtime -### Dynamic Loading within the Lind System +In case of Lind, we implement dynamic loading for wasmtime to support applications like scripting language interpreters (eg: python), web servers (Apache HTTP, Nginx) that load modules at runtime using `dlopen/dlsym`. Additionally, we also extend wasmtime to support dynamic linking so as to reduce the memory footprint of our webassembly binaries and to eliminate the overhead of recompiling entire applications whenever underlying libraries are updated. -In the Lind system, dynamic loading support is implemented by fundamentally extending Wasmtime’s parsing and instantiation mechanisms. Calls from `glibc`, such as dlopen, dlsym, and dlclose, are redirected to runtime-provided implementations. The runtime then loads additional WASM modules, allocates memory, resolves symbols, and handles relocations natively. -Unlike the traditional Linux model where dynamic linking is delegated to an external, untrusted user-space process, Lind integrates the dynamic loader directly into the trusted Wasmtime runtime. This architectural shift is necessary for several reasons: +## The Linux Native Execution Model + +When a program is executed on Linux, the kernel creates a new process image using `execve()` and maps the ELF executable into the process’s virtual address space. For statically linked binaries, the kernel sets up the stack and auxiliary data structures, then transfers control directly to the program’s entry point. + +For dynamically linked binaries, the execution model splits responsibilities: the trusted kernel handles the initial loading, but dynamic loading is managed in user space. The ELF header contains a `PT_INTERP` segment specifying an external dynamic loader (typically `/lib64/ld-linux-x86-64.so.2`). The kernel maps this loader into the same process and transfers control to it. The loader then pulls in required shared libraries, resolves symbols, and performs relocations before finally jumping to the program's entry point. Crucially, this dynamic loader operates entirely within the untrusted user-space environment, sharing the same virtual address space as the main executable. + +## Design Decisions + +Unlike traditional Linux systems that rely on a standalone dynamic linker/loader (like `ld.so`), we have extended the wasmtime WebAssembly runtime to handle dynamic loading internally. We chose this design strategy for the following reasons. -1. Architectural Consistency: An essential requirement of any dynamic loader is the ability to read memory contents, resolve symbols, and modify relocation targets. Because the WebAssembly runtime already maintains absolute control over module memory, function tables, and instantiation state, extending it to handle dynamic loading is a natural fit. +Beyond determining paths and loading dependent libraries into memory, a primary responsibility of a dynamic linker/loader is resolving symbol references - mapping the program's imported functions and data to the correct memory addresses (exports) within the external modules. To accomplish this, the loader must have the privilege to read and modify the memory of both the executing program and the loaded libraries. In Linux, this is achieved by mapping the dynamic loader and the shared libraries into the same virtual address space as the executing process. -2. Performance and Efficiency: WebAssembly linking requires direct, synchronous modification of internal runtime state, such as indirect function tables and memory bounds. Relying on an external loader process to manipulate these structures would introduce prohibitive overhead from inter-process communication (IPC) latency, data marshaling, and serialization. +WebAssembly (WASM) binaries, however, operate under a different paradigm. They run inside a trusted host runtime (such as Wasmtime) that parses and validates the module, JIT-compiles the code, and instantiates it by allocating a contiguous, sandboxed linear memory region. WASM modules do not rely on OS-level virtual memory mapping. Instead, execution, memory management, and boundary mediation are handled entirely by the runtime to enforce strict isolation and memory safety. -3. Security: By internalizing the dynamic loader, the system avoids context-switching to an untrusted environment, ensuring that the entire module instantiation and linking process remains fast, secure, and securely isolated within the trusted computing base. +Because the WebAssembly runtime already maintains absolute, privileged control over module memory, function tables, and instantiation state, extending the runtime itself to handle dynamic loading is the most secure and natural fit. ## Current Implementation Status We have implemented dynamic loading support in Wasmtime. For applications that are compiled as dynamically linked executables or shared libraries, we are able to support both capabilities below: @@ -42,6 +57,7 @@ We have implemented dynamic loading support in Wasmtime. For applications that a ## Additional Features to be added: 1. Support for fork, threads, and signals within the shared libraries. +2. As of now, the dependent libraries have to be explicitly specified using `--preload` option. The compiler (`clang`) is supposed to add metadata about the required libraries when `--shared` or `-fPIC` option is used. Currently this is not working. This has to be fixed so that compiled adds the metadata and the dynamic loader can parse the metadata to determine the libraries required at runtime. ## Changes made to implement dynamic loading: From cd510eb9c4c8f51cff2bbac2130b2eaf6fd032a6 Mon Sep 17 00:00:00 2001 From: Qianxi Chen Date: Sat, 23 May 2026 10:23:13 +0000 Subject: [PATCH 8/9] resolve comments --- docs/internal/dynamicloading.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md index d565d804b..f39c3b2b5 100644 --- a/docs/internal/dynamicloading.md +++ b/docs/internal/dynamicloading.md @@ -53,11 +53,12 @@ We have implemented dynamic loading support in Wasmtime. For applications that a 1. Launch the application while injecting all required dependent libraries using the `--preload` option (similar to `LD_PRELOAD`). 2. Ensure that `dlopen()`, `dlsym()`, and `dlclose()` are properly resolved at runtime and corresponding libraries loaded. +3. Partial support for fork and threads within shared libraries: global snapshot propagation and name collision detection are implemented (tasks 1 and 2 of [#1028](https://github.com/Lind-Project/lind-wasm/issues/1028)). Cross-thread epoch-based dlopen replay and full signal handling within shared libraries remain to be done (tasks 3 and 4). ## Additional Features to be added: -1. Support for fork, threads, and signals within the shared libraries. -2. As of now, the dependent libraries have to be explicitly specified using `--preload` option. The compiler (`clang`) is supposed to add metadata about the required libraries when `--shared` or `-fPIC` option is used. Currently this is not working. This has to be fixed so that compiled adds the metadata and the dynamic loader can parse the metadata to determine the libraries required at runtime. +1. Complete support for fork, threads, and signals within the shared libraries (tasks 3 and 4 of [#1028](https://github.com/Lind-Project/lind-wasm/issues/1028)). +2. As of now, the dependent libraries have to be explicitly specified using `--preload` option. The compiler (`clang`) is supposed to add metadata about the required libraries when `--shared` or `-fPIC` option is used. Currently this is not implemented. This has to be fixed so that the compiler adds the metadata and the dynamic loader can parse the metadata to determine the libraries required at runtime. ## Changes made to implement dynamic loading: @@ -65,7 +66,7 @@ To execute WebAssembly applications within Lind, Wasmtime is modified to interfa ### Parsing the dynamic section -The `dylink.0` custom section within WASM shared libraries is parsed to retrieve dynamic linking metadata. The `load_module` function is responsible for parsing the entire WASM binary to extract all section contents, including code, data, imports, exports, and dynamic linking information. As of now, `memory_size`, `memopry_alignment`, `table_size`, `table_alignment` and `importinfo` are parsed. We do not handle `needed` and `exportinfo` contents of `dylink.0`c section. +The `dylink.0` custom section within WASM shared libraries is parsed to retrieve dynamic linking metadata. The `load_module` function is responsible for parsing the entire WASM binary to extract all section contents, including code, data, imports, exports, and dynamic linking information. As of now, `memory_size`, `memory_alignment`, `table_size`, `table_alignment` and `importinfo` are parsed. We do not handle `needed` and `exportinfo` contents of `dylink.0`c section. ### Handling libraries passed via `--preload` @@ -124,7 +125,7 @@ This host function is responsible for finding the memory address or function ind #### `dlclose` (Lifecycle Management) This function manages the cleanup and unloading of libraries. * **Reference Counting:** Decrements the reference count of the library identified by the provided `handle`. -* **Unloading:** If the reference count reaches zero and the library is flagged as deletable (i.e., it was not loaded with `RTLD_NODELETE`), the host removes it from the global symbol table and frees associated resources. +* **Symbol Table Update:** If the reference count reaches zero and the library is flagged as deletable (i.e., it was not loaded with `RTLD_NODELETE`), the host removes it from the global symbol table so that subsequent `dlsym` calls will not resolve symbols from the unloaded library. Note: the library is **not truly unloaded** from memory in the current implementation — fully reclaiming Wasm module resources within Wasmtime's architecture is non-trivial and is tracked as a future improvement. * **Returns:** `0` on success, strictly adhering to POSIX-compatible conventions. @@ -201,7 +202,7 @@ Additional linker flags that can be used: ## Metadata added by linker to the shared WASM binary -The generated shared WASM library binary will have a custom section called `dynlink.0` containing: +The generated shared WASM library binary will have a custom section called `dylink.0` containing: 1. **`WASM_DYNLINK_MEM_INFO`**: Specifies memory and table space requirements. 2. **`WASM_DYLINK_NEEDED`**: Specifies external module dependencies. From 888ebf5506cfdec85e8c4bb4260d27e59d5f0e35 Mon Sep 17 00:00:00 2001 From: Vidya Lakshmi Rajagopalan Date: Sun, 7 Jun 2026 07:11:41 -0400 Subject: [PATCH 9/9] Update docs/internal/dynamicloading.md Co-authored-by: Alice Wen <40227173+Yaxuan-w@users.noreply.github.com> --- docs/internal/dynamicloading.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/internal/dynamicloading.md b/docs/internal/dynamicloading.md index f39c3b2b5..77e251179 100644 --- a/docs/internal/dynamicloading.md +++ b/docs/internal/dynamicloading.md @@ -58,7 +58,7 @@ We have implemented dynamic loading support in Wasmtime. For applications that a ## Additional Features to be added: 1. Complete support for fork, threads, and signals within the shared libraries (tasks 3 and 4 of [#1028](https://github.com/Lind-Project/lind-wasm/issues/1028)). -2. As of now, the dependent libraries have to be explicitly specified using `--preload` option. The compiler (`clang`) is supposed to add metadata about the required libraries when `--shared` or `-fPIC` option is used. Currently this is not implemented. This has to be fixed so that the compiler adds the metadata and the dynamic loader can parse the metadata to determine the libraries required at runtime. +2. As of now, the dependent libraries have to be explicitly specified using `--preload` option in lind-boot. The compiler (`clang`) is supposed to add metadata about the required libraries when `--shared` or `-fPIC` option is used. Currently this is not implemented. This has to be fixed so that linker/wasm-ld should emit wasm dynamic linking needed metadata, and the loader can parse it to determine the libraries required at runtime. ## Changes made to implement dynamic loading: