Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load precompiled module from library loaded by the OS loader? #7777

Open
Milek7 opened this issue Jan 15, 2024 · 5 comments
Open

Load precompiled module from library loaded by the OS loader? #7777

Milek7 opened this issue Jan 15, 2024 · 5 comments

Comments

@Milek7
Copy link
Contributor

Milek7 commented Jan 15, 2024

Feature

Precompiled modules are ELF files that seemingly are able to be linked into executables. Would it be possible to let them load using OS loader (either by linking them into application binary, or linking into shared object and dlopen), and then import this code into wasmtime Module?

Benefit

Support of platforms that doesn't allow mapping pages as executable, like iOS or game consoles.

Implementation

Module::deserialize variant that takes pointers to already loaded segments and fills them into CodeMemory struct instead of mmaping them. Probably also needs #7349 to be useful.

@pchickey
Copy link
Contributor

Serialized modules happen to use the ELF format, but that should be treated as an internal implementation detail to Wasmtime and is not intended to be exposed to any loader other than Module::deserialize, such as an OS loader.

In general if pages can't be mapped as executable at all, then Wasmtime won't work whether it is mapping those pages out of a file (as in deserialize) or materializing them otherwise to create an executable Module.

Can you tell us more about the use case that motivates this request? Maybe there is another way to meet it.

@Milek7
Copy link
Contributor Author

Milek7 commented Jan 16, 2024

Use case is using Wasmtime on platforms which limit mapping pages as executable. As I understand it, Wasmtime only needs to map compiled code as executable during Module creation, and doesn't need to generate any new code during execution, right? (with the exception of generating host function trampolines, but I take that this is intended to be removed too)

@alexcrichton
Copy link
Member

Yes once a module is loaded and executable no further executable mappings need be may (so long as you don't use Func::new and friends or create new modules). It's theoretically possible that a precompiled module could be made into a linkable object to link into the main application, but that's a pretty significant chunk of work to be done at the API layer in addition to the object layer. Currently the ELF artifact, as @pchickey mentions, "just happens to be ELF" and isn't suitable for actually linking into an application.

Are you working with a platform like iOS that doesn't allow mapping executable memory at all? Or something along those lines? If new executable memory can be dynamically loaded Wasmtime should work well, but if all the executable memory must be statically enumerated that'll be more difficult.

@Milek7
Copy link
Contributor Author

Milek7 commented Jan 16, 2024

I'm looking at feasibility of using wasmtime on game console. I will know more about the limitations later but it would be under NDA so I probably won't be able to discuss them here anyway. Alternatively I'm considiering using something like wasm2c, but that would require more changes in embedding code so getting wasmtime to work would be nice.

I'm correct in that if sections from ELF artifact would be loaded into address space (with .text mapped as executable), it would suffice to basically modify CodeMemory::new to read header from passed pointer (obviously it won't be header of real underlying file, just decoy to point to already loaded data), and make CodeMemory::publish no-op? Or is there something more to it? It would need some external tooling to mangle precompiled output into object file that can be used, put decoy header in there, etc, but doesn't seem too complicated.

As for Func::new, I found that this proposal https://github.com/bytecodealliance/rfcs/blob/main/accepted/tail-calls.md specified that after changes wasm → array case would handled by "This trampoline is generated by the Wasm compiler and stored in the compiled Wasm module." Were the plans changed or it's still expected that this change will happen?

@alexcrichton
Copy link
Member

Ah ok makes sense. The exact implementation of this I'm not certain about, but you're on the right track ish. Currently CodeMemory is not exposed from the public API of the wasmtime crate, so while it's part of the internal stuff happening in Wasmtime it's not exposed to end-users to easily integrate with.

What this would perhaps look like is something along the lines of a trait NativeObject in the public API of Wasmtime which acts as a CodeMemory (of sorts). The internals of Wasmtime would use the trait and embedders could supply their own version of statically linked data for example. How exactly an embedder would create such a trait object, though, is a bit unknown to me. That's where there's a good bit of design I think. All technically feasible, but perhaps a little hairy too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants