bjorn: thanks. will come back to that if I need it. will stick to wasm-c-api only for now. extensions if I need them.
you got this weird typedef/enum clash going on. visual studio doesn't like it.
typedef uint8_t wasmtime_opt_level_t;
enum wasmtime_opt_level_enum { // OptLevel
WASMTIME_OPT_LEVEL_NONE,
WASMTIME_OPT_LEVEL_SPEED,
WASMTIME_OPT_LEVEL_SPEED_AND_SIZE,
};
I don't care as going wasm-c-api direct so can work around it but fyi
should change my subject as this isn't WMRT, its wasmtime :)
Great to hear that you have initial things working! Please do let us know about issues as you find them—this is great feedback!
As @Benjamin Brittain says, Wasmtime supports the wasm-c-api. It does have some additions, such as support for WASI, but those might not be immediately relevant to your use case, at least to begin with
yeah, nothing like hitting something for real to see what happens :)
looks like I should be able to get the basics up & running from here. so lets see ...
cheers guys :)
(it also has a few things stubbed out like wasm_frame_instance
)
good point on the stubs, yes. There are some corners of the api that we've only filled in as needed
runs, works as expected. clean exit.
<><> contact :)
for clean wasm-c-api, standard wasm.h header can be used with wasmtime-c-api, wasmtime.h and wasi.h just for extras
had no joy compiling against your extras & as noob don't need them just yet. pushed me to the standard stuff where I should be anyway so all good. can look at how to interface to your extensions when I get that far. cheers.
@Steve Williams oh one important thing to note is that the examples in the repo should be up-to-date, but they need to be paired with the same version of wasmtime. There's been a number of changes to wasmtime-specific APIs since 0.15.0 so if you're using the examples in the repo you'll likely need to use the dev releases
yup - understood. getting my head around standard wasm-c-api first :)
thanks. don't suppose there's a chatroom for that somewhere as that's not really what this room's for.
thinking where to start. we've had versions of our scripting interface in javascript, java, csharp and native.
as I like c++, found this : https://github.com/alexnoz/wasm-class-sample/blob/master/dog.cc
maybe start there, which is comfortable for me, but not necessarily for webdevs.
this is a bit off topic for here but anyone for insight for what's the cleanest performant web assembly source language that will suit webdevs ?
with an example & means of compilation. the easier it is, the better as we're going for accessibility here.
maybe I do start there. gets me a class. I'll want instances of the class to connect to their native equivalent somehow. have done this before by having a master engine class which generates instances of things, which creates the instances inside a callback, which binds in a native instance, which should be hidden from the runtime view. the native pointer is accessible from within native callbacks.
that's too much for here. sorry thinking out loud. I'll shut up and just do it :)
Note that that example uses Emscripten, which means that it won't work with Wasmtime, as Wasmtime doesn't support Emscripten's ABI
that's gold, thanks :) care to suggest something that will work ?
As for source languages, I think Rust and AssemblyScript are the best supported ones right now, and are generally seen pretty positively by webdevs. C++ might work, but is seen as much scarier by most webdevs
the problem is that right now you need some kind of binding layer for being able to communicate using high-level data types (as opposed to just numbers). Interface Types will address that, but neither is the spec done, nor do we have a complete implementation in Wasmtime, nor is there a C++ toolchain for them :confused:
I know that both @Dan Gohman and @fitzgen (he/him) had sketches of a C++ bindings layer that could work, but I don't think there's anything you could just take and run with
hmmmmm ....
don't need anything fancy. I can get objects into native callbacks. if I have a void * I can scribble in there, I can tag in our native thing and in a destructor, remove it, with access in any of the methods. if you don't have a void * I can scribble in, doesn't sound the hardest job ever to add one.
& that wouldn't be accessible script side so would be safe & secure.
binding all this is the tricky bit. I've done it with other scripting APIs so just going at it should get me to the point of identifying what's missing, if anything.
looking for a simple assemblyscript exampel, bit like the Dog C++ one above. no joy thus far.
assuming its a bit like javascript, which would keep current webdevs happy, but I know nothing - this is all new to me.
realize you guys like your rust & we'll support that in due course, just don't think its the smart move right now as it does nt help migrate existing web apps over.
I'm here - noob on multiple fronts whilst just about to write something tricky :)
https://www.sitepen.com/blog/getting-started-with-assemblyscript/
gets my head in the right place. so assemblyscript it is. coz easy ish. will learn it as I go, I suppose :)
think I'm in the scripting twilight zone :)
here's the bit I don't understand. my native c++ engine instantiates wasmtime. wasmtime loads a wasm binary. that wasm binary asks what invoked it (my c++ thing) to create a Foo. how does whatever compiles mything.as know the class Foo exists ? in .net I had a bootstrap assembly we referenced in with all this stuff defined in it.
here's a snippet from our mono csharp bootstrap.
public class Zone
{
[DllImport("__Internal")] static extern IntPtr Zone_CreateNative();
public Zone()
{
m_native = Zone_CreateNative();
}
IntPtr m_native;
}
Its not ideal, as the native pointer is visible script side but hopefully you can see what I'm trying to do.
assemblyscript looks like rust, think I'm being conneed into migrating to rust here :) but whatever. web assembly is language neutral so can backtrack later :)
so, from what I've seen, callbacks into trusted native code can be compiled or at least referenced.
Then you have
[DllImport("__Internal")] static extern void Zone_SomeMethod(IntPtr native);
void Zone::SomeMethod()
{
Zone_SomeMethod(m_native);
}
... to hook native interop into the scripted equivalent.
that probaby has some fancy comp sci terminology I don't understand. I just do it :)
it works & looks like it'll work again, but I don't want the script to be able to see its m_native handle as modifying a native pointer would be bad. as would doing unsupported things with it such as swapping handles between two instances or any other hackery.
equivalent of __Internal in mono appears to be this stuff in wasm text thingy.
(func $print (import "" "print") (param i32) (result i32))
(func $closure (import "" "closure") (result i32))
which then gets bound by the runtime as per the examples.
so just a case of figuring out the syntax for that bit.
guessing I can compile that into a module other wasm stuff can bind to ... equivalent of our mono bootstrap.dll
but I have no idea yet as new to this stuff :)
so ... I can hack together a bunch of import functions into a wsm text thingy, which our runtime will load & fix up the pointers as per sample code examples. what I don't understand is how a wasm thing I'm compiling knows about this stuff.
something like this ?
https://github.com/AssemblyScript/assemblyscript/blob/master/tests/compiler/external.ts
going right to basics, we got this as the simples wasm example.
https://github.com/WebAssembly/wasm-c-api/blob/master/example/hello.wat
which is a precompiled script in text format. what might be the equivalent of that in assemblyscript.
ahhh :)
https://assemblyscript.org/docs/std/
sorry, too much thinking out loud.
I got this as my first I have no clue what I'm doing rough block out. have no idea if it compiles yet :)
if I can get something like that to at least run, that gets us to roughly where we were with mono. can then worry about how to lock down the native pointer & perhaps specifiy it better as it doesn't need to be 64 bit on 32 bit run times.
ooh, we got uintptr type. that's better.
sorry :)
hi. me again, with trivial questions. wanting to experiment with assemblyscript. I'm on windows (can use linux, but I want a windows end-end solution asap). so I need asc.exe to compile. finding one seems harder than I'd expect. any clues ?
found assemblyscript discord channel, so can ask issues specific to that tool chain over there rather than bother you lot :) sorry.
yeah, I think the ASC Discord channel is probably better for these questions—lots more people with good knowledge of that toolchain than here :slight_smile:
Its a whole world of pain. their toolchain relies on node.js which is a whole ecosystem I'd like to avoid. so I'm trying emscripten after you said not supported coz I don't see the problem if I keep within your constraints & not wanting to lose my mind with crate weirdnesses either :)
think I'm getting old, I just want to have a source file and have it compile. I don't want to install zigabytes of junk with weird names for stuff.
I learnt a crate is a library. library is a fine word. we don't need to rename things :)
this is the problem with open sores software, it gets way too nerdy. I like to keep things simple :) rant over :)
If your target audience are webdevs, I'm really skeptical C++ is the language to go with, but anyway, I hope things work out
absolutely, but right now, my audience is me to get our wasm stuff talking to our native stuff and I'm a c++ guy.
(I will point out that while pears are very similar to apples indeed, it still makes sense to not call them apples)
once wasm -> native is working, we can hook up various languages on top of wasm.
that being the point. everyone can use whatever high level stuff they want once the interfaces are established.
your stuff is nice - its all the stuff over this that's got holes all over the place.
emscripten may not be ideal, but it actually installs without too many weirdnesses and actually compiles its own examples with errors.
if assemblyscript did that, I'd be using assemblyscript :)
given assemblyscript targets your runtime, it'd be nice if it compiled itself to target your runtime. then node.js weirdnesses can get trashed.
before I dive into this any further, how are you guys doing performance wise vs .net assembly mono & microsoft implementations - close or miles out at this point. not sure how mature this stuff is. in fact, haven't much of a clue if ready for prime time.
I don't think those are directly comparable, because the source languages are so different. Going from C++ or Rust, you should expect something along the lines of 50% of native performance for most usage. Not sure for AssemblyScript, but then there's no "native" version of that ...
Fastly have a very different use case from yours, but for that they have pretty impressive results: https://www.fastly.com/blog/lucet-performance-and-lifecycle
(Fastly is using a different runtime, Lucet, which is a sibling to Wasmtime and pretty much the same wrt to runtime performance)
thanks I'd like to see the results of the same benchmark running on .net and wasmtime on the same machine. mono & ms for .net.
not your problem, obv, but that's what I'd like to see.
so, performance aside, lets look at practicalities. here's my minimal c++ testcase & an extract of what emcc spits out.
Zone_CreateNative is my experimental wasm callback thingy I can fix up as per wasm-c-api example.
the others are concerning. I don't understand how they resolve. is this why you were saying don't use emcc ?
don't even want to do it quite like that, but I'd expect one unresolved from that. happy to switch languages to get what I need. doesn't have to be c++. just want to get into solution space asap. not have holes.
is this one for the emcc guys ?
ie. how to get it to spit out entirely resolved output. (except for anything deliberately external)
if the answer to getting things to resolve is just switch to rust like everyone else, then I guess I do. if that's the solution path, then it is.
maybe I get that as its just compiling one source file & not linking. I have no clue, this is all new :)
I won't be able to look into this enough to be able to answer these questions, I'm afraid :frown:
understood. what I need to progress further is any high level language that emits resolved output that runs in wasmtime. with explicit externals where I put them so I can hook them up. if that's not possible, I gotta go back to .net assembly as I need a solution not a problem.
got to be frank - if this isn't ready, then its not. we're out of cash & I've got to ship product. this is interesting but if its not ready, our v.1 will have to target .net assembly.
and understand you work from wasm down. what generates that isn't your problem.
also not sure how hiding our native pointers is going to work. in .net assembly, there's the concept of objects so we can hook something in those the managed script can't see. web assembly is lower level. everything is seen.
if I can get a working example in any language, I can play around & try to figure something out.
the final issue is the only one that's appropriate for here. we need a means of securely connecting from script side to native that the script side can't see. if we can't do that, web assembly, weirdly wouldn't be secure enough to use and so got to stop there.
if I'm understanding correctly, unlike .net assembly, web assembly doesn't have an object model. that, I think is a deal breaker as we can't connect securely. maybe I'm wrong. as I can't compile an example right now, I'm not in the code enough to be sure.
to fix this, you need the concept of a hybrid class shared between native & script side. the script side can call methods native side but can't see the native side pointer. I don't think you have that yet.
Do we have any doc/blog that discusses the wasmtime components. I just wanted to read about it and understand how the wasm code is executed.
Hmm, I don't think we do, but that sounds like something that'd be really useful! @Dan Gohman, is there something in this direction somewhere?
is there a document or summary of the low level types supported by wasm ? is there the equivalent of a base class for objects ?
did .net assembly just win ?
:)
because secure. its the web. if your security derives from security in the javascript layer, you're not inherently secure, as the js layer is legacy.
hope I'm wrong.
yes, somewhat true in case of emscripten, its binding layer give a world to wasm code. you have to be careful what you are exposing to untrusted code.
thanks, yury. played around a bit more, came up with this.
but I can't, as far as I'm aware hide the secure base class away. I want the runtime to define that and never let derived types access it direct.
... but then we need to be able to get stuff done so we need secure methods, which gets us to this.
which I'm not really liking. At this point, I'm thinking .net assembly is more elegant & secure.
like I say, hope I'm wrong, I'm noob at web assembly. I might have completely the wrong end of the stick here.
regardless of the language & exact approach, I think this boils down to the runtime needs to define the base class for anything you need to interop with the runtime. dot net implements that web assembly doesn't. as of current version.
The Wasm security model is definitely as strong as (properly sandboxed) .Net, but the mechanisms are quite different, so I think applying the same kind of pattern matching might not be the right way to go.
I'd encourage you to read up on Wasm more thoroughly before jumping to conclusions. At the same time, I appreciate that you have limited time, so perhaps going with something that you're already more familiar with makes sense.
in the event we deliver a solid 3d web solution, our choice of secure scripting mechanism will be fairly permanent, as javascript is for html today.
so I'd like to get it right. to make a decision based on what is the best technical solution, rather than quick fix.
as of this moment, I'm thinking .net is a better architecture. its more secure. I want to be wrong. that's why I want some straight c++ that compiles to wasm so I can see exactly what's going on.
I want to try to corrupt my own example script side to see if I can. right now I'm not seeing anything stopping me.
can even drop the c++ requirement & code this in web assembly direct. I still need a base class with a runtime side pointer my runtime overload will allocate that the web assembly code can't access directly.
Ok, all I can say at this point is that Wasm isn't less secure, and that its security model has nothing to do with JS, but I unfortunately don't have the bandwidth to talk you through the architecture. There's a wealth of information about it available, though
If its not less secure, where is your base class, please.
have I lost the plot here ? am I making sense ? I am new to this system. I could be completely wrong and I should read more. I picked this up a day ago. its way too early to jump to conclusions, especially before experts.
there needs to be a protected pointer in classes that are shared with the runtime. what is the mechanism for ensuring script side can't access such pointers please.
or, if you don't have such a thing yet, can you see the need. I get that this is new. I understand I can't have everything today and that code evolves.
[Runtime view] <----- method <------- [wasm view]
to do anything on the DOM.
in legacy, you go via javascript. when using wasm direct, there's no javascript isolation layer.
https://webassembly.org/docs/semantics/#types
I'll add to that unprotected memory - stuff created & managed by the native app DOM ("web browser") - an extension to your runtime, running in the same memory space.
Pointers to unprotected memory must be guarded or you just lost whatever security you had.
Only trusted methods - implemented runtime side should be able to access unprotected memory pointers.
I'm heading back to mono / .net as I need a secure performant scripting system without a bunch of legacy in the middle. if you don't have that yet, but you do in html browsers with javascript magic I don't currently comprehend, perhaps you can boil your magic javascript down to its core essentials to in effect get wasm a secure base class. sorry I can't contribute more but funding crisis means I need to deliver an immediate solution to assure investors.
Uhm, Wasm was designed with memory safety in mind, and AFAIK accessing anything out-of-bounds for instance is inherently illegal in Wasm and will result in an immediate trap. Did you perhaps have a look at this?
yeah I looked at that. obj_1 with dom handle. obj_2 with dom handle. wasm code swaps the handles. bad stuff happens.
wasm was designed with javascript running on top. when you take that away, it falls apart. show me an example with a single dom base class implemented trusted ("web browser") side, accessed wasm (untrusted script side) that I can't break.
Hmm, given my limited knowledge of how DOM classes actually work, I'm not sure I understand what the problem is. But that aside, is your usecase targetting Wasm + JS, or standalone Wasm?
standalone. as I can do with mono. mentioned not to annoy you but to explain where solution space is.
Oh, not to worry, not getting annoyed, just trying to understand where you're coming from ;-)
k, currently here : https://github.com/WebAssembly/wasm-c-api/blob/master/example/hello.c
OK, so how do you think standalone Wasm with Wasmtime runtime say is any less secure than .NET vm?
hello_callback is untrusted. I can do anything there - it's straight c
including call native methods using a native pointer. that example doesn't have one as its too simple but take it a step further to pull one out of its parameters and you can.
But hello_callback
is the callback supplied by you, the runtime provider, is it not?
yes. that's what makes it trusted code. I wrote it so I trust it coz I know what its doing.
So if you open up for an attack inside a callback like this, then it's the runtime's problem, is it not?
What I'm getting at here, is that Wasm code that's executed by your runtime is untrusted and sandboxed but only as much as you will provide in your runtime
absolutely. we don't open up an attack inside our callback. we're careful. we're the web browser.
but what we have to do is give the script a reference of some kind to one of our things. lets keep it simple and say a html table.
say the script wants to add a row to the table, it has to tell us what table it wants to add a row to.
wasm-c-api and web browser use cases are not the same
I know :) its not all about web browser. its about having trusted stuff and untrusted stuff and having some way of communicating across that divide.
Can you explain why two thing are mixed in the same conversation?
Yeah, I'm kinda confused here as well :-)
web browser / web script is the obvious example.
Oh, and in WASI, you can only communicate with resources if you've given such a capability to the runtime in the first place
So even if your Wasm binary wants to access /dev/random
say, it will only be able to if and only if you, as the runtime user, will provide such a capability
So I guess to answer your question, in WASI, the comms across the divide (trusted vs untrusted) should happen only via capabilities
Also, looks like you fond of mono, can you provide hello_callback example of how mono does embedding + callback. Is it described in https://www.mono-project.com/docs/advanced/pinvoke/ ?
pinvoke is nasty. that's what I don't like about mono, you can call out to anything.
okay
I don't know your stuff well enough yet, but lets see if we can get an example so we're on the same page.
without JS or DOM please :) wasmtime does not know what it is
yeah, I know, DOM is just shorthand for trusted native. its not all about web browsers.
@Steve Williams from what you've been saying, I believe that wasm would fit your use case but it may not be quite as you might imagine (and not the same as mono). The feature that wasm has to support this is called anyref
and is part of the reference types proposal. This proposal is not currently fully implemented in Wasmtime nor is it a fully finished proposal, it's still in the stabilization process. The purpose of anyref
is so that the host can pass a value to a wasm module which is impossible for wasm to forge. For example you could pass your html table directly to wasm, and wasm couldn't do anything with it other than pass it back to you later on (which is what it sounds like you're going for)
As a workaround today we implement this with table indices. The host has a table of object it wants the wasm module to have access to, for example you'd have a list of html tables on the host, and you'd pass indexes into the table to the wasm module. When calling a host API the host would then need to translate that index to a resource. The context of the API indicates that the index is to the list of html tables, and the host would bounds-check that
alex - that sounds about right - thank you :)
this is not a perfect solution, but it is what works today. This is how WASI is implemented which works with files/directories/etc, where the host has a table of files/directories and passes i32 file descriptors to the wasm module.
Once fully implemented everything will be anyref
though where you will literally pass an unforgeable reference to a wasm module, and then wasm will later pass it back to your host imports.
You are guaranteed that wasm never modified the value, and you're also guaranteed that the host constructed the value.
I'm not personally familiar with .NET but it is likely not as powerful as .NET. The anyref/reference-types proposal is pretty minimal and doesn't allow things like classes/extensions/etc, it's just opaque values being passed around. Whether or not that works for your use case I'm not sure.
handles are a bit better but script side can still mess with them. I want tight binding between script side view and runtime view such that script side can't even see, never mind change its runtime side reference - however that might be represented. its stuck to it hard & invisible.
You've got no equivalent of mono_object_new
http://docs.go-mono.com/?link=xhtml%3adeploy%2fmono-api-object.html
that's sounding interesting though. if can see but can't mess with, a step in the right direction. problem is you can swap handles to drop them into views of objects they weren't created with when being malicious. in our trusted side, we cast the pointer to what we know it is to do stuff and bang things go wrong. or perform too many checks for it to be performant.
hence don't want untrusted side to have access. at all.
You can store a list of objects. The index received from wasm then points in that list of objects. For safety you then only need to perform a bounds check and you need to check if the object isn't destroyed.
per type. maybe. then if untrusted wants to switch its references around, it does & whatever happens does, but with known types so safe & result is up to the app. maybe. will let that settle.
thanks bjorn3 :)
Hi everyone. Just joining the community. I'm working on a (subset of) Ruby to Web Assembly compiler (see https://github.com/ljulliar/rlang). I'm currently trying to integrate Rlang with Wasmtime (WASI, type interface, command line arguments,...)
Hello!
update. got the basics compiling assemblyscript so should have a working example of above nonsense tomorrow :)
cheers all :)
so ... if I'm understanding, wasmtime is just pure runtime. it doesn't understand anything about file i/o for example. so, first example of the native interfacing I'm proposing should be to add native file i/o support, then assemblyscript compiler could target wasmtime direct.
perhaps trying to run before I can walk here, but that's current thoughts. we'll see where it leads.
The WASI code in wasmtime should give you file IO, I believe; as I glanced at the comments above, I wonder about going down the AssemblyScript route: I've been able to successfully compile C to Wasm (with some limitations) using both Emscripten and wasi-sdk
Yeah, you can access files and directories on the host in Wasmtime via WASI and its capabilities-oriented security model.
We currently only allow for preopening of the directories (preopening meaning, you can give permission to Wasmtime to access some directory on the host).
In the future, this will naturally be extended to other host resources.
Morning all. So if file i/o is there already, is there anything inherently stopping assemblyscript compiling assemblyscript targeting wasmtime ?
I'm not understanding why their dev environment has a node.js dependency. I'd like to see this system "float" on its own - bootstrap itself, or at the very least understand why that hasn't happened yet. If simply its just a job on the list that hasn't happened yet, that's life at the edge :)
EU next gen internet funding event today - most likely a dull webinar, but might interest some.
With regard to this project, I'd like to see AssemblyScript targeting wasmtime & whatever it takes to make that happen funded.
Why - coz if we have a self sustaining ecosystem, we need our own stuff so make sure it's spot on.
Why I'm going AssemblyScript (at least for now) - I'm implementing performant secure scripting into our 3D web tech, with the primary audience for that being webdevs. AssemblyScript is the closest we have right now to what they're familiar with. I prefer C++, but I'm not currently targeting me (did that yesterday - so far so good).
or, to at least prove the principle, is there any compiler to wasmtime that runs within the wasmtime runtime yet ?
if not does anyone have any insight as to why ?
is it simply nobody's been motivated to do that yet ?
or is there some gap I don't currently understand.
with to regard to moving the assemblyscript compiler over, I think that work has merit, I'd like to see it done, but don't want to either do or manage that work as got too much on as it is. if anyone's up for doing that with eu funding (if approved - not up to me), happy to put in a word (not that anyone cares what I think) to say I think that project should be funded. reasoning above.
ummmm .... noob intro has an error. fopen needs to be in "rb" mode, windoze :)
just tried loading something else into it & it failed part way into a load. thought how could that possibly fail, then had that doh moment :)
https://github.com/WebAssembly/wasm-c-api/blob/master/example/hello.c
AssemblyScript seems to want one of these things defining.
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
don't suppose anyone wants to drop some c-api hints as to how to do that. I'll figure it out but shortcuts welcome :)
thats an abort function in namespace env with 4 int32 parameters ?
in the event there's an easier way than patching this up, all ears :)
ummm if that is a namespace thing, I don't see namespaces in the c api. think I'm stuck.
here's my minimal assemblyscript test, modelled as far as possible on c-api hello.c example.
//// ---- code[start]
export declare function hello(): void
export function run(): void
{
hello();
}
/// --- code[end]
that gets me two imports I'm not sure what to do with yet. one I'm expecting, the other seems to be some kind of a default.
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(import "index" "hello" (func $assembly/index/hello))
suggest something like this is a noob tutorial. happy to run with it once I can see what I'm doing.
export declare function is a very long winded way of saying import, but lets not mess with assembyscript syntax just yet :)
also, as these are c-api questions, maybe this isn't the right place for them as you have a runtime that implements the api, you're not maintainers of the api.
c-api examples are missing an example that resolves multiple imports from an assembly explicitly by name so I know I'm assigning things correctly.
docs seem light. will have another look at the headers to see if it's obvious.
nope. checked the header. I pass in an array of external functions. I don't understand how I present that in the right order. I need to bind my implementation to its identifier not cross fingers & hope things are in some pre-deterimined order ... I think. unless I can create some kind of a binding module that does have them in a guaranteed order.
happy to pivot to your extensions api if that's required to resolve these robustly.
c-api module has meta data that describes import and exports types and names.
ahhh ... thanks. care to shine a light on where that is please :)
searched meta in wasm.h ... nothing.
there is an example about exports https://github.com/WebAssembly/wasm-c-api/blob/master/example/reflect.c#L128 , but imports will look the same, see wasm_module_exports and wasm_module_imports
thanks, yury. will see if I can get my head around that.
is there a doc somewhere explaining how wasmtime run command line arguments are being passed to the _start entry point of the WASM module ?
Not as such. "_start" doesn't get passed args; the program to query for them via args_sizes_get
and args_get
calls.
Are these functions imported in the WASM module by the WASm runtime ? (let me explain: I'm writing WAT code more or less directly by hand so I cannot rely on C to wasm or Rust to WSM compiler to handle that for me)
Yes, these are WASI functions, imported in a wasm module and typically implemented by the runtime.
In a C or Rust toolchain, the code to call these and set up the user-facing argv is added by the toolchain
A little more of my nonsense - sorry. I've got getting my head around the reflection stuff to do next but gave the whole problem some more thought.
Our use case is secure performant 3D web scripting. My first thought was to go with AssemblyScript as initial webdev supported language for that. However, if I'm honest, I don't like it. The current compiler runs in node.js which means the compiler is written in javascript. Which hardcore compiler engineers write their compilers in js ? Not many. What's the optimal compiler toolchain right now ? llvm stuff. So for webdevs, we get to rust. Which isn't a million miles away in terms of syntax from AssemblyScript. So think I pivot our connectivity to Rust. Thinking out loud. Hope that's ok. Realise entire point of WebAssembly is to be language agnostic, but all the same I have to choose one. Others can be supported later.
Apologies if anyone here works on what I just dismissed. Maybe its great and I'm wrong.
Ahhhh ... doh, got it. AssemblyScript compiler isn't written in javascript, it hooks into html browser tech tree javascript compilers. So it'll be decent. However, the focus there is speed of compilation over pure optimized performance so still reckon llvm path is a better call.
Anyhow, we'll see. As long as interface is accessible from all, plenty of R&D, competition & complementary approaches possible.
Not the biggest fan of Rust syntax from what I've seen, but it'll do for now.
& that's why AssemblyScrript compiler guys can't target wasmtime, coz they need to pull the compiler from the legacy tech tree :)
or maybe I'm way off. haven't checked the code, running this in my head, which isn't always right.
This looks to be my new starting point : https://dev.to/h_ajsf/simple-rust--wasm-example-5b1m
Too much off topic rambling here, sorry, not sure where else to put it.
Don't need all of that as not hooking into js/html, but lets me build a simple example. yay :)
will create our own channel somewhere for this stuff soon. its off topic for here & not wanting to annoy or derail anything else.
but progress. back to the reflect stuff & lets see if I can hook something in.
I just learnt wasm address space is 32 bit. not a problem for now. cool. getting there :)
ahhh ... that's better. small test, small output where I can see what's going on :)
love how the format has a list of function signatures & each entry only references that sig id.
nice :)
going super slow as exhausted.
Now do clang without stdlibs :) clang --target=wasm32 -nostdlib -Wl,--no-entry,--export=foobar ..
Going to take it all the way Rust unless I find a good reason not to. Can come back to C++ later. Needed a reason to learn it, think I've got one :)
Shame we can't do c# without all the junk yet, maybe that'll come at some point. Managed heap has its place in high level stuff & the syntax is pretty sweet.
I know mono can target wasm getting c# thru, but it brings with it a ton of .net baggage we don't need. I like things minimalist.
not understanding why the wat for that rust test is tiny (expected) but the wasm is huge.
utils.wat - 525 bytes
utils.wasm - 1773461 bytes
that's an issue we can no doubt resolve but not a production stop issue.
the following is however a production stop issue.
utils .wasm crashes wasm_instance_new in the refect example.
my hunch is coz there's an unresolved extern (deliberate). that's the entire point of loading this way is to scan for it so we can patch it up.
I need to be able to do a reflection scan or whatever the terminology is with a gap as the point is to find the gaps so we can fill them :)
anything unresolved after our expected gaps are found & patched is an error, but that'd be up to us to fail on or otherwise.
to reproduce, the rust source is in the pastebin immediately above, compile standard rust as per the tutorial I'm working from above.
load into reflect.c with s/export/import.
fopen "rb" so the load doesn't mess up :)
modified reflect.c here to save everyone a job : https://pastebin.com/1KQQqTCv
if you guys need anything else to repro or I'm doing something idiotic, please let me know :) could be import loads need to be done a different way. I literally did a search & replace. might be more to it.
I'm running wasmtime-v0.15.0-x86_64-windows-c-api - happy to switch to upgrade if that's required to patch this up. also happy to fix it myself if it's trivial.
as an alternative, if its possible to replace exported functions, could do it that way instead.
losing it. you can load with imports that can be patched. that's what hello.c does. so it must be something specific regarding that example triggering a fault.
advance-software.com/misc/test.wasm
nope, not losing it, if a little tired. in hello.c, the missing function (the import) is passed into wasm_instance_new so everything can resolve & the file loads.
in the import reflection example we're throwing together here, the resolving function isn't available as we're scanning for imports prior to resolving them..
so its not file specific. its api misuse, an api gap or an implementation error.
happy to log over here if required, or if the info in this chat is sufficient, I can swtich to something else whilst waiting for this to resolve.
https://github.com/bytecodealliance/wasmtime/issues
anything else I need to do at this time, please let me know.
if this is tricky, maybe can figure out some way of routing everything via a single imported entrypoint for now.
summary for those not wanting to read a wall of text : wasm-c-api reflection example is exports. flipped it to imports as per suggestion here.
problem: can't reflect bcoz wasm_instance_new crashes with unresolved imports, thereby making import reflection impossible at this point. unless of course I'm doing it wrong. in any case, function shouldn't crash with essentially valid input. realise this is work in progress at the edge :)
.... but you've got a real user here. if wasmtime is up to it & license is acceptable (something bsd-ish will do), we'll go for it.
turn around in a real app is about a week once I've got a way through. single entry point as I've suggested might be a way through. I'll experiment.
at the very least, I need that function not crashing as passing a function with unresolved imports we're not expecting will be outside my control. I can dive in & try & patch that if I have to, but that'll have to wait until I have api use side up to minimum first.
given there are other implementations of the api, perhaps we have to run with one of those to start with. currently have no idea what they do with the use case explained above.
wasmtime website missing legal. we might open source our 3d web tech at some point, but that decision hasn't been made yet so I need to work with complementary technologies that allow us to open source as & where we see fit at a time of our choosing. our direct interfacing to wasmtime will be an infinity "action" plugin - we've got those for .net, mono, java, javascript and native right now. no objection to that being open source.
.... but you've got a real user here. if wasmtime is up to it & license is acceptable (something bsd-ish will do), we'll go for it.
Is Apache-2.0 WITH LLVM-exception
acceptable?
wasmtime website missing legal.
What exactly are you missing? You may find it at https://bytecodealliance.org/. This is the website of the alliance which wasmtime is part of.
Is Apache-2.0 WITH LLVM-exception acceptable?
Dunno yet, thanks for the link. Will review. At this point I've stated our intent & configuration & nobody's complained, so suspect we're good.
Thanks again, bjorn3
hate legal, but got to have all bases covered.
appears to be this thing : https://www.apache.org/licenses/LICENSE-2.0
My reading of this is that legal is sound.
Though I haven't seen the llvm excemption legal yet as I don't know where that is.
suspect we're good. the intent there is to be permissive which is what I'm looking for, so pretty much bsd.
ahhh, here :)
prefer BSD as these things get complicated for no good reason, that being why I prefer BSD - its simple, but lets stay technical here unless there's a good reason to dive into legal. I don't have one. that'll do. thanks, all. wanting to contribute back too, have already done so in terms of one bugfix (sample code fopen mode) & trialing this tech first in a real world application. we continue ...
lets keep focus here to get to something production ready.
wasm_instance_new crashes with unresolved imports. can't have it crashing. reject with error code is minimal fix to get inside solution space.
The last argument of wasm_instance_new
is a pointer to write a pointer to a wasm_trap_t
to. Did you pass a null pointer for it? If so, I think you will need to pass it a pointer to a variable to store the pointer in. You can initialize the variable itself to a null pointer though.
wasm_trap_t *err = NULL;
wasm_instance_new(..., &err);
if (err) {
// handle error
}
ahhhh, is that what it is :)
you rock, again :)
/passes a virtual beer.
will give it a shot, cheers.
nope, doesn't fix it. nice try :) still crashes. if it was that, function should fail passing a null back.
Do you have a backtrace?
how is this even working anyway. going to show my ignorance here.
from hello.c
const wasm_extern_t* imports[] = { wasm_func_as_extern(test_func) };
own wasm_instance_t* instance = wasm_instance_new( store, module, imports, &err);
so ... imports is wasm_extern_t** - how do you know how long the array is ?
I'd have minimum null terminated, so this :
const wasm_extern_t* imports[] = { wasm_func_as_extern(test_func), nullptr };
is there some trick to get the array length I don't know about ?
Looks like wasm_instance_new
uses the amount of imports of the wasm module as length of that array: https://github.com/bytecodealliance/wasmtime/blob/9364eb1d98d4b82d30ce72ec1e46ee72a1ea6a0c/crates/c-api/src/instance.rs#L52
If you directly use wasmtime_instance_new
, you can explicitly pass an array length.
I think this should be either documented or preferably changed for wasm-c-api
, as it is quite dangerous. cc @Dan Gohman?
wasmtime_instance_new seems to be the way to go, thanks.
was going to dive in & fix this myself, but of course wasmtime is written in rust. I am rust noobie, I can barely throw together a 2 line test so think I should leave internals to the pros for now.
& that gets me to the wasmtime api - I have reason to be there now, thanks. will see what other goodies are there.
that I think is the crash. an implicit length from untrusted variable input is used where the code should specify explicitly what its providing as wasmtime_instance_new indeed does. so that's my next job - see if that gets us past the hurdle. cheers :)
I think minimum we need to be able to scan input wasm for how many of each time of unresolved it has & then decide whether to proceed. if malicious, corrupt or unintended wasm passes me something with 1000s of unresolved, I think I want to reject it right there.
wasmtime_instance_new isn't in the header. maybe I can patch it as it looks exported in the code. also perhaps time to move from distribution to build this myself if we're in active development bouncing off each other now.
a distribution update with that in it would be smashing if its easy enough to do. I'd rather not dive into other people's projects if at all possible as hands full where I am.
think I step back until I have a wasmtime.h with wasmtime_instance_new defined in it. if thoughts are just come grab trunk and build it, maybe I should. but I'd prefer a package update containing this as its essential & not all about me.
ahhh ... it is in truck header :)
so being impatient, I suppose I have a go at building this bad boy :)
time for a distribution update as that entrypoint is required to use wasmtime.
if current wasm-c-api specifies a nullptr terminated list for imports, you're good as its then fully specified. that it doesn't is the issue. so that's a documentation fix & implementation & sample code fix to resolve. api can stay as it is.
wall of text above not helps, can you explain how many modules you are trying to instantiate and how you fill the imports array?
1 test module for now but long term this is how webdevs pass us functionality so we could receive anything.
wasm-c-api does not do linking, so building the imports (linking) falls on embedder shoulder
how many imports is in said module and what their types?
I understand I have to provide the imports. for now, I'll go with one function uint32_t mything(uint32 class_id)
alright, basic hello_world example covers this use case
so I'm expecting that to be unresolved as we bind it, but this is where webdevs pass us code to run. they might have other stuff unresolved.
so I need to know whats unresolved to understand if its just our stuff I'm about to patch or other stuff too (a reject)
no, hello.c doesn't cover this use case. because webdevs might pass me something with the unresolved I'm expecting & perhaps a bunch of others too.
such files should be rejects, but I have no idea what they'll pass as they're untrusted.
correct, your code suppose to use wasm_module_imports to build imports for wasm_instance_new
the same order
basically you are doing linking
hang on ... light bulb moment :)
sample code has wasm_module_imports after wasmtime_instance_new but there's no reason for it to be that way around.
which sample code?
there is no sample code for wasm_module_imports, so you have to improvise and guess that the imports array is populated based on module metadata
I'm hybrid munged reflect.c and hello.c at this point.
so yeah, I can perform a wasm_module_imports prior to instantiating anything. and that's part of a sanity check.
or maybe it is my santity check. with the minimal example we're running here, I expect 1 import. anything else is fail at that point.
in wasmtime, we tried to map c-api to rust, maybe documentation in the rust API will help more, see e.g. https://docs.rs/wasmtime/0.16.0/wasmtime/struct.Instance.html#providing-imports
thanks. /0.16.0/ would help - I'm on 0.15.0 & 0.16.0 has wasmtime_instance_new which I still might need :)
Instance::new was there from old versions
wasmtime_instance_new is not directly related to Instance::new, wasm_instance_new is
actually now they are
this might work. I've still got a crash, but after what I think I need. let me figure out what's going bang now.
to answer what sample code - the import reflection example we're working on that I'm happy to pass back.
maybe worth to sending it to wasm-c-api?
happy to send it where you want. let me clean it up first. this works, thanks so much :)
output :
Initializing...
Loading binary...
Compiling module...
Extracting imports...
Instantiating module...
import 0 "create_native"
func i32 -> i32
Shutting down...
do extracting imports before "Instantiate module.." also, the module field needs to be shown
doh. so simple. now we know what we have we can reject anything that's not as expected before it has the chance to go bang, so its safe.
let me grab some more caffeine, tidy that up (its minimal) then you can check I'm doing things correctly direct if you'd like. seems good.
right, there is a sensitive topic about what safe and what is not at https://github.com/WebAssembly/wasm-c-api/issues/132
summary: all good. noob stupid moment :)
I've got this for imports.c
concern - as I'm literally getting my head around this as we go - is the thing that's giving me how many of these things there are the number of unique function signatures or the number of unique functions. I'll put together another test wasm file so I know.
perfect. gets the number of unique functions. output from test doing exactly that as follows.
Initializing...
Loading binary...
Compiling module...
Extracting imports...
import 0 "create_native" func i32 -> i32
import 1 "release_native" func i32 -> i32
Shutting down...
so imports.c above with whatever test wasm anyone wants - it should be able to safely load anything ready to roll.
and I've got what I need to continue in a safe & robust way. thanks all. back on track. apologies for offroading into fail :)
that new sample should stop it happening again.
might make sense to delete this thread. its quite verbose & don't want to waste people's time on stuff that isn't needed.
it boils down to see imports.c example code, which I've provided & happy to submit somewhere if desired.
thanks for the clang command line, yury. took rust for a spin. I hate it, so implementing our bootstrap in wasm/c++ .
got the basics running.
rust is awful. full of things done differently for no good reason. yuk.
if others want to use it, fine, I won't be one of them :)
this isn't a rust group so perhaps shouldn't have even said that & realise you guys like it.
you're insane :)
... and yes, I know wasmtime is written in rust. not trying to cause offence, its just not for me. we've got solid interfacing so we can all use the language of our choice. we don't all have to choose the same one. that being the elegance of the setup. we continue ... all good :)
Just saying you don't want to cause offense doesn't really work if it follows inflammatory language like in this case. Please tone it down.
sure, sorry. point was to thank yury for pointing me in the right direction.
simple stuff like :
let mut x : int32;
that doesn't make sense. what's wrong with var if you must have a reserved word ?
x : int32;
would be sufficient. its implicit you're declaring.
the language offends me, hence the tone.
c-like has many advantages.
so I tried to macro "let mut" to var & couldn't.
at that point I decided the language doesn't let me do what I want.
but anyhow, as stated, this isn't a rust group. just explaining why I'm pivoting back to my happy place. it has no tangible effect on our or your deliverables.
debug interface upgrade is where the focus should be here. I think, anyway. we can argue about rust syntax other places.
also, from c++ I can bash wasm & wasmtime runtime hard to see if your security model stands up. so this is all good.
Last updated: Dec 23 2024 at 12:05 UTC