-
Notifications
You must be signed in to change notification settings - Fork 70
Argc/Argv support for SGX #605
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
Conversation
142bff0 to
7079b23
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good, but I'm concerned that this approach will lead to having two versions of a lot WAMR-related logic. I think a mixin shared between EnclaveWasmModule and WAMRWasmModule makes sense (e.g. WAMRModuleMixin or WAMRModuleCommon or something)
include/enclave/inside/native.h
Outdated
| // | ||
| // Link to WAMR docs: | ||
| // https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md#buffer-address-conversion-and-boundary-check | ||
| // ---------------------------------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a lot like the comment in https://github.com/faasm/faasm/blob/main/include/wamr/native.h, and feels like it's just repeating what's in the WAMR docs. Is it necessary and can we somehow avoid having this information in two places?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added the new relevant bits to the file you link, and removed this duplicated comment and added a reference to where it is explained.
| // In enclave release mode (i.e NDEBUG set) we disable debug logging | ||
| #ifdef NDEBUG | ||
| void ocallLogDebug(const char* msg) { ; }; | ||
| #else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come this has a different method signature to the declaration in debug mode? Shouldn't they be the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both methods need to have different return values to prevent the RELEASE version from doing any kind of OCall. Whereas the second signature is that corresponding to an OCall.
| uint32_t faaslet_id); | ||
| uint32_t faaslet_id, | ||
| uint32_t argc, | ||
| char** argv); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still some kebab_case in this file, would be good to refactor to PascalCase in future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do in the immediately subsequent PR.
| } | ||
| } | ||
|
|
||
| void EnclaveWasmModule::prepareArgcArgv(uint32_t argcIn, char** argvIn) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same point re. duplication with WARMWasmModule and mixin. We need to find a way to avoid duplicating these functions otherwise we'll end up with two copies of everything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, this call in particular can not be abstracted out, as WAMR's (non-SGX) version is implemented in WasmModule and uses calls to faabric.
In addition, the method signature is different:
void EnclaveWasmModule::prepareArgcArgv(uint32_t argcIn, char** argvIn);
void WAMRWasmModule::prepareArgcArgv(const faabric::Message& msg);There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok I see, it's slightly confusing to have the same name and have it factored out as a separate function then, especially as it's only called in one place. I'd probably just inline the logic in the callFunction method.
| GET_EXECUTING_MODULE_AND_CHECK(exec_env); | ||
|
|
||
| *argcWasm = module->getArgc(); | ||
| *argvBuffSizeWasm = module->getArgvBufferSize(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very similar to
Line 26 in bcdbf54
| uint32_t wasi_args_sizes_get(wasm_exec_env_t exec_env, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think native symbols aren't such good candidates to be included in a mixin. The native symbol registration doesn't work well with templated functions, and there are some methods (like logging and getting the executing module) that have different names and signatures.
That being said, after the new mixin structure the methods body is either trivial or implemented in the WAMRModuleMixin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mean we should merge the whole native symbol thing in, just the logic of the body of the function. This is how we share host interface logic between WAVM and WAMR normally, e.g. having a method like module->setUpArgcArgv(argcWasm, argvBuffSizeWasm) rather individual calls to getArgc and getArgvBufferSize. Admittedly here it will only save a couple of lines, but it's more the principle of absolutely minimising duplication.
…ution environment
|
|
||
| // ---- argc/arv ---- | ||
|
|
||
| uint32_t getArgc(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getters I need to implement in the actual modules, as the mixin does not have access to private members.
| @@ -0,0 +1,66 @@ | |||
| #pragma once | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Shillaker this is the header file where are define the mixin (I plan on adding more calls currently in WAMRWasmModule as I need to implement them as well in EnclaveWasmModule).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok nice, great that we can share this stuff more now.
I just wanted to check, do you think we could actually do this via an intermediate superclass? I.e. have the following hierarchy:
WasmModule
|
WAMRModuleCommon
| |
WAMRWasmModule EnclaveWasmModule
We could then move the common properties between WAMRWasmModule and EnclaveWasmModule, like argc and argvBufferSize into WAMRModuleCommon and avoid the need for the stuff with underlying. We could also then potentially share methods like loadWasm.
I have a feeling we discussed this before, but can't remember why we couldn't do a superclass.
(Happy to continue discussion on Slack if easier)
| } | ||
| } | ||
|
|
||
| void EnclaveWasmModule::prepareArgcArgv(uint32_t argcIn, char** argvIn) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok I see, it's slightly confusing to have the same name and have it factored out as a separate function then, especially as it's only called in one place. I'd probably just inline the logic in the callFunction method.
| GET_EXECUTING_MODULE_AND_CHECK(exec_env); | ||
|
|
||
| *argcWasm = module->getArgc(); | ||
| *argvBuffSizeWasm = module->getArgvBufferSize(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mean we should merge the whole native symbol thing in, just the logic of the body of the function. This is how we share host interface logic between WAVM and WAMR normally, e.g. having a method like module->setUpArgcArgv(argcWasm, argvBuffSizeWasm) rather individual calls to getArgc and getArgvBufferSize. Admittedly here it will only save a couple of lines, but it's more the principle of absolutely minimising duplication.
| @@ -0,0 +1,66 @@ | |||
| #pragma once | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok nice, great that we can share this stuff more now.
I just wanted to check, do you think we could actually do this via an intermediate superclass? I.e. have the following hierarchy:
WasmModule
|
WAMRModuleCommon
| |
WAMRWasmModule EnclaveWasmModule
We could then move the common properties between WAMRWasmModule and EnclaveWasmModule, like argc and argvBufferSize into WAMRModuleCommon and avoid the need for the stuff with underlying. We could also then potentially share methods like loadWasm.
I have a feeling we discussed this before, but can't remember why we couldn't do a superclass.
(Happy to continue discussion on Slack if easier)
| #include <vector> | ||
|
|
||
| template<typename T> | ||
| struct WAMRModuleMixin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be a class? It gives us more flexibility around scoping the members.
|
After our offline discussion I have added a comment in the mixin header file, explaining our design choices. |
In this PR I implement the WASI calls to access
argcandargvinside SGX:wasi_args_getandwasi_args_sizes_get. The immediate consequence is that now the test function:demo/argc_argv_testalso runs on SGX.The bulk of the implementation is almost copied from WAMR's (
src/wamr/env.cpp), and requires no OCalls. The only major change to the OCall/ECall interface is that we now passargcandargvto theecallCallFunctioncall. Note that the OCall/ECall interface forces us to serialiseargvinto a byte array, which means some more work.In addition, I re-factor the utility functions to run SGX tests to match the WAVM and WAMR counterparts: now we have
execFunction,execWamrFunction,execSgxFunction, andexecFuncWithPool,execFuncWithWamrPool, andexecFuncWithSgxPool.