Skip to content

Use native types when calling host functions #494

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@ fn main() -> hyperlight_host::Result<()> {
let message = "Hello, World! I am executing inside of a VM :)\n".to_string();
// in order to call a function it first must be defined in the guest and exposed so that
// the host can call it
let result = multi_use_sandbox.call_guest_function_by_name(
let result: i32 = multi_use_sandbox.call_guest_function_by_name(
"PrintOutput",
ReturnType::Int,
Some(vec![ParameterValue::String(message.clone())]),
(message),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does message need to be in parens?

);

assert!(result.is_ok());
Expand Down
4 changes: 2 additions & 2 deletions fuzz/fuzz_targets/guest_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ fuzz_target!(
SANDBOX.set(Mutex::new(mu_sbox)).unwrap();
},

|data: (ReturnType, Option<Vec<ParameterValue>>)| {
|data: (ReturnType, Vec<ParameterValue>)| {
let mut sandbox = SANDBOX.get().unwrap().lock().unwrap();
let _ = sandbox.call_guest_function_by_name("PrintOutput", data.0, data.1);
let _ = sandbox.call_type_erased_guest_function_by_name("PrintOutput", data.0, data.1);
}
);
2 changes: 1 addition & 1 deletion fuzz/fuzz_targets/host_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fuzz_target!(
let (host_func_name, host_func_return, mut host_func_params) = data;
let mut sandbox = SANDBOX.get().unwrap().lock().unwrap();
host_func_params.insert(0, ParameterValue::String(host_func_name));
match sandbox.call_guest_function_by_name("FuzzHostFunc", host_func_return, Some(host_func_params)) {
match sandbox.call_type_erased_guest_function_by_name("FuzzHostFunc", host_func_return, host_func_params) {
Err(HyperlightError::GuestAborted(_, message)) if !message.contains("Host Function Not Found") => {
// We don't allow GuestAborted errors, except for the "Host Function Not Found" case
panic!("Guest Aborted: {}", message);
Expand Down
21 changes: 6 additions & 15 deletions fuzz/fuzz_targets/host_print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use std::sync::{Mutex, OnceLock};

use hyperlight_host::func::{ParameterValue, ReturnType, ReturnValue};
use hyperlight_host::sandbox::uninitialized::GuestBinary;
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
use hyperlight_host::sandbox_state::transition::Noop;
Expand All @@ -28,22 +27,14 @@ fuzz_target!(
SANDBOX.set(Mutex::new(mu_sbox)).unwrap();
},

|data: ParameterValue| -> Corpus {
// only interested in String types
if !matches!(data, ParameterValue::String(_)) {
return Corpus::Reject;
}

|data: String| -> Corpus {
let mut sandbox = SANDBOX.get().unwrap().lock().unwrap();
let res = sandbox.call_guest_function_by_name(
let len: i32 = sandbox.call_guest_function_by_name::<i32>(
"PrintOutput",
ReturnType::Int,
Some(vec![data.clone()]),
);
match res {
Ok(ReturnValue::Int(len)) => assert!(len >= 0),
_ => panic!("Unexpected return value: {:?}", res),
}
data,
)
.expect("Unexpected return value");
assert!(len >= 0);

Corpus::Keep
});
31 changes: 5 additions & 26 deletions src/hyperlight_host/benches/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
use std::time::Duration;

use criterion::{criterion_group, criterion_main, Criterion};
use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
use hyperlight_host::sandbox::{MultiUseSandbox, SandboxConfiguration, UninitializedSandbox};
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
use hyperlight_host::sandbox_state::transition::Noop;
Expand All @@ -43,11 +42,7 @@ fn guest_call_benchmark(c: &mut Criterion) {

b.iter(|| {
call_ctx
.call(
"Echo",
ReturnType::Int,
Some(vec![ParameterValue::String("hello\n".to_string())]),
)
.call::<String>("Echo", "hello\n".to_string())
.unwrap()
});
});
Expand All @@ -59,11 +54,7 @@ fn guest_call_benchmark(c: &mut Criterion) {

b.iter(|| {
sandbox
.call_guest_function_by_name(
"Echo",
ReturnType::Int,
Some(vec![ParameterValue::String("hello\n".to_string())]),
)
.call_guest_function_by_name::<String>("Echo", "hello\n".to_string())
.unwrap()
});
});
Expand All @@ -88,13 +79,9 @@ fn guest_call_benchmark(c: &mut Criterion) {

b.iter(|| {
sandbox
.call_guest_function_by_name(
.call_guest_function_by_name::<()>(
"LargeParameters",
ReturnType::Void,
Some(vec![
ParameterValue::VecBytes(large_vec.clone()),
ParameterValue::String(large_string.clone()),
]),
(large_vec.clone(), large_string.clone()),
)
.unwrap()
});
Expand All @@ -114,15 +101,7 @@ fn guest_call_benchmark(c: &mut Criterion) {
uninitialized_sandbox.evolve(Noop::default()).unwrap();
let mut call_ctx = multiuse_sandbox.new_call_context();

b.iter(|| {
call_ctx
.call(
"Add",
ReturnType::Int,
Some(vec![ParameterValue::Int(1), ParameterValue::Int(41)]),
)
.unwrap()
});
b.iter(|| call_ctx.call::<i32>("Add", (1_i32, 41_i32)).unwrap());
});

group.finish();
Expand Down
32 changes: 6 additions & 26 deletions src/hyperlight_host/examples/func_ctx/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
use hyperlight_host::func::call_ctx::MultiUseGuestCallContext;
use hyperlight_host::sandbox::{MultiUseSandbox, UninitializedSandbox};
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
use hyperlight_host::sandbox_state::transition::Noop;
use hyperlight_host::{new_error, GuestBinary, Result};
use hyperlight_host::{GuestBinary, Result};
use hyperlight_testing::simple_guest_as_string;

fn main() {
Expand Down Expand Up @@ -47,29 +46,10 @@ fn main() {
/// call `ctx.finish()` and return the resulting `MultiUseSandbox`. Return an `Err`
/// if anything failed.
fn do_calls(mut ctx: MultiUseGuestCallContext) -> Result<MultiUseSandbox> {
{
let res1: String = {
let rv = ctx.call(
"Echo",
ReturnType::Int,
Some(vec![ParameterValue::String("hello".to_string())]),
)?;
rv.try_into()
}
.map_err(|e| new_error!("failed to get Echo result: {}", e))?;
println!("got Echo res: {res1}");
}
{
let res2: i32 = {
let rv = ctx.call(
"CallMalloc",
ReturnType::Int,
Some(vec![ParameterValue::Int(200)]),
)?;
rv.try_into()
}
.map_err(|e| new_error!("failed to get CallMalloc result: {}", e))?;
println!("got CallMalloc res: {res2}");
}
let res: String = ctx.call("Echo", "hello".to_string())?;
println!("got Echo res: {res}");

let res: i32 = ctx.call("CallMalloc", 200_i32)?;
println!("got CallMalloc res: {res}");
ctx.finish()
}
14 changes: 6 additions & 8 deletions src/hyperlight_host/examples/guest-debugging/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ limitations under the License.
#![allow(clippy::disallowed_macros)]
use std::thread;

use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
#[cfg(gdb)]
use hyperlight_host::sandbox::config::DebugInfo;
use hyperlight_host::sandbox::SandboxConfiguration;
Expand Down Expand Up @@ -62,13 +61,12 @@ fn main() -> hyperlight_host::Result<()> {

// Call guest function
let message = "Hello, World! I am executing inside of a VM :)\n".to_string();
let result = multi_use_sandbox.call_guest_function_by_name(
"PrintOutput", // function must be defined in the guest binary
ReturnType::Int,
Some(vec![ParameterValue::String(message.clone())]),
);

assert!(result.is_ok());
multi_use_sandbox
.call_guest_function_by_name::<i32>(
"PrintOutput", // function must be defined in the guest binary
message.clone(),
)
.unwrap();

Ok(())
}
Expand Down
14 changes: 6 additions & 8 deletions src/hyperlight_host/examples/hello-world/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ limitations under the License.
#![allow(clippy::disallowed_macros)]
use std::thread;

use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
use hyperlight_host::sandbox_state::transition::Noop;
use hyperlight_host::{MultiUseSandbox, UninitializedSandbox};
Expand All @@ -42,13 +41,12 @@ fn main() -> hyperlight_host::Result<()> {

// Call guest function
let message = "Hello, World! I am executing inside of a VM :)\n".to_string();
let result = multi_use_sandbox.call_guest_function_by_name(
"PrintOutput", // function must be defined in the guest binary
ReturnType::Int,
Some(vec![ParameterValue::String(message.clone())]),
);

assert!(result.is_ok());
multi_use_sandbox
.call_guest_function_by_name::<i32>(
"PrintOutput", // function must be defined in the guest binary
message,
)
.unwrap();

Ok(())
}
25 changes: 8 additions & 17 deletions src/hyperlight_host/examples/logging/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ limitations under the License.
#![allow(clippy::disallowed_macros)]
extern crate hyperlight_host;

use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
use hyperlight_host::sandbox::uninitialized::UninitializedSandbox;
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
use hyperlight_host::sandbox_state::transition::Noop;
Expand Down Expand Up @@ -53,12 +52,9 @@ fn main() -> Result<()> {

// Call a guest function 5 times to generate some log entries.
for _ in 0..5 {
let result = multiuse_sandbox.call_guest_function_by_name(
"Echo",
ReturnType::String,
Some(vec![ParameterValue::String("a".to_string())]),
);
result.unwrap();
multiuse_sandbox
.call_guest_function_by_name::<String>("Echo", "a".to_string())
.unwrap();
}

// Define a message to send to the guest.
Expand All @@ -67,12 +63,9 @@ fn main() -> Result<()> {

// Call a guest function that calls the HostPrint host function 5 times to generate some log entries.
for _ in 0..5 {
let result = multiuse_sandbox.call_guest_function_by_name(
"PrintOutput",
ReturnType::Int,
Some(vec![ParameterValue::String(msg.clone())]),
);
result.unwrap();
multiuse_sandbox
.call_guest_function_by_name::<i32>("PrintOutput", msg.clone())
.unwrap();
}
Ok(())
};
Expand All @@ -95,10 +88,8 @@ fn main() -> Result<()> {
for _ in 0..5 {
let mut ctx = multiuse_sandbox.new_call_context();

let result = ctx.call("Spin", ReturnType::Void, None);
assert!(result.is_err());
let result = ctx.finish();
multiuse_sandbox = result.unwrap();
ctx.call::<()>("Spin", ()).unwrap_err();
multiuse_sandbox = ctx.finish().unwrap();
}

Ok(())
Expand Down
26 changes: 8 additions & 18 deletions src/hyperlight_host/examples/metrics/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
extern crate hyperlight_host;
use std::thread::{spawn, JoinHandle};

use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
use hyperlight_host::sandbox::uninitialized::UninitializedSandbox;
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
use hyperlight_host::sandbox_state::transition::Noop;
Expand Down Expand Up @@ -65,12 +64,9 @@ fn do_hyperlight_stuff() {

// Call a guest function 5 times to generate some metrics.
for _ in 0..5 {
let result = multiuse_sandbox.call_guest_function_by_name(
"Echo",
ReturnType::String,
Some(vec![ParameterValue::String("a".to_string())]),
);
assert!(result.is_ok());
multiuse_sandbox
.call_guest_function_by_name::<String>("Echo", "a".to_string())
.unwrap();
}

// Define a message to send to the guest.
Expand All @@ -79,12 +75,9 @@ fn do_hyperlight_stuff() {

// Call a guest function that calls the HostPrint host function 5 times to generate some metrics.
for _ in 0..5 {
let result = multiuse_sandbox.call_guest_function_by_name(
"PrintOutput",
ReturnType::Int,
Some(vec![ParameterValue::String(msg.clone())]),
);
assert!(result.is_ok());
multiuse_sandbox
.call_guest_function_by_name::<i32>("PrintOutput", msg.clone())
.unwrap();
}
Ok(())
});
Expand All @@ -108,11 +101,8 @@ fn do_hyperlight_stuff() {
for _ in 0..5 {
let mut ctx = multiuse_sandbox.new_call_context();

let result = ctx.call("Spin", ReturnType::Void, None);
assert!(result.is_err());
let result = ctx.finish();
assert!(result.is_ok());
multiuse_sandbox = result.unwrap();
ctx.call::<()>("Spin", ()).unwrap_err();
multiuse_sandbox = ctx.finish().unwrap();
}

for join_handle in join_handles {
Expand Down
9 changes: 2 additions & 7 deletions src/hyperlight_host/examples/tracing-chrome/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
#![allow(clippy::disallowed_macros)]
use hyperlight_host::func::{ParameterValue, ReturnType, ReturnValue};
use hyperlight_host::sandbox::uninitialized::UninitializedSandbox;
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
use hyperlight_host::sandbox_state::transition::Noop;
Expand All @@ -41,13 +40,9 @@ fn main() -> Result<()> {

// do the function call
let current_time = std::time::Instant::now();
let res = sbox.call_guest_function_by_name(
"Echo",
ReturnType::String,
Some(vec![ParameterValue::String("Hello, World!".to_string())]),
)?;
let res: String = sbox.call_guest_function_by_name("Echo", "Hello, World!".to_string())?;
let elapsed = current_time.elapsed();
println!("Function call finished in {:?}.", elapsed);
assert!(matches!(res, ReturnValue::String(s) if s == "Hello, World!"));
assert_eq!(res, "Hello, World!");
Ok(())
}
Loading