diff --git a/src/hyperlight_common/src/flatbuffer_wrappers/host_function_definition.rs b/src/hyperlight_common/src/flatbuffer_wrappers/host_function_definition.rs new file mode 100644 index 000000000..edd447f4d --- /dev/null +++ b/src/hyperlight_common/src/flatbuffer_wrappers/host_function_definition.rs @@ -0,0 +1,160 @@ +/* +Copyright 2025 The Hyperlight Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +use anyhow::{Error, Result, anyhow}; +use flatbuffers::{FlatBufferBuilder, WIPOffset}; +#[cfg(feature = "tracing")] +use tracing::{Span, instrument}; + +use super::function_types::{ParameterType, ReturnType}; +use crate::flatbuffers::hyperlight::generated::{ + HostFunctionDefinition as FbHostFunctionDefinition, + HostFunctionDefinitionArgs as FbHostFunctionDefinitionArgs, ParameterType as FbParameterType, +}; + +/// The definition of a function exposed from the host to the guest +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct HostFunctionDefinition { + /// The function name + pub function_name: String, + /// The type of the parameter values for the host function call. + pub parameter_types: Option>, + /// The type of the return value from the host function call + pub return_type: ReturnType, +} + +impl HostFunctionDefinition { + /// Create a new `HostFunctionDefinition`. + #[cfg_attr(feature = "tracing", instrument(skip_all, parent = Span::current(), level= "Trace"))] + pub fn new( + function_name: String, + parameter_types: Option>, + return_type: ReturnType, + ) -> Self { + Self { + function_name, + parameter_types, + return_type, + } + } + + /// Convert this `HostFunctionDefinition` into a `WIPOffset`. + #[cfg_attr(feature = "tracing", instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace"))] + pub(crate) fn convert_to_flatbuffer_def<'a>( + &self, + builder: &mut FlatBufferBuilder<'a>, + ) -> Result>> { + let host_function_name = builder.create_string(&self.function_name); + let return_value_type = self.return_type.into(); + let vec_parameters = match &self.parameter_types { + Some(vec_pvt) => { + let num_items = vec_pvt.len(); + let mut parameters: Vec = Vec::with_capacity(num_items); + for pvt in vec_pvt { + let fb_pvt = pvt.clone().into(); + parameters.push(fb_pvt); + } + Some(builder.create_vector(¶meters)) + } + None => None, + }; + + let fb_host_function_definition: WIPOffset = + FbHostFunctionDefinition::create( + builder, + &FbHostFunctionDefinitionArgs { + function_name: Some(host_function_name), + return_type: return_value_type, + parameters: vec_parameters, + }, + ); + + Ok(fb_host_function_definition) + } + + /// Verify that the function call has the correct parameter types. + #[cfg_attr(feature = "tracing", instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace"))] + pub fn verify_equal_parameter_types( + &self, + function_call_parameter_types: &[ParameterType], + ) -> Result<()> { + if let Some(parameter_types) = &self.parameter_types { + for (i, parameter_type) in parameter_types.iter().enumerate() { + if parameter_type != &function_call_parameter_types[i] { + return Err(anyhow!("Incorrect parameter type for parameter {}", i + 1)); + } + } + } + Ok(()) + } +} + +impl TryFrom<&FbHostFunctionDefinition<'_>> for HostFunctionDefinition { + type Error = Error; + #[cfg_attr(feature = "tracing", instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace"))] + fn try_from(value: &FbHostFunctionDefinition) -> Result { + let function_name = value.function_name().to_string(); + let return_type = value.return_type().try_into().map_err(|_| { + anyhow!( + "Failed to convert return type for function {}", + function_name + ) + })?; + let parameter_types = match value.parameters() { + Some(pvt) => { + let len = pvt.len(); + let mut pv: Vec = Vec::with_capacity(len); + for fb_pvt in pvt { + let pvt: ParameterType = fb_pvt.try_into().map_err(|_| { + anyhow!( + "Failed to convert parameter type for function {}", + function_name + ) + })?; + pv.push(pvt); + } + Some(pv) + } + None => None, + }; + + Ok(Self::new(function_name, parameter_types, return_type)) + } +} + +impl TryFrom<&[u8]> for HostFunctionDefinition { + type Error = Error; + #[cfg_attr(feature = "tracing", instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace"))] + fn try_from(value: &[u8]) -> Result { + let fb_host_function_definition = flatbuffers::root::>(value) + .map_err(|e| anyhow!("Error while reading HostFunctionDefinition: {:?}", e))?; + Self::try_from(&fb_host_function_definition) + } +} + +impl TryFrom<&HostFunctionDefinition> for Vec { + type Error = Error; + #[cfg_attr(feature = "tracing", instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace"))] + fn try_from(hfd: &HostFunctionDefinition) -> Result> { + let mut builder = flatbuffers::FlatBufferBuilder::new(); + let host_function_definition = hfd.convert_to_flatbuffer_def(&mut builder)?; + builder.finish_size_prefixed(host_function_definition, None); + Ok(builder.finished_data().to_vec()) + } +} diff --git a/src/hyperlight_common/src/flatbuffer_wrappers/host_function_details.rs b/src/hyperlight_common/src/flatbuffer_wrappers/host_function_details.rs new file mode 100644 index 000000000..2c18a584b --- /dev/null +++ b/src/hyperlight_common/src/flatbuffer_wrappers/host_function_details.rs @@ -0,0 +1,102 @@ +/* +Copyright 2025 The Hyperlight Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +use alloc::vec::Vec; + +use anyhow::{Error, Result}; +use flatbuffers::{WIPOffset, size_prefixed_root}; +#[cfg(feature = "tracing")] +use tracing::{Span, instrument}; + +use super::host_function_definition::HostFunctionDefinition; +use crate::flatbuffers::hyperlight::generated::{ + HostFunctionDefinition as FbHostFunctionDefinition, + HostFunctionDetails as FbHostFunctionDetails, + HostFunctionDetailsArgs as FbHostFunctionDetailsArgs, +}; + +/// `HostFunctionDetails` represents the set of functions that the host exposes to the guest. +#[derive(Debug, Default, Clone)] +pub struct HostFunctionDetails { + /// The host functions. + pub host_functions: Option>, +} + +impl TryFrom<&[u8]> for HostFunctionDetails { + type Error = Error; + #[cfg_attr(feature = "tracing", instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace"))] + fn try_from(value: &[u8]) -> Result { + let host_function_details_fb = size_prefixed_root::(value) + .map_err(|e| anyhow::anyhow!("Error while reading HostFunctionDetails: {:?}", e))?; + + let host_function_definitions = match host_function_details_fb.functions() { + Some(hfd) => { + let len = hfd.len(); + let mut vec_hfd: Vec = Vec::with_capacity(len); + for i in 0..len { + let fb_host_function_definition = hfd.get(i); + let hfdef = HostFunctionDefinition::try_from(&fb_host_function_definition)?; + vec_hfd.push(hfdef); + } + + Some(vec_hfd) + } + + None => None, + }; + + Ok(Self { + host_functions: host_function_definitions, + }) + } +} + +impl TryFrom<&HostFunctionDetails> for Vec { + type Error = Error; + #[cfg_attr(feature = "tracing", instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace"))] + fn try_from(value: &HostFunctionDetails) -> Result> { + let mut builder = flatbuffers::FlatBufferBuilder::new(); + let vec_host_function_definitions = match &value.host_functions { + Some(vec_hfd) => { + let num_items = vec_hfd.len(); + let mut host_function_definitions: Vec> = + Vec::with_capacity(num_items); + + for hfd in vec_hfd { + let host_function_definition = hfd.convert_to_flatbuffer_def(&mut builder)?; + host_function_definitions.push(host_function_definition); + } + + Some(host_function_definitions) + } + None => None, + }; + + let fb_host_function_definitions = + vec_host_function_definitions.map(|v| builder.create_vector(&v)); + + let host_function_details = FbHostFunctionDetails::create( + &mut builder, + &FbHostFunctionDetailsArgs { + functions: fb_host_function_definitions, + }, + ); + builder.finish_size_prefixed(host_function_details, None); + let res = builder.finished_data().to_vec(); + + Ok(res) + } +} diff --git a/src/hyperlight_common/src/flatbuffer_wrappers/mod.rs b/src/hyperlight_common/src/flatbuffer_wrappers/mod.rs index 424ade97d..5e6edcf8c 100644 --- a/src/hyperlight_common/src/flatbuffer_wrappers/mod.rs +++ b/src/hyperlight_common/src/flatbuffer_wrappers/mod.rs @@ -21,4 +21,8 @@ pub mod guest_error; pub mod guest_log_data; /// cbindgen:ignore pub mod guest_log_level; +/// cbindgen:ignore +pub mod host_function_definition; +/// cbindgen:ignore +pub mod host_function_details; pub mod util; diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/error_code_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/error_code_generated.rs index 7190bf56e..dba1ed055 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/error_code_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/error_code_generated.rs @@ -124,10 +124,8 @@ impl<'a> flatbuffers::Follow<'a> for ErrorCode { type Inner = Self; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - let b = flatbuffers::read_scalar_at::(buf, loc); - Self(b) - } + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) } } @@ -135,9 +133,7 @@ impl flatbuffers::Push for ErrorCode { type Output = ErrorCode; #[inline] unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { - unsafe { - flatbuffers::emplace_scalar::(dst, self.0); - } + flatbuffers::emplace_scalar::(dst, self.0); } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_generated.rs index b02b0cc3e..17d31fa9f 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for FunctionCall<'a> { type Inner = FunctionCall<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } @@ -292,14 +290,14 @@ pub fn size_prefixed_root_as_function_call_with_opts<'b, 'o>( /// # Safety /// Callers must trust the given bytes do indeed contain a valid `FunctionCall`. pub unsafe fn root_as_function_call_unchecked(buf: &[u8]) -> FunctionCall { - unsafe { flatbuffers::root_unchecked::(buf) } + flatbuffers::root_unchecked::(buf) } #[inline] /// Assumes, without verification, that a buffer of bytes contains a size prefixed FunctionCall and returns it. /// # Safety /// Callers must trust the given bytes do indeed contain a valid size prefixed `FunctionCall`. pub unsafe fn size_prefixed_root_as_function_call_unchecked(buf: &[u8]) -> FunctionCall { - unsafe { flatbuffers::size_prefixed_root_unchecked::(buf) } + flatbuffers::size_prefixed_root_unchecked::(buf) } #[inline] pub fn finish_function_call_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_result_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_result_generated.rs index 42393b377..8ff674e6c 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_result_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_result_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for FunctionCallResult<'a> { type Inner = FunctionCallResult<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } @@ -515,7 +513,7 @@ pub fn size_prefixed_root_as_function_call_result_with_opts<'b, 'o>( /// # Safety /// Callers must trust the given bytes do indeed contain a valid `FunctionCallResult`. pub unsafe fn root_as_function_call_result_unchecked(buf: &[u8]) -> FunctionCallResult { - unsafe { flatbuffers::root_unchecked::(buf) } + flatbuffers::root_unchecked::(buf) } #[inline] /// Assumes, without verification, that a buffer of bytes contains a size prefixed FunctionCallResult and returns it. @@ -524,7 +522,7 @@ pub unsafe fn root_as_function_call_result_unchecked(buf: &[u8]) -> FunctionCall pub unsafe fn size_prefixed_root_as_function_call_result_unchecked( buf: &[u8], ) -> FunctionCallResult { - unsafe { flatbuffers::size_prefixed_root_unchecked::(buf) } + flatbuffers::size_prefixed_root_unchecked::(buf) } #[inline] pub fn finish_function_call_result_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_type_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_type_generated.rs index abd07b6b8..67edacdf9 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_type_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/function_call_type_generated.rs @@ -66,10 +66,8 @@ impl<'a> flatbuffers::Follow<'a> for FunctionCallType { type Inner = Self; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - let b = flatbuffers::read_scalar_at::(buf, loc); - Self(b) - } + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) } } @@ -77,9 +75,7 @@ impl flatbuffers::Push for FunctionCallType { type Output = FunctionCallType; #[inline] unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { - unsafe { - flatbuffers::emplace_scalar::(dst, self.0); - } + flatbuffers::emplace_scalar::(dst, self.0); } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/guest_error_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/guest_error_generated.rs index 7189b13c6..57887a31b 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/guest_error_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/guest_error_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for GuestError<'a> { type Inner = GuestError<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } @@ -194,14 +192,14 @@ pub fn size_prefixed_root_as_guest_error_with_opts<'b, 'o>( /// # Safety /// Callers must trust the given bytes do indeed contain a valid `GuestError`. pub unsafe fn root_as_guest_error_unchecked(buf: &[u8]) -> GuestError { - unsafe { flatbuffers::root_unchecked::(buf) } + flatbuffers::root_unchecked::(buf) } #[inline] /// Assumes, without verification, that a buffer of bytes contains a size prefixed GuestError and returns it. /// # Safety /// Callers must trust the given bytes do indeed contain a valid size prefixed `GuestError`. pub unsafe fn size_prefixed_root_as_guest_error_unchecked(buf: &[u8]) -> GuestError { - unsafe { flatbuffers::size_prefixed_root_unchecked::(buf) } + flatbuffers::size_prefixed_root_unchecked::(buf) } #[inline] pub fn finish_guest_error_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/guest_log_data_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/guest_log_data_generated.rs index b7938f11a..8deec7cad 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/guest_log_data_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/guest_log_data_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for GuestLogData<'a> { type Inner = GuestLogData<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } @@ -290,14 +288,14 @@ pub fn size_prefixed_root_as_guest_log_data_with_opts<'b, 'o>( /// # Safety /// Callers must trust the given bytes do indeed contain a valid `GuestLogData`. pub unsafe fn root_as_guest_log_data_unchecked(buf: &[u8]) -> GuestLogData { - unsafe { flatbuffers::root_unchecked::(buf) } + flatbuffers::root_unchecked::(buf) } #[inline] /// Assumes, without verification, that a buffer of bytes contains a size prefixed GuestLogData and returns it. /// # Safety /// Callers must trust the given bytes do indeed contain a valid size prefixed `GuestLogData`. pub unsafe fn size_prefixed_root_as_guest_log_data_unchecked(buf: &[u8]) -> GuestLogData { - unsafe { flatbuffers::size_prefixed_root_unchecked::(buf) } + flatbuffers::size_prefixed_root_unchecked::(buf) } #[inline] pub fn finish_guest_log_data_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlbool_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlbool_generated.rs index 5c3b30536..d2005e5a5 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlbool_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlbool_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hlbool<'a> { type Inner = hlbool<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hldouble_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hldouble_generated.rs index 3527275a6..5c71c2c9e 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hldouble_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hldouble_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hldouble<'a> { type Inner = hldouble<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlfloat_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlfloat_generated.rs index aa03ee930..93673efe1 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlfloat_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlfloat_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hlfloat<'a> { type Inner = hlfloat<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlint_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlint_generated.rs index 7ebb3c462..a162f6eec 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlint_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlint_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hlint<'a> { type Inner = hlint<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hllong_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hllong_generated.rs index a3815898a..690afaa26 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hllong_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hllong_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hllong<'a> { type Inner = hllong<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlsizeprefixedbuffer_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlsizeprefixedbuffer_generated.rs index 22907adf7..ed1e74b37 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlsizeprefixedbuffer_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlsizeprefixedbuffer_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hlsizeprefixedbuffer<'a> { type Inner = hlsizeprefixedbuffer<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlstring_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlstring_generated.rs index 827498527..ba8c2eb7f 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlstring_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlstring_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hlstring<'a> { type Inner = hlstring<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hluint_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hluint_generated.rs index d6388bc02..e10699658 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hluint_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hluint_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hluint<'a> { type Inner = hluint<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlulong_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlulong_generated.rs index 18a22f7ed..db83b936d 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlulong_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlulong_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hlulong<'a> { type Inner = hlulong<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlvecbytes_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlvecbytes_generated.rs index 18437cecb..e673cd425 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlvecbytes_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlvecbytes_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hlvecbytes<'a> { type Inner = hlvecbytes<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlvoid_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlvoid_generated.rs index 6f169ffcc..76e0e9f97 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlvoid_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/hlvoid_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for hlvoid<'a> { type Inner = hlvoid<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/host_function_definition_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/host_function_definition_generated.rs new file mode 100644 index 000000000..381f77fcc --- /dev/null +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/host_function_definition_generated.rs @@ -0,0 +1,204 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// @generated +extern crate alloc; +extern crate flatbuffers; +use alloc::boxed::Box; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use core::cmp::Ordering; +use core::mem; + +use self::flatbuffers::{EndianScalar, Follow}; +use super::*; +pub enum HostFunctionDefinitionOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct HostFunctionDefinition<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for HostFunctionDefinition<'a> { + type Inner = HostFunctionDefinition<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: flatbuffers::Table::new(buf, loc), + } + } +} + +impl<'a> HostFunctionDefinition<'a> { + pub const VT_FUNCTION_NAME: flatbuffers::VOffsetT = 4; + pub const VT_PARAMETERS: flatbuffers::VOffsetT = 6; + pub const VT_RETURN_TYPE: flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + HostFunctionDefinition { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args HostFunctionDefinitionArgs<'args>, + ) -> flatbuffers::WIPOffset> { + let mut builder = HostFunctionDefinitionBuilder::new(_fbb); + if let Some(x) = args.parameters { + builder.add_parameters(x); + } + if let Some(x) = args.function_name { + builder.add_function_name(x); + } + builder.add_return_type(args.return_type); + builder.finish() + } + + #[inline] + pub fn function_name(&self) -> &'a str { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::>( + HostFunctionDefinition::VT_FUNCTION_NAME, + None, + ) + .unwrap() + } + } + #[inline] + pub fn key_compare_less_than(&self, o: &HostFunctionDefinition) -> bool { + self.function_name() < o.function_name() + } + + #[inline] + pub fn key_compare_with_value(&self, val: &str) -> ::core::cmp::Ordering { + let key = self.function_name(); + key.cmp(val) + } + #[inline] + pub fn parameters(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::>>( + HostFunctionDefinition::VT_PARAMETERS, + None, + ) + } + } + #[inline] + pub fn return_type(&self) -> ReturnType { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + HostFunctionDefinition::VT_RETURN_TYPE, + Some(ReturnType::hlint), + ) + .unwrap() + } + } +} + +impl flatbuffers::Verifiable for HostFunctionDefinition<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>( + "function_name", + Self::VT_FUNCTION_NAME, + true, + )? + .visit_field::>>( + "parameters", + Self::VT_PARAMETERS, + false, + )? + .visit_field::("return_type", Self::VT_RETURN_TYPE, false)? + .finish(); + Ok(()) + } +} +pub struct HostFunctionDefinitionArgs<'a> { + pub function_name: Option>, + pub parameters: Option>>, + pub return_type: ReturnType, +} +impl<'a> Default for HostFunctionDefinitionArgs<'a> { + #[inline] + fn default() -> Self { + HostFunctionDefinitionArgs { + function_name: None, // required field + parameters: None, + return_type: ReturnType::hlint, + } + } +} + +pub struct HostFunctionDefinitionBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> HostFunctionDefinitionBuilder<'a, 'b, A> { + #[inline] + pub fn add_function_name(&mut self, function_name: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>( + HostFunctionDefinition::VT_FUNCTION_NAME, + function_name, + ); + } + #[inline] + pub fn add_parameters( + &mut self, + parameters: flatbuffers::WIPOffset>, + ) { + self.fbb_.push_slot_always::>( + HostFunctionDefinition::VT_PARAMETERS, + parameters, + ); + } + #[inline] + pub fn add_return_type(&mut self, return_type: ReturnType) { + self.fbb_.push_slot::( + HostFunctionDefinition::VT_RETURN_TYPE, + return_type, + ReturnType::hlint, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + ) -> HostFunctionDefinitionBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + HostFunctionDefinitionBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + self.fbb_ + .required(o, HostFunctionDefinition::VT_FUNCTION_NAME, "function_name"); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for HostFunctionDefinition<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("HostFunctionDefinition"); + ds.field("function_name", &self.function_name()); + ds.field("parameters", &self.parameters()); + ds.field("return_type", &self.return_type()); + ds.finish() + } +} diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/host_function_details_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/host_function_details_generated.rs new file mode 100644 index 000000000..71edd22b3 --- /dev/null +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/host_function_details_generated.rs @@ -0,0 +1,215 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// @generated +extern crate alloc; +extern crate flatbuffers; +use alloc::boxed::Box; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use core::cmp::Ordering; +use core::mem; + +use self::flatbuffers::{EndianScalar, Follow}; +use super::*; +pub enum HostFunctionDetailsOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct HostFunctionDetails<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for HostFunctionDetails<'a> { + type Inner = HostFunctionDetails<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: flatbuffers::Table::new(buf, loc), + } + } +} + +impl<'a> HostFunctionDetails<'a> { + pub const VT_FUNCTIONS: flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + HostFunctionDetails { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args HostFunctionDetailsArgs<'args>, + ) -> flatbuffers::WIPOffset> { + let mut builder = HostFunctionDetailsBuilder::new(_fbb); + if let Some(x) = args.functions { + builder.add_functions(x); + } + builder.finish() + } + + #[inline] + pub fn functions( + &self, + ) -> Option>>> + { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::>, + >>(HostFunctionDetails::VT_FUNCTIONS, None) + } + } +} + +impl flatbuffers::Verifiable for HostFunctionDetails<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>, + >>("functions", Self::VT_FUNCTIONS, false)? + .finish(); + Ok(()) + } +} +pub struct HostFunctionDetailsArgs<'a> { + pub functions: Option< + flatbuffers::WIPOffset< + flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset>>, + >, + >, +} +impl<'a> Default for HostFunctionDetailsArgs<'a> { + #[inline] + fn default() -> Self { + HostFunctionDetailsArgs { functions: None } + } +} + +pub struct HostFunctionDetailsBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> HostFunctionDetailsBuilder<'a, 'b, A> { + #[inline] + pub fn add_functions( + &mut self, + functions: flatbuffers::WIPOffset< + flatbuffers::Vector<'b, flatbuffers::ForwardsUOffset>>, + >, + ) { + self.fbb_.push_slot_always::>( + HostFunctionDetails::VT_FUNCTIONS, + functions, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + ) -> HostFunctionDetailsBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + HostFunctionDetailsBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for HostFunctionDetails<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("HostFunctionDetails"); + ds.field("functions", &self.functions()); + ds.finish() + } +} +#[inline] +/// Verifies that a buffer of bytes contains a `HostFunctionDetails` +/// and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_host_function_details_unchecked`. +pub fn root_as_host_function_details( + buf: &[u8], +) -> Result { + flatbuffers::root::(buf) +} +#[inline] +/// Verifies that a buffer of bytes contains a size prefixed +/// `HostFunctionDetails` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `size_prefixed_root_as_host_function_details_unchecked`. +pub fn size_prefixed_root_as_host_function_details( + buf: &[u8], +) -> Result { + flatbuffers::size_prefixed_root::(buf) +} +#[inline] +/// Verifies, with the given options, that a buffer of bytes +/// contains a `HostFunctionDetails` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_host_function_details_unchecked`. +pub fn root_as_host_function_details_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::root_with_opts::>(opts, buf) +} +#[inline] +/// Verifies, with the given verifier options, that a buffer of +/// bytes contains a size prefixed `HostFunctionDetails` and returns +/// it. Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_host_function_details_unchecked`. +pub fn size_prefixed_root_as_host_function_details_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::size_prefixed_root_with_opts::>(opts, buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a HostFunctionDetails and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid `HostFunctionDetails`. +pub unsafe fn root_as_host_function_details_unchecked(buf: &[u8]) -> HostFunctionDetails { + flatbuffers::root_unchecked::(buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a size prefixed HostFunctionDetails and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid size prefixed `HostFunctionDetails`. +pub unsafe fn size_prefixed_root_as_host_function_details_unchecked( + buf: &[u8], +) -> HostFunctionDetails { + flatbuffers::size_prefixed_root_unchecked::(buf) +} +#[inline] +pub fn finish_host_function_details_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( + fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + root: flatbuffers::WIPOffset>, +) { + fbb.finish(root, None); +} + +#[inline] +pub fn finish_size_prefixed_host_function_details_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( + fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + root: flatbuffers::WIPOffset>, +) { + fbb.finish_size_prefixed(root, None); +} diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/log_level_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/log_level_generated.rs index 0b8076f8a..a47458489 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/log_level_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/log_level_generated.rs @@ -86,10 +86,8 @@ impl<'a> flatbuffers::Follow<'a> for LogLevel { type Inner = Self; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - let b = flatbuffers::read_scalar_at::(buf, loc); - Self(b) - } + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) } } @@ -97,9 +95,7 @@ impl flatbuffers::Push for LogLevel { type Output = LogLevel; #[inline] unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { - unsafe { - flatbuffers::emplace_scalar::(dst, self.0); - } + flatbuffers::emplace_scalar::(dst, self.0); } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_generated.rs index 44ee4df58..41e80c4ac 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_generated.rs @@ -21,10 +21,8 @@ impl<'a> flatbuffers::Follow<'a> for Parameter<'a> { type Inner = Parameter<'a>; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - Self { - _tab: flatbuffers::Table::new(buf, loc), - } + Self { + _tab: flatbuffers::Table::new(buf, loc), } } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_type_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_type_generated.rs index 404a4fa5a..5ef4b56e1 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_type_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_type_generated.rs @@ -94,10 +94,8 @@ impl<'a> flatbuffers::Follow<'a> for ParameterType { type Inner = Self; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - let b = flatbuffers::read_scalar_at::(buf, loc); - Self(b) - } + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) } } @@ -105,9 +103,7 @@ impl flatbuffers::Push for ParameterType { type Output = ParameterType; #[inline] unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { - unsafe { - flatbuffers::emplace_scalar::(dst, self.0); - } + flatbuffers::emplace_scalar::(dst, self.0); } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_value_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_value_generated.rs index ea701a73d..91d51b456 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_value_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/parameter_value_generated.rs @@ -98,10 +98,8 @@ impl<'a> flatbuffers::Follow<'a> for ParameterValue { type Inner = Self; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - let b = flatbuffers::read_scalar_at::(buf, loc); - Self(b) - } + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) } } @@ -109,9 +107,7 @@ impl flatbuffers::Push for ParameterValue { type Output = ParameterValue; #[inline] unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { - unsafe { - flatbuffers::emplace_scalar::(dst, self.0); - } + flatbuffers::emplace_scalar::(dst, self.0); } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/return_type_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/return_type_generated.rs index a11af8c07..0610cdd55 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/return_type_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/return_type_generated.rs @@ -98,10 +98,8 @@ impl<'a> flatbuffers::Follow<'a> for ReturnType { type Inner = Self; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - let b = flatbuffers::read_scalar_at::(buf, loc); - Self(b) - } + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) } } @@ -109,9 +107,7 @@ impl flatbuffers::Push for ReturnType { type Output = ReturnType; #[inline] unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { - unsafe { - flatbuffers::emplace_scalar::(dst, self.0); - } + flatbuffers::emplace_scalar::(dst, self.0); } } diff --git a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/return_value_generated.rs b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/return_value_generated.rs index f86a941bc..2c9f94872 100644 --- a/src/hyperlight_common/src/flatbuffers/hyperlight/generated/return_value_generated.rs +++ b/src/hyperlight_common/src/flatbuffers/hyperlight/generated/return_value_generated.rs @@ -102,10 +102,8 @@ impl<'a> flatbuffers::Follow<'a> for ReturnValue { type Inner = Self; #[inline] unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { - let b = flatbuffers::read_scalar_at::(buf, loc); - Self(b) - } + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) } } @@ -113,9 +111,7 @@ impl flatbuffers::Push for ReturnValue { type Output = ReturnValue; #[inline] unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { - unsafe { - flatbuffers::emplace_scalar::(dst, self.0); - } + flatbuffers::emplace_scalar::(dst, self.0); } } diff --git a/src/hyperlight_common/src/flatbuffers/mod.rs b/src/hyperlight_common/src/flatbuffers/mod.rs index 6674216df..f8ac0929d 100644 --- a/src/hyperlight_common/src/flatbuffers/mod.rs +++ b/src/hyperlight_common/src/flatbuffers/mod.rs @@ -44,6 +44,10 @@ pub mod hyperlight { pub use self::error_code_generated::*; mod guest_error_generated; pub use self::guest_error_generated::*; + mod host_function_definition_generated; + pub use self::host_function_definition_generated::*; + mod host_function_details_generated; + pub use self::host_function_details_generated::*; mod hlsizeprefixedbuffer_generated; pub use self::hlsizeprefixedbuffer_generated::*; mod log_level_generated; diff --git a/src/hyperlight_common/src/mem.rs b/src/hyperlight_common/src/mem.rs index f25e37085..c6b3c48ad 100644 --- a/src/hyperlight_common/src/mem.rs +++ b/src/hyperlight_common/src/mem.rs @@ -48,4 +48,5 @@ pub struct HyperlightPEB { pub output_stack: GuestMemoryRegion, pub guest_heap: GuestMemoryRegion, pub guest_stack: GuestStack, + pub host_function_definitions: GuestMemoryRegion, } diff --git a/src/hyperlight_guest/src/guest_handle/host_comm.rs b/src/hyperlight_guest/src/guest_handle/host_comm.rs index 4614cd775..20c776c72 100644 --- a/src/hyperlight_guest/src/guest_handle/host_comm.rs +++ b/src/hyperlight_guest/src/guest_handle/host_comm.rs @@ -17,6 +17,7 @@ limitations under the License. use alloc::format; use alloc::string::ToString; use alloc::vec::Vec; +use core::slice::from_raw_parts; use hyperlight_common::flatbuffer_wrappers::function_call::{FunctionCall, FunctionCallType}; use hyperlight_common::flatbuffer_wrappers::function_types::{ @@ -25,6 +26,7 @@ use hyperlight_common::flatbuffer_wrappers::function_types::{ use hyperlight_common::flatbuffer_wrappers::guest_error::{ErrorCode, GuestError}; use hyperlight_common::flatbuffer_wrappers::guest_log_data::GuestLogData; use hyperlight_common::flatbuffer_wrappers::guest_log_level::LogLevel; +use hyperlight_common::flatbuffer_wrappers::host_function_details::HostFunctionDetails; use hyperlight_common::outb::OutBAction; use super::handle::GuestHandle; @@ -99,6 +101,21 @@ impl GuestHandle { self.get_host_return_value::() } + pub fn get_host_function_details(&self) -> HostFunctionDetails { + let peb_ptr = self.peb().unwrap(); + let host_function_details_buffer = + unsafe { (*peb_ptr).host_function_definitions.ptr as *const u8 }; + let host_function_details_size = + unsafe { (*peb_ptr).host_function_definitions.size as usize }; + + let host_function_details_slice: &[u8] = + unsafe { from_raw_parts(host_function_details_buffer, host_function_details_size) }; + + host_function_details_slice + .try_into() + .expect("Failed to convert buffer to HostFunctionDetails") + } + /// Write an error to the shared output data buffer. pub fn write_error(&self, error_code: ErrorCode, message: Option<&str>) { let guest_error: GuestError = GuestError::new( diff --git a/src/hyperlight_guest_bin/src/host_comm.rs b/src/hyperlight_guest_bin/src/host_comm.rs index f7c1b7b54..b3ea0302c 100644 --- a/src/hyperlight_guest_bin/src/host_comm.rs +++ b/src/hyperlight_guest_bin/src/host_comm.rs @@ -24,6 +24,7 @@ use hyperlight_common::flatbuffer_wrappers::function_types::{ ParameterValue, ReturnType, ReturnValue, }; use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode; +use hyperlight_common::flatbuffer_wrappers::host_function_details::HostFunctionDetails; use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result; use hyperlight_guest::error::{HyperlightGuestError, Result}; @@ -58,6 +59,12 @@ pub fn get_host_return_value>() -> Result { handle.get_host_return_value::() } +pub fn get_host_function_details() -> HostFunctionDetails { + let handle = unsafe { GUEST_HANDLE }; + + handle.get_host_function_details() +} + /// Print a message using the host's print function. /// /// This function requires memory to be setup to be used. In particular, the diff --git a/src/hyperlight_host/src/func/host_functions.rs b/src/hyperlight_host/src/func/host_functions.rs index ca055c0b8..3944b0703 100644 --- a/src/hyperlight_host/src/func/host_functions.rs +++ b/src/hyperlight_host/src/func/host_functions.rs @@ -20,8 +20,9 @@ use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, Ret use super::utils::for_each_tuple; use super::{ParameterTuple, ResultType, SupportedReturnType}; +use crate::sandbox::host_funcs::FunctionEntry; use crate::sandbox::{ExtraAllowedSyscall, UninitializedSandbox}; -use crate::{Result, log_then_return, new_error}; +use crate::{Result, new_error}; /// A sandbox on which (primitive) host functions can be registered /// @@ -52,7 +53,15 @@ impl Registerable for UninitializedSandbox { .host_funcs .try_lock() .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?; - (*hfs).register_host_function(name.to_string(), hf.into().into()) + + let entry = FunctionEntry { + function: hf.into().into(), + extra_allowed_syscalls: None, + parameter_types: Args::TYPE, + return_type: Output::TYPE, + }; + + (*hfs).register_host_function(name.to_string(), entry, self.mgr.unwrap_mgr_mut()) } #[cfg(all(feature = "seccomp", target_os = "linux"))] fn register_host_function_with_syscalls( @@ -65,7 +74,15 @@ impl Registerable for UninitializedSandbox { .host_funcs .try_lock() .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?; - (*hfs).register_host_function_with_syscalls(name.to_string(), hf.into().into(), eas) + + let entry = FunctionEntry { + function: hf.into().into(), + extra_allowed_syscalls: Some(eas), + parameter_types: Args::TYPE, + return_type: Output::TYPE, + }; + + (*hfs).register_host_function(name.to_string(), entry, self.mgr.unwrap_mgr_mut()) } } @@ -182,31 +199,18 @@ pub(crate) fn register_host_function Result<()> { let func = func.into().into(); - if let Some(_eas) = extra_allowed_syscalls { - if cfg!(all(feature = "seccomp", target_os = "linux")) { - // Register with extra allowed syscalls - #[cfg(all(feature = "seccomp", target_os = "linux"))] - { - sandbox - .host_funcs - .try_lock() - .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))? - .register_host_function_with_syscalls(name.to_string(), func, _eas)?; - } - } else { - // Log and return an error - log_then_return!( - "Extra allowed syscalls are only supported on Linux with seccomp enabled" - ); - } - } else { - // Register without extra allowed syscalls - sandbox - .host_funcs - .try_lock() - .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))? - .register_host_function(name.to_string(), func)?; - } + let entry = FunctionEntry { + function: func, + extra_allowed_syscalls: extra_allowed_syscalls.clone(), + parameter_types: Args::TYPE, + return_type: Output::TYPE, + }; + + sandbox + .host_funcs + .try_lock() + .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))? + .register_host_function(name.to_string(), entry, sandbox.mgr.unwrap_mgr_mut())?; Ok(()) } diff --git a/src/hyperlight_host/src/func/utils.rs b/src/hyperlight_host/src/func/utils.rs index de21f501b..f06c35a3c 100644 --- a/src/hyperlight_host/src/func/utils.rs +++ b/src/hyperlight_host/src/func/utils.rs @@ -1,5 +1,5 @@ /* -Copyright 2024 The Hyperlight Authors. +Copyright 2025 The Hyperlight Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/hyperlight_host/src/hypervisor/crashdump.rs b/src/hyperlight_host/src/hypervisor/crashdump.rs index e6e776c37..ae865ef56 100644 --- a/src/hyperlight_host/src/hypervisor/crashdump.rs +++ b/src/hyperlight_host/src/hypervisor/crashdump.rs @@ -1,5 +1,5 @@ /* -Copyright 2024 The Hyperlight Authors. +Copyright 2025 The Hyperlight Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/hyperlight_host/src/mem/layout.rs b/src/hyperlight_host/src/mem/layout.rs index 7bdda34e1..70850d39f 100644 --- a/src/hyperlight_host/src/mem/layout.rs +++ b/src/hyperlight_host/src/mem/layout.rs @@ -16,12 +16,12 @@ limitations under the License. use std::fmt::Debug; use std::mem::{offset_of, size_of}; -use hyperlight_common::mem::{GuestStack, HyperlightPEB, PAGE_SIZE_USIZE}; +use hyperlight_common::mem::{GuestMemoryRegion, HyperlightPEB, PAGE_SIZE_USIZE}; use rand::{RngCore, rng}; use tracing::{Span, instrument}; use super::memory_region::MemoryRegionType::{ - Code, GuardPage, Heap, InputData, OutputData, PageTables, Peb, Stack, + Code, GuardPage, Heap, HostFunctionDefinitions, InputData, OutputData, PageTables, Peb, Stack, }; use super::memory_region::{MemoryRegion, MemoryRegionFlags, MemoryRegionVecBuilder}; use super::mgr::AMOUNT_OF_MEMORY_PER_PT; @@ -41,6 +41,8 @@ use crate::{Result, new_error}; // +-------------------------------------------+ // | Input Data | // +-------------------------------------------+ +// | Host Function Definitions | +// +-------------------------------------------+ // | PEB Struct | (HyperlightPEB size) // +-------------------------------------------+ // | Guest Code | @@ -54,6 +56,10 @@ use crate::{Result, new_error}; // | PML4 | // +-------------------------------------------+ 0x0_000 +/// +/// - `HostDefinitions` - the length of this is the `HostFunctionDefinitionSize` +/// field from `SandboxConfiguration` +/// /// - `InputData` - this is a buffer that is used for input data to the host program. /// the length of this field is `InputDataSize` from `SandboxConfiguration` /// @@ -83,6 +89,7 @@ pub(crate) struct SandboxMemoryLayout { peb_security_cookie_seed_offset: usize, peb_guest_dispatch_function_ptr_offset: usize, // set by guest in guest entrypoint peb_code_pointer_offset: usize, + pub(super) peb_host_function_definitions_offset: usize, peb_input_data_offset: usize, peb_output_data_offset: usize, peb_heap_data_offset: usize, @@ -90,6 +97,7 @@ pub(crate) struct SandboxMemoryLayout { // The following are the actual values // that are written to the PEB struct + pub(crate) host_function_definitions_buffer_offset: usize, pub(super) input_data_buffer_offset: usize, pub(super) output_data_buffer_offset: usize, guest_heap_buffer_offset: usize, @@ -126,7 +134,11 @@ impl Debug for SandboxMemoryLayout { &format_args!("{:#x}", self.peb_guest_dispatch_function_ptr_offset), ) .field( - "Code and OutB Pointer Offset", + "Host Function Definitions Offset", + &format_args!("{:#x}", self.peb_host_function_definitions_offset), + ) + .field( + "Code Pointer Offset", &format_args!("{:#x}", self.peb_code_pointer_offset), ) .field( @@ -145,6 +157,10 @@ impl Debug for SandboxMemoryLayout { "Guest Stack Offset", &format_args!("{:#x}", self.peb_guest_stack_data_offset), ) + .field( + "Host Function Definitions Buffer Offset", + &format_args!("{:#x}", self.host_function_definitions_buffer_offset), + ) .field( "Input Data Buffer Offset", &format_args!("{:#x}", self.input_data_buffer_offset), @@ -230,12 +246,19 @@ impl SandboxMemoryLayout { let peb_output_data_offset = peb_offset + offset_of!(HyperlightPEB, output_stack); let peb_heap_data_offset = peb_offset + offset_of!(HyperlightPEB, guest_heap); let peb_guest_stack_data_offset = peb_offset + offset_of!(HyperlightPEB, guest_stack); + let peb_host_function_definitions_offset = + peb_offset + offset_of!(HyperlightPEB, host_function_definitions); // The following offsets are the actual values that relate to memory layout, // which are written to PEB struct let peb_address = Self::BASE_ADDRESS + peb_offset; + // make sure host function definitions buffer starts at 4K boundary + let host_function_definitions_buffer_offset = round_up_to( + peb_host_function_definitions_offset + size_of::(), + PAGE_SIZE_USIZE, + ); let input_data_buffer_offset = round_up_to( - peb_guest_stack_data_offset + size_of::(), + host_function_definitions_buffer_offset + cfg.get_host_function_definition_size(), PAGE_SIZE_USIZE, ); let output_data_buffer_offset = round_up_to( @@ -260,12 +283,14 @@ impl SandboxMemoryLayout { peb_security_cookie_seed_offset, peb_guest_dispatch_function_ptr_offset, peb_code_pointer_offset, + peb_host_function_definitions_offset, peb_input_data_offset, peb_output_data_offset, peb_heap_data_offset, peb_guest_stack_data_offset, sandbox_memory_config: cfg, code_size, + host_function_definitions_buffer_offset, input_data_buffer_offset, output_data_buffer_offset, guest_heap_buffer_offset, @@ -284,6 +309,22 @@ impl SandboxMemoryLayout { self.peb_output_data_offset } + /// Get the offset in guest memory to the host function definitions + /// size + #[instrument(skip_all, parent = Span::current(), level= "Trace")] + pub(super) fn get_host_function_definitions_size_offset(&self) -> usize { + // The size field is the first field in the `HostFunctions` struct + self.peb_host_function_definitions_offset + } + + /// Get the offset in guest memory to the host function definitions + /// pointer. + #[instrument(skip_all, parent = Span::current(), level= "Trace")] + fn get_host_function_definitions_pointer_offset(&self) -> usize { + // The size field is the field after the size field in the `HostFunctions` struct which is a u64 + self.peb_host_function_definitions_offset + size_of::() + } + /// Get the offset in guest memory to the minimum guest stack address. #[instrument(skip_all, parent = Span::current(), level= "Trace")] fn get_min_guest_stack_address_offset(&self) -> usize { @@ -447,6 +488,8 @@ impl SandboxMemoryLayout { let mut total_mapped_memory_size: usize = round_up_to(code_size, PAGE_SIZE_USIZE); total_mapped_memory_size += round_up_to(stack_size, PAGE_SIZE_USIZE); total_mapped_memory_size += round_up_to(heap_size, PAGE_SIZE_USIZE); + total_mapped_memory_size += + round_up_to(cfg.get_host_function_definition_size(), PAGE_SIZE_USIZE); total_mapped_memory_size += round_up_to(cfg.get_input_data_size(), PAGE_SIZE_USIZE); total_mapped_memory_size += round_up_to(cfg.get_output_data_size(), PAGE_SIZE_USIZE); total_mapped_memory_size += round_up_to(size_of::(), PAGE_SIZE_USIZE); @@ -526,12 +569,31 @@ impl SandboxMemoryLayout { } // PEB - let input_data_offset = builder.push_page_aligned( + let host_functions_definitions_offset = builder.push_page_aligned( size_of::(), MemoryRegionFlags::READ | MemoryRegionFlags::WRITE, Peb, ); + let expected_host_functions_definitions_offset = + TryInto::::try_into(self.host_function_definitions_buffer_offset)?; + + if host_functions_definitions_offset != expected_host_functions_definitions_offset { + return Err(new_error!( + "Host Function Definitions offset does not match expected Host Function Definitions offset expected: {}, actual: {}", + expected_host_functions_definitions_offset, + host_functions_definitions_offset + )); + } + + // host function definitions + let input_data_offset = builder.push_page_aligned( + self.sandbox_memory_config + .get_host_function_definition_size(), + MemoryRegionFlags::READ, + HostFunctionDefinitions, + ); + let expected_input_data_offset = TryInto::::try_into(self.input_data_buffer_offset)?; if input_data_offset != expected_input_data_offset { @@ -672,6 +734,16 @@ impl SandboxMemoryLayout { // Skip guest_dispatch_function_ptr_offset because it is set by the guest + // Set up Host Function Definition + shared_mem.write_u64( + self.get_host_function_definitions_size_offset(), + self.sandbox_memory_config + .get_host_function_definition_size() + .try_into()?, + )?; + let addr = get_address!(host_function_definitions_buffer_offset); + shared_mem.write_u64(self.get_host_function_definitions_pointer_offset(), addr)?; + // Skip code, is set when loading binary // skip outb and outb context, is set when running in_proc @@ -779,6 +851,8 @@ mod tests { expected_size += round_up_to(size_of::(), PAGE_SIZE_USIZE); + expected_size += round_up_to(cfg.get_host_function_definition_size(), PAGE_SIZE_USIZE); + expected_size += round_up_to(cfg.get_input_data_size(), PAGE_SIZE_USIZE); expected_size += round_up_to(cfg.get_output_data_size(), PAGE_SIZE_USIZE); diff --git a/src/hyperlight_host/src/mem/memory_region.rs b/src/hyperlight_host/src/mem/memory_region.rs index 686e8750a..1ddb842e1 100644 --- a/src/hyperlight_host/src/mem/memory_region.rs +++ b/src/hyperlight_host/src/mem/memory_region.rs @@ -131,6 +131,8 @@ pub enum MemoryRegionType { Code, /// The region contains the PEB Peb, + /// The region contains the Host Function Definitions + HostFunctionDefinitions, /// The region contains the Input Data InputData, /// The region contains the Output Data diff --git a/src/hyperlight_host/src/mem/mgr.rs b/src/hyperlight_host/src/mem/mgr.rs index 3996d0d66..5c82acfd2 100644 --- a/src/hyperlight_host/src/mem/mgr.rs +++ b/src/hyperlight_host/src/mem/mgr.rs @@ -23,6 +23,7 @@ use hyperlight_common::flatbuffer_wrappers::function_call::{ use hyperlight_common::flatbuffer_wrappers::function_types::ReturnValue; use hyperlight_common::flatbuffer_wrappers::guest_error::GuestError; use hyperlight_common::flatbuffer_wrappers::guest_log_data::GuestLogData; +use hyperlight_common::flatbuffer_wrappers::host_function_details::HostFunctionDetails; use tracing::{Span, instrument}; use super::exe::ExeInfo; @@ -170,6 +171,8 @@ where MemoryRegionType::InputData => PAGE_PRESENT | PAGE_RW | PAGE_NX, MemoryRegionType::OutputData => PAGE_PRESENT | PAGE_RW | PAGE_NX, MemoryRegionType::Peb => PAGE_PRESENT | PAGE_RW | PAGE_NX, + // Host Function Definitions are readonly in the guest + MemoryRegionType::HostFunctionDefinitions => PAGE_PRESENT | PAGE_NX, MemoryRegionType::PageTables => PAGE_PRESENT | PAGE_RW | PAGE_NX, }, // If there is an error then the address isn't mapped so mark it as not present @@ -312,6 +315,42 @@ impl SandboxMemoryManager { Ok(Self::new(layout, shared_mem, load_addr, entrypoint_offset)) } + /// Writes host function details to memory + #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] + pub(crate) fn write_buffer_host_function_details(&mut self, buffer: &[u8]) -> Result<()> { + let host_function_details = HostFunctionDetails::try_from(buffer).map_err(|e| { + new_error!( + "write_buffer_host_function_details: failed to convert buffer to HostFunctionDetails: {}", + e + ) + })?; + + let host_function_call_buffer: Vec = (&host_function_details).try_into().map_err(|_| { + new_error!( + "write_buffer_host_function_details: failed to convert HostFunctionDetails to Vec" + ) + })?; + + let buffer_size = { + let size_u64 = self + .shared_mem + .read_u64(self.layout.get_host_function_definitions_size_offset())?; + usize::try_from(size_u64) + }?; + + if host_function_call_buffer.len() > buffer_size { + log_then_return!( + "Host Function Details buffer is too big for the host_function_definitions buffer" + ); + } + + self.shared_mem.copy_from_slice( + host_function_call_buffer.as_slice(), + self.layout.host_function_definitions_buffer_offset, + )?; + Ok(()) + } + /// Set the stack guard to `cookie` using `layout` to calculate /// its location and `shared_mem` to write it. #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] diff --git a/src/hyperlight_host/src/sandbox/config.rs b/src/hyperlight_host/src/sandbox/config.rs index f535b385d..b1391c084 100644 --- a/src/hyperlight_host/src/sandbox/config.rs +++ b/src/hyperlight_host/src/sandbox/config.rs @@ -46,6 +46,9 @@ pub struct SandboxConfiguration { /// Guest gdb debug port #[cfg(gdb)] guest_debug_info: Option, + /// The size of the memory buffer that is made available for Guest Function + /// Definitions + host_function_definition_size: usize, /// The size of the memory buffer that is made available for input to the /// Guest Binary input_data_size: usize, @@ -92,6 +95,12 @@ impl SandboxConfiguration { pub const DEFAULT_OUTPUT_SIZE: usize = 0x4000; /// The minimum size of output data pub const MIN_OUTPUT_SIZE: usize = 0x2000; + /// The default size of host function definitionsSET + /// Host function definitions has its own page in memory, in order to be READ-ONLY + /// from a guest's perspective. + pub const DEFAULT_HOST_FUNCTION_DEFINITION_SIZE: usize = 0x1000; + /// The minimum size of host function definitions + pub const MIN_HOST_FUNCTION_DEFINITION_SIZE: usize = 0x1000; /// The default interrupt retry delay pub const DEFAULT_INTERRUPT_RETRY_DELAY: Duration = Duration::from_micros(500); /// The default signal offset from `SIGRTMIN` used to determine the signal number for interrupting @@ -103,6 +112,7 @@ impl SandboxConfiguration { fn new( input_data_size: usize, output_data_size: usize, + function_definition_size: usize, stack_size_override: Option, heap_size_override: Option, interrupt_retry_delay: Duration, @@ -113,6 +123,10 @@ impl SandboxConfiguration { Self { input_data_size: max(input_data_size, Self::MIN_INPUT_SIZE), output_data_size: max(output_data_size, Self::MIN_OUTPUT_SIZE), + host_function_definition_size: max( + function_definition_size, + Self::MIN_HOST_FUNCTION_DEFINITION_SIZE, + ), stack_size_override: stack_size_override.unwrap_or(0), heap_size_override: heap_size_override.unwrap_or(0), interrupt_retry_delay, @@ -124,6 +138,16 @@ impl SandboxConfiguration { } } + /// Set the size of the memory buffer that is made available for serialising host function definitions + /// the minimum value is MIN_HOST_FUNCTION_DEFINITION_SIZE + #[instrument(skip_all, parent = Span::current(), level= "Trace")] + pub fn set_host_function_definition_size(&mut self, host_function_definition_size: usize) { + self.host_function_definition_size = max( + host_function_definition_size, + Self::MIN_HOST_FUNCTION_DEFINITION_SIZE, + ); + } + /// Set the size of the memory buffer that is made available for input to the guest /// the minimum value is MIN_INPUT_SIZE #[instrument(skip_all, parent = Span::current(), level= "Trace")] @@ -201,6 +225,11 @@ impl SandboxConfiguration { self.guest_debug_info = Some(debug_info); } + #[instrument(skip_all, parent = Span::current(), level= "Trace")] + pub(crate) fn get_host_function_definition_size(&self) -> usize { + self.host_function_definition_size + } + #[instrument(skip_all, parent = Span::current(), level= "Trace")] pub(crate) fn get_input_data_size(&self) -> usize { self.input_data_size @@ -256,6 +285,7 @@ impl Default for SandboxConfiguration { Self::new( Self::DEFAULT_INPUT_SIZE, Self::DEFAULT_OUTPUT_SIZE, + Self::DEFAULT_HOST_FUNCTION_DEFINITION_SIZE, None, None, Self::DEFAULT_INTERRUPT_RETRY_DELAY, @@ -279,9 +309,11 @@ mod tests { const HEAP_SIZE_OVERRIDE: u64 = 0x50000; const INPUT_DATA_SIZE_OVERRIDE: usize = 0x4000; const OUTPUT_DATA_SIZE_OVERRIDE: usize = 0x4001; + const HOST_FUNCTION_DEFINITION_SIZE_OVERRIDE: usize = 0x4002; let mut cfg = SandboxConfiguration::new( INPUT_DATA_SIZE_OVERRIDE, OUTPUT_DATA_SIZE_OVERRIDE, + HOST_FUNCTION_DEFINITION_SIZE_OVERRIDE, Some(STACK_SIZE_OVERRIDE), Some(HEAP_SIZE_OVERRIDE), SandboxConfiguration::DEFAULT_INTERRUPT_RETRY_DELAY, @@ -304,6 +336,10 @@ mod tests { assert_eq!(2048, cfg.heap_size_override); assert_eq!(INPUT_DATA_SIZE_OVERRIDE, cfg.input_data_size); assert_eq!(OUTPUT_DATA_SIZE_OVERRIDE, cfg.output_data_size); + assert_eq!( + HOST_FUNCTION_DEFINITION_SIZE_OVERRIDE, + cfg.host_function_definition_size + ); } #[test] @@ -311,6 +347,7 @@ mod tests { let mut cfg = SandboxConfiguration::new( SandboxConfiguration::MIN_INPUT_SIZE - 1, SandboxConfiguration::MIN_OUTPUT_SIZE - 1, + SandboxConfiguration::MIN_HOST_FUNCTION_DEFINITION_SIZE - 1, None, None, SandboxConfiguration::DEFAULT_INTERRUPT_RETRY_DELAY, @@ -322,14 +359,25 @@ mod tests { ); assert_eq!(SandboxConfiguration::MIN_INPUT_SIZE, cfg.input_data_size); assert_eq!(SandboxConfiguration::MIN_OUTPUT_SIZE, cfg.output_data_size); + assert_eq!( + SandboxConfiguration::MIN_HOST_FUNCTION_DEFINITION_SIZE, + cfg.host_function_definition_size + ); assert_eq!(0, cfg.stack_size_override); assert_eq!(0, cfg.heap_size_override); cfg.set_input_data_size(SandboxConfiguration::MIN_INPUT_SIZE - 1); cfg.set_output_data_size(SandboxConfiguration::MIN_OUTPUT_SIZE - 1); + cfg.set_host_function_definition_size( + SandboxConfiguration::MIN_HOST_FUNCTION_DEFINITION_SIZE - 1, + ); assert_eq!(SandboxConfiguration::MIN_INPUT_SIZE, cfg.input_data_size); assert_eq!(SandboxConfiguration::MIN_OUTPUT_SIZE, cfg.output_data_size); + assert_eq!( + SandboxConfiguration::MIN_HOST_FUNCTION_DEFINITION_SIZE, + cfg.host_function_definition_size + ); } mod proptests { @@ -354,6 +402,13 @@ mod tests { prop_assert_eq!(size, cfg.get_output_data_size()); } + #[test] + fn host_function_definition_size(size in SandboxConfiguration::MIN_HOST_FUNCTION_DEFINITION_SIZE..=SandboxConfiguration::MIN_HOST_FUNCTION_DEFINITION_SIZE * 10) { + let mut cfg = SandboxConfiguration::default(); + cfg.set_host_function_definition_size(size); + prop_assert_eq!(size, cfg.get_host_function_definition_size()); + } + #[test] fn stack_size_override(size in 0x1000..=0x10000u64) { let mut cfg = SandboxConfiguration::default(); diff --git a/src/hyperlight_host/src/sandbox/host_funcs.rs b/src/hyperlight_host/src/sandbox/host_funcs.rs index 8bd00a87c..158ff87d5 100644 --- a/src/hyperlight_host/src/sandbox/host_funcs.rs +++ b/src/hyperlight_host/src/sandbox/host_funcs.rs @@ -17,13 +17,19 @@ limitations under the License. use std::collections::HashMap; use std::io::{IsTerminal, Write}; -use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnValue}; +use hyperlight_common::flatbuffer_wrappers::function_types::{ + ParameterType, ParameterValue, ReturnType, ReturnValue, +}; +use hyperlight_common::flatbuffer_wrappers::host_function_definition::HostFunctionDefinition; +use hyperlight_common::flatbuffer_wrappers::host_function_details::HostFunctionDetails; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use tracing::{Span, instrument}; use super::ExtraAllowedSyscall; use crate::HyperlightError::HostFunctionNotFound; use crate::func::host_functions::TypeErasedHostFunction; +use crate::mem::mgr::SandboxMemoryManager; +use crate::mem::shared_mem::ExclusiveSharedMemory; use crate::{Result, new_error}; #[derive(Default)] @@ -32,9 +38,29 @@ pub struct FunctionRegistry { functions_map: HashMap, } +impl From<&mut FunctionRegistry> for HostFunctionDetails { + fn from(registry: &mut FunctionRegistry) -> Self { + let host_functions = registry + .functions_map + .iter() + .map(|(name, entry)| HostFunctionDefinition { + function_name: name.clone(), + parameter_types: Some(entry.parameter_types.to_vec()), + return_type: entry.return_type, + }) + .collect(); + + HostFunctionDetails { + host_functions: Some(host_functions), + } + } +} + pub struct FunctionEntry { pub function: TypeErasedHostFunction, pub extra_allowed_syscalls: Option>, + pub parameter_types: &'static [ParameterType], + pub return_type: ReturnType, } impl FunctionRegistry { @@ -43,22 +69,22 @@ impl FunctionRegistry { pub(crate) fn register_host_function( &mut self, name: String, - func: TypeErasedHostFunction, + func: FunctionEntry, + mgr: &mut SandboxMemoryManager, ) -> Result<()> { - self.register_host_function_helper(name, func, None) - } + self.functions_map.insert(name, func); - /// Register a host function with the sandbox, with a list of extra syscalls - /// that the function is allowed to make. - #[instrument(err(Debug), skip_all, parent = Span::current(), level = "Trace")] - #[cfg(all(feature = "seccomp", target_os = "linux"))] - pub(crate) fn register_host_function_with_syscalls( - &mut self, - name: String, - func: TypeErasedHostFunction, - extra_allowed_syscalls: Vec, - ) -> Result<()> { - self.register_host_function_helper(name, func, Some(extra_allowed_syscalls)) + let hfd = HostFunctionDetails::from(self); + + let buffer: Vec = (&hfd).try_into().map_err(|e| { + new_error!( + "Error serializing host function details to flatbuffer: {}", + e + ) + })?; + + mgr.write_buffer_host_function_details(&buffer)?; + Ok(()) } /// Assuming a host function called `"HostPrint"` exists, and takes a @@ -88,34 +114,13 @@ impl FunctionRegistry { self.call_host_func_impl(name, args) } - fn register_host_function_helper( - &mut self, - name: String, - function: TypeErasedHostFunction, - extra_allowed_syscalls: Option>, - ) -> Result<()> { - #[cfg(not(all(feature = "seccomp", target_os = "linux")))] - if extra_allowed_syscalls.is_some() { - return Err(new_error!( - "Extra syscalls are only supported on Linux with seccomp" - )); - } - - self.functions_map.insert( - name, - FunctionEntry { - function, - extra_allowed_syscalls, - }, - ); - Ok(()) - } - #[instrument(err(Debug), skip_all, parent = Span::current(), level = "Trace")] fn call_host_func_impl(&self, name: &str, args: Vec) -> Result { let FunctionEntry { function, extra_allowed_syscalls, + parameter_types: _, + return_type: _, } = self .functions_map .get(name) diff --git a/src/hyperlight_host/src/sandbox/mod.rs b/src/hyperlight_host/src/sandbox/mod.rs index baf98c72f..c6e33c84b 100644 --- a/src/hyperlight_host/src/sandbox/mod.rs +++ b/src/hyperlight_host/src/sandbox/mod.rs @@ -17,7 +17,7 @@ limitations under the License. /// Configuration needed to establish a sandbox. pub mod config; /// Functionality for reading, but not modifying host functions -mod host_funcs; +pub(crate) mod host_funcs; /// Functionality for dealing with `Sandbox`es that contain Hypervisors pub(crate) mod hypervisor; /// Functionality for dealing with initialized sandboxes that can diff --git a/src/schema/host_function_definition.fbs b/src/schema/host_function_definition.fbs new file mode 100644 index 000000000..2367007b7 --- /dev/null +++ b/src/schema/host_function_definition.fbs @@ -0,0 +1,11 @@ +include "function_types.fbs"; + +namespace Hyperlight.Generated; + +table HostFunctionDefinition { + function_name:string(required, key); + parameters:[ParameterType]; + return_type:ReturnType; +} + +root_type HostFunctionDefinition; \ No newline at end of file diff --git a/src/schema/host_function_details.fbs b/src/schema/host_function_details.fbs new file mode 100644 index 000000000..5ebd68576 --- /dev/null +++ b/src/schema/host_function_details.fbs @@ -0,0 +1,9 @@ +include "host_function_definition.fbs"; + +namespace Hyperlight.Generated; + +table HostFunctionDetails { + functions:[HostFunctionDefinition]; +} + +root_type HostFunctionDetails; \ No newline at end of file