fidius-host::loader Rust¶
Core plugin loading and descriptor validation.
Structs¶
fidius-host::loader::LoadedLibrary¶
pub
A loaded plugin library with validated descriptors.
Fields¶
| Name | Type | Description |
|---|---|---|
library |
Arc < Library > |
The dynamically loaded library. Must stay alive while any PluginHandle exists. |
plugins |
Vec < LoadedPlugin > |
Validated plugin descriptors with owned metadata. |
fidius-host::loader::LoadedPlugin¶
pub
A single validated plugin from a loaded library.
Fields¶
| Name | Type | Description |
|---|---|---|
info |
PluginInfo |
Owned metadata copied from the FFI descriptor. |
vtable |
* const c_void |
Raw vtable pointer (points into the loaded library's memory). |
free_buffer |
Option < unsafe extern "C" fn (* mut u8 , usize) > |
Free function for plugin-allocated buffers. |
method_count |
u32 |
Total number of methods in the vtable. |
descriptor |
* const PluginDescriptor |
Raw pointer to the plugin's descriptor in library memory. Kept so the |
host can read metadata fields (method_metadata, trait_metadata) |
||
without re-walking the registry. Valid for the lifetime of library. |
||
library |
Arc < Library > |
Reference to the library to keep it alive. |
Functions¶
fidius-host::loader::load_library¶
pub
Load a plugin library from a path.
Opens the dylib, calls fidius_get_registry(), validates the registry
and all descriptors, copies FFI data to owned types.
Source
pub fn load_library(path: &Path) -> Result<LoadedLibrary, LoadError> {
let path_str = path.display().to_string();
#[cfg(feature = "tracing")]
tracing::debug!(path = %path_str, "loading library");
// Check architecture before dlopen
crate::arch::check_architecture(path)?;
// dlopen
let library = unsafe { Library::new(path) }.map_err(|e| {
if e.to_string().contains("No such file") || e.to_string().contains("not found") {
LoadError::LibraryNotFound {
path: path_str.clone(),
}
} else {
LoadError::LibLoading(e)
}
})?;
// dlsym("fidius_get_registry")
let get_registry: libloading::Symbol<unsafe extern "C" fn() -> *const PluginRegistry> =
unsafe { library.get(b"fidius_get_registry") }.map_err(|_| LoadError::SymbolNotFound {
path: path_str.clone(),
})?;
// Call to get the registry pointer
let registry = unsafe { &*get_registry() };
// Validate magic
if registry.magic != FIDIUS_MAGIC {
return Err(LoadError::InvalidMagic);
}
// Validate registry version
if registry.registry_version != REGISTRY_VERSION {
return Err(LoadError::IncompatibleRegistryVersion {
got: registry.registry_version,
expected: REGISTRY_VERSION,
});
}
let library = Arc::new(library);
// Iterate descriptors and validate each
let mut plugins = Vec::with_capacity(registry.plugin_count as usize);
for i in 0..registry.plugin_count {
let desc = unsafe { &**registry.descriptors.add(i as usize) };
let plugin = validate_descriptor(desc, &library)?;
plugins.push(plugin);
}
Ok(LoadedLibrary { library, plugins })
}
fidius-host::loader::validate_descriptor¶
private
fn validate_descriptor (desc : & PluginDescriptor , library : & Arc < Library > ,) -> Result < LoadedPlugin , LoadError >
Validate a single descriptor and copy to owned types.
Source
fn validate_descriptor(
desc: &PluginDescriptor,
library: &Arc<Library>,
) -> Result<LoadedPlugin, LoadError> {
// Check ABI version
if desc.abi_version != ABI_VERSION {
return Err(LoadError::IncompatibleAbiVersion {
got: desc.abi_version,
expected: ABI_VERSION,
});
}
// Copy FFI strings to owned
let interface_name = unsafe { desc.interface_name_str() }.to_string();
let plugin_name = unsafe { desc.plugin_name_str() }.to_string();
let info = PluginInfo {
name: plugin_name,
interface_name,
interface_hash: desc.interface_hash,
interface_version: desc.interface_version,
capabilities: desc.capabilities,
buffer_strategy: desc
.buffer_strategy_kind()
.map_err(|v| LoadError::UnknownBufferStrategy { value: v })?,
};
Ok(LoadedPlugin {
info,
vtable: desc.vtable,
free_buffer: desc.free_buffer,
method_count: desc.method_count,
descriptor: desc as *const PluginDescriptor,
library: Arc::clone(library),
})
}
fidius-host::loader::validate_against_interface¶
pub
fn validate_against_interface (plugin : & LoadedPlugin , expected_hash : Option < u64 > , expected_strategy : Option < BufferStrategyKind > ,) -> Result < () , LoadError >
Validate a loaded plugin against expected interface parameters.
Source
pub fn validate_against_interface(
plugin: &LoadedPlugin,
expected_hash: Option<u64>,
expected_strategy: Option<BufferStrategyKind>,
) -> Result<(), LoadError> {
if let Some(hash) = expected_hash {
if plugin.info.interface_hash != hash {
return Err(LoadError::InterfaceHashMismatch {
got: plugin.info.interface_hash,
expected: hash,
});
}
}
if let Some(strategy) = expected_strategy {
if plugin.info.buffer_strategy != strategy {
return Err(LoadError::BufferStrategyMismatch {
got: plugin.info.buffer_strategy,
expected: strategy,
});
}
}
Ok(())
}