AbiModule

Trait AbiModule 

Source
pub trait AbiModule:
    Send
    + Sync
    + 'static {
Show 22 methods // Required methods fn name() -> &'static str where Self: Sized; fn get_name(&self) -> String; fn clone_boxed(&self) -> Box<dyn AbiModule + Send + Sync>; fn handle_syscall( &mut self, trapframe: &mut Trapframe, ) -> Result<usize, &'static str>; fn execute_binary( &self, file_object: &KernelObject, argv: &[&str], envp: &[&str], task: &Task, trapframe: &mut Trapframe, ) -> Result<(), &'static str>; // Provided methods fn on_task_cloned( &mut self, _parent_task: &Task, _child_task: &Task, _flags: CloneFlags, ) -> Result<(), &'static str> { ... } fn on_task_exit(&mut self, _task: &Task) { ... } fn get_task_namespace(&self) -> Arc<TaskNamespace> { ... } fn can_execute_binary( &self, _file_object: &KernelObject, _file_path: &str, _current_abi: Option<&(dyn AbiModule + Send + Sync)>, ) -> Option<u8> { ... } fn initialize_from_existing_handles( &mut self, _task: &Task, ) -> Result<(), &'static str> { ... } fn normalize_env_to_scarlet(&self, _envp: &mut Vec<String>) { ... } fn denormalize_env_from_scarlet(&self, _envp: &mut Vec<String>) { ... } fn choose_load_address( &self, _elf_type: u16, _target: LoadTarget, ) -> Option<u64> { ... } fn get_interpreter_path(&self, requested_interpreter: &str) -> String { ... } fn get_runtime_config( &self, _file_object: &KernelObject, _file_path: &str, ) -> Option<RuntimeConfig> { ... } fn get_default_cwd(&self) -> &str { ... } fn setup_overlay_environment( &self, _target_vfs: &Arc<VfsManager>, _base_vfs: &Arc<VfsManager>, _system_path: &str, _config_path: &str, ) -> Result<(), &'static str> { ... } fn setup_shared_resources( &self, _target_vfs: &Arc<VfsManager>, _base_vfs: &Arc<VfsManager>, ) -> Result<(), &'static str> { ... } fn handle_event( &self, _event: Event, _target_task_id: u32, ) -> Result<(), &'static str> { ... } fn set_tls_pointer(&mut self, _ptr: usize) { ... } fn get_tls_pointer(&self) -> Option<usize> { ... } fn set_clear_child_tid(&mut self, _ptr: usize) { ... }
}
Expand description

ABI module trait.

This trait defines the interface for ABI modules in the Scarlet kernel. ABI modules are responsible for handling system calls and providing the necessary functionality for different application binary interfaces.

Each ABI module must implement Clone to support task cloning with independent ABI state per task.

Required Methods§

Source

fn name() -> &'static str
where Self: Sized,

Source

fn get_name(&self) -> String

Source

fn clone_boxed(&self) -> Box<dyn AbiModule + Send + Sync>

Clone this ABI module into a boxed trait object

This method enables cloning ABI modules as trait objects, allowing each task to have its own independent ABI instance.

Source

fn handle_syscall( &mut self, trapframe: &mut Trapframe, ) -> Result<usize, &'static str>

Source

fn execute_binary( &self, file_object: &KernelObject, argv: &[&str], envp: &[&str], task: &Task, trapframe: &mut Trapframe, ) -> Result<(), &'static str>

Binary execution (each ABI supports its own binary format)

This method actually executes a binary that has already been verified by can_execute_binary. Use file_object.as_file() to access FileObject, and call ABI-specific loaders (ELF, PE, etc.) to load and execute the binary.

Environment variables are passed directly as envp array, not stored in task.

§Arguments
  • file_object - Binary file to execute (already opened, in KernelObject format)
  • argv - Command line arguments
  • envp - Environment variables in “KEY=VALUE” format
  • task - Target task (modified by this method)
  • trapframe - Execution context (modified by this method)
§Implementation Notes
  • Use file_object.as_file() to get FileObject
  • Use ABI-specific loaders (e.g., task::elf_loader)
  • Environment variables are passed directly as envp parameter
  • Set task’s memory space, registers, and entry point
  • Update trapframe registers (PC, SP) for the new process
  • Recommended to restore original state on execution failure
§Return Value Handling in Syscall Context

The Scarlet syscall mechanism works as follows:

  1. sys_execve() calls this method
  2. sys_execve() returns usize to syscall_handler()
  3. syscall_handler() returns Ok(usize) to syscall_dispatcher()
  4. syscall_dispatcher() returns Ok(usize) to trap handler
  5. Trap handler calls trapframe.set_return_value(usize) automatically

Provided Methods§

Source

fn on_task_cloned( &mut self, _parent_task: &Task, _child_task: &Task, _flags: CloneFlags, ) -> Result<(), &'static str>

Hook invoked after Task::clone_task creates the child

Source

fn on_task_exit(&mut self, _task: &Task)

Hook invoked as part of Task::exit cleanup for the current task

ABI modules can perform per-ABI teardown such as waking futex waiters, clearing TLS/robust-list pointers, or delivering exit-related signals.

Source

fn get_task_namespace(&self) -> Arc<TaskNamespace>

Get the task namespace for this ABI.

This allows each ABI to have its own namespace for task IDs. By default, returns the root namespace.

§Returns

The task namespace for this ABI

Source

fn can_execute_binary( &self, _file_object: &KernelObject, _file_path: &str, _current_abi: Option<&(dyn AbiModule + Send + Sync)>, ) -> Option<u8>

Determine if a binary can be executed by this ABI and return confidence

This method reads binary content directly from the file object and executes ABI-specific detection logic (magic bytes, header structure, entry point validation, etc.).

§Arguments
  • file_object - Binary file to check (in KernelObject format)
  • file_path - File path (for auxiliary detection like file extensions)
  • current_abi - Current task’s ABI reference for inheritance/compatibility decisions
§Returns
  • Some(confidence) - Confidence level (0-100) if executable by this ABI
  • None - Not executable by this ABI
§Implementation Guidelines
  • Use file_object.as_file() to access FileObject
  • Use StreamOps::read() to directly read file content
  • Check ABI-specific magic bytes and header structures
  • Validate entry point and architecture compatibility
  • Consider current_abi for inheritance/compatibility bonus (same ABI = higher confidence)
  • Return confidence based on how well the binary matches this ABI
  • No need for artificial score limitations - let each ABI decide its own confidence
  • 0-30: Basic compatibility (correct magic bytes, architecture)
  • 31-60: Good match (+ file extension, path hints, valid entry point)
  • 61-80: Strong match (+ ABI-specific headers, symbols, sections)
  • 81-100: Perfect match (+ same ABI inheritance, full validation)
§Example Scoring Strategy
let mut confidence = 0;

// Basic format check
if self.is_valid_format(file_object) { confidence += 30; }

// Entry point validation
if self.is_valid_entry_point(file_object) { confidence += 15; }

// File path hints
if file_path.contains(self.get_name()) { confidence += 15; }

// ABI inheritance bonus
if let Some(abi) = current_abi {
    if abi.get_name() == self.get_name() { confidence += 40; }
}

Some(confidence.min(100))
Source

fn initialize_from_existing_handles( &mut self, _task: &Task, ) -> Result<(), &'static str>

Handle conversion when switching ABIs

Source

fn normalize_env_to_scarlet(&self, _envp: &mut Vec<String>)

Convert environment variables from this ABI to Scarlet canonical format (in-place)

This method is called when switching from this ABI to another ABI. It should convert ABI-specific environment variables to a canonical Scarlet format that can then be converted to the target ABI.

Uses in-place modification to avoid expensive allocations.

§Arguments
  • envp - Mutable reference to environment variables in “KEY=VALUE” format, will be modified to contain Scarlet canonical format
§Implementation Guidelines
  • Convert paths to absolute Scarlet namespace paths
  • Normalize variable names to Scarlet conventions
  • Remove ABI-specific variables that don’t translate
  • Ensure all paths are absolute and start with /
  • Modify the vector in-place for efficiency
Source

fn denormalize_env_from_scarlet(&self, _envp: &mut Vec<String>)

Convert environment variables from Scarlet canonical format to this ABI’s format (in-place)

This method is called when switching to this ABI from another ABI. It should convert canonical Scarlet environment variables to this ABI’s specific format and namespace.

Uses in-place modification to avoid expensive allocations.

§Arguments
  • envp - Mutable reference to environment variables in Scarlet canonical format, will be modified to contain this ABI’s format
Source

fn choose_load_address( &self, _elf_type: u16, _target: LoadTarget, ) -> Option<u64>

Choose base address for ELF loading (ABI-specific strategy)

This method allows each ABI to define its own memory layout preferences for different types of ELF objects. The ELF loader will use these addresses when loading binaries for this ABI.

§Arguments
  • elf_type - ELF file type (ET_EXEC, ET_DYN, etc.)
  • target - Target component being loaded
§Returns

Base address where the component should be loaded, or None to use kernel default strategy

Source

fn get_interpreter_path(&self, requested_interpreter: &str) -> String

Override interpreter path (for ABI compatibility)

This method allows each ABI to specify which dynamic linker should be used when a binary requires dynamic linking (has PT_INTERP).

§Arguments
  • requested_interpreter - Interpreter path from PT_INTERP segment
§Returns

The interpreter path to actually use (may be different from requested)

Source

fn get_runtime_config( &self, _file_object: &KernelObject, _file_path: &str, ) -> Option<RuntimeConfig>

Get userland runtime configuration for executing binaries

This method allows ABI modules to delegate binary execution to userland runtimes. When a runtime is configured, the binary will be executed via the runtime instead of being loaded directly by the kernel.

§Arguments
  • file_object - Binary file to check
  • file_path - File path for format detection
§Returns
  • Some(RuntimeConfig) - Runtime configuration if delegation is needed
  • None - No runtime delegation, execute directly
§Example Use Cases
  • MS-DOS binaries via DOSBox (Linux ABI runtime)
  • Wasm binaries via Scarlet-native Wasm runtime
  • Java bytecode via JVM
  • Cross-architecture binaries via QEMU user-mode
Source

fn get_default_cwd(&self) -> &str

Get default working directory for this ABI

Source

fn setup_overlay_environment( &self, _target_vfs: &Arc<VfsManager>, _base_vfs: &Arc<VfsManager>, _system_path: &str, _config_path: &str, ) -> Result<(), &'static str>

Setup overlay environment for this ABI (read-only base + writable layer)

Creates overlay filesystem with provided base VFS and paths. The TransparentExecutor is responsible for providing base_vfs, paths, and verifying that directories exist. This method assumes that required directories (/system/{abi}, /data/config/{abi}) have been prepared by the user/administrator as part of system setup.

§Arguments
  • target_vfs - VfsManager to configure with overlay filesystem
  • base_vfs - Base VFS containing system and config directories
  • system_path - Path to read-only base layer (e.g., “/system/scarlet”)
  • config_path - Path to writable persistence layer (e.g., “/data/config/scarlet”)
Source

fn setup_shared_resources( &self, _target_vfs: &Arc<VfsManager>, _base_vfs: &Arc<VfsManager>, ) -> Result<(), &'static str>

Setup shared resources accessible across all ABIs

Bind mounts common directories that should be shared from base VFS. The TransparentExecutor is responsible for providing base_vfs.

§Arguments
  • target_vfs - VfsManager to configure
  • base_vfs - Base VFS containing shared directories
Source

fn handle_event( &self, _event: Event, _target_task_id: u32, ) -> Result<(), &'static str>

Handle incoming event from EventManager

This method is called when an event is delivered to a task using this ABI. Each ABI can implement its own event handling strategy:

  • Scarlet ABI: Handle-based queuing with EventSubscription objects
  • xv6 ABI: POSIX-like signals and pipe notifications
  • Other ABIs: Custom event processing mechanisms
§Arguments
  • event - The event to be delivered
  • target_task_id - ID of the task that should receive the event
§Returns
  • Ok(()) if the event was successfully handled
  • Err(message) if event delivery failed
Source

fn set_tls_pointer(&mut self, _ptr: usize)

Set the TLS (Thread Local Storage) pointer for this task

Default implementation does nothing - ABIs that support TLS should override this method.

Source

fn get_tls_pointer(&self) -> Option<usize>

Get the TLS (Thread Local Storage) pointer for this task

Default implementation returns None - ABIs that support TLS should override this method.

Source

fn set_clear_child_tid(&mut self, _ptr: usize)

Set the clear_child_tid pointer for thread exit notification

Default implementation does nothing - ABIs that support TLS should override this method.

Implementors§