abi: update abi docs

This commit is contained in:
Mark Poliakov 2025-01-06 18:33:35 +02:00
parent 34a5f4f0d8
commit 86f4a3f214
13 changed files with 130 additions and 12 deletions

View File

@ -18,7 +18,7 @@ pub struct DebugOptions {
impl Default for DebugOptions {
fn default() -> Self {
Self {
serial_level: LogLevel::Info,
serial_level: LogLevel::Debug, // LogLevel::Info,
display_level: LogLevel::Info,
disable_program_trace: false,
}

View File

@ -1,5 +1,7 @@
//! Architecture-specific ABI implementation details
#![allow(missing_docs)]
#[cfg(target_arch = "aarch64")]
pub(crate) mod aarch64;
#[cfg(target_arch = "aarch64")]

View File

@ -1,39 +1,61 @@
//! Debugging functionality
use crate::{arch::SavedFrame, io::RawFd};
/// Describes a debugger operation
#[derive(Debug)]
pub enum DebugOperation<'a> {
/// Attach to a given process
Attach(RawFd),
/// Detach from the current process
Detach,
/// Send an interrupt to the debugee
Interrupt,
/// Continue the debugee, `Continue(true)` represents a "single step"
Continue(bool),
/// Set a breakpoint at a given address
SetBreakpoint(usize),
/// Read data from the debugee memory
ReadMemory {
/// Address to read the data from
address: usize,
/// Buffer to place the result into
buffer: &'a mut [u8],
},
/// Write data to the debugee memory
WriteMemory {
/// Address to write the data to
address: usize,
/// Buffer to read the data from
buffer: &'a [u8],
},
}
// TODO fill this
/// Represents a debug event
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug)]
pub enum DebugFrame {
/// The debugee has started
Startup {
/// The address at which the process image is loaded
image_base: usize,
/// The address by which the instruction pointer is offset (when ASLR is in effect)
ip_offset: usize,
/// Current instruction pointer
ip: usize,
},
/// The debugee has completed a single instruction step
Step {
/// Current process state
frame: SavedFrame,
},
/// The debugee has hit a breakpoint
HitBreakpoint {
/// Current process state
frame: SavedFrame,
},
// TODO exit status
/// The debugee has exited
Exited,
}

View File

@ -1,3 +1,4 @@
//! Message channel handling
use abi_lib::SyscallRegister;
pub use crate::generated::ChannelPublisherId;
@ -56,5 +57,6 @@ impl SyscallRegister for MessageDestination {
}
impl ChannelPublisherId {
/// NULL publisher ID, usually represents the publisher which opened the channel
pub const ZERO: Self = Self(0);
}

View File

@ -4,12 +4,17 @@ use crate::generated::ProcessGroupId;
use super::terminal;
/// Represents a video device framebuffer
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct Framebuffer {
/// Width in pixels
pub width: u32,
/// Height in pixels
pub height: u32,
/// Amount of bytes to add to move from one row to the next
pub stride: usize,
/// Size of the framebuffer in bytes
pub size: usize,
}

View File

@ -1,5 +1,8 @@
//! Filesystem management functions and structures
/// Describes an action performed on a filesystem
#[derive(Debug)]
pub enum FilesystemControl {
/// Flushes the filesystem cache
FlushCache,
}

View File

@ -1,3 +1,5 @@
//! I/O-related definitions
mod channel;
mod device;
mod file;
@ -21,35 +23,45 @@ pub use terminal::{
TerminalOutputOptions, TerminalSize,
};
/// Describes a rename/move operation
#[derive(Clone, Debug)]
pub struct Rename<'a> {
/// Where to look the source path at
pub source_at: Option<RawFd>,
/// Source path
pub source: &'a str,
/// Where to look the destination path at
pub destination_at: Option<RawFd>,
/// Destination path
pub destination: &'a str,
}
impl UserId {
/// Returns the `root` user ID
pub const fn root() -> Self {
Self(0)
}
/// Returns `true` if the user ID represents a root user
pub const fn is_root(&self) -> bool {
self.0 == 0
}
}
impl GroupId {
/// Returns the `root` group ID
pub const fn root() -> Self {
Self(0)
}
/// Returns `true` if the group ID represents a root user
pub const fn is_root(&self) -> bool {
self.0 == 0
}
}
impl FileMode {
/// Constructs a file mode from a raw [u32]
pub const fn new(value: u32) -> Self {
Self(value)
}
@ -66,12 +78,16 @@ impl FileMode {
}
impl RawFd {
/// Default stdin file descriptor
pub const STDIN: Self = Self(0);
/// Default stdout file descriptor
pub const STDOUT: Self = Self(1);
/// Default stderr file descriptor
pub const STDERR: Self = Self(2);
}
impl OpenOptions {
/// Empty set of open options
pub const fn default() -> Self {
Self(0)
}

View File

@ -8,8 +8,7 @@
stable_features
)]
#![feature(trace_macros, const_trait_impl, inline_const_pat, ip_in_core)]
// TODO temporary
#![allow(missing_docs)]
#![warn(missing_docs)]
#[cfg(all(any(feature = "alloc", test), not(feature = "rustc-dep-of-std")))]
extern crate alloc;
@ -21,13 +20,18 @@ pub(crate) mod macros;
pub mod util;
mod generated {
#![allow(missing_docs)]
use crate::{arch::SavedFrame, process::SpawnOption, util::FixedString};
include!(concat!(env!("OUT_DIR"), "/generated_types.rs"));
}
pub mod error {
//! Error type used by the ABI functions/kernel/runtime
pub use crate::generated::Error;
// TODO have syscall-generator implement TryFrom<#repr> for #enum
}

View File

@ -25,6 +25,7 @@ impl ExitCode {
matches!(self, Self::Exited(0))
}
/// Returns `Some(...)` if the [ExitCode] represents a process killed by a signal
pub fn signal(&self) -> Option<Result<Signal, u32>> {
match self {
Self::BySignal(sig) => Some(*sig),

View File

@ -19,6 +19,9 @@ pub use thread::ThreadOption;
// TODO this is ugly
pub mod auxv {
#![allow(missing_docs)]
//! Auxiliary values passed to the executable
pub const TLS_MASTER_COPY: u64 = 0x80;
pub const TLS_FULL_SIZE: u64 = 0x81;
pub const TLS_DATA_SIZE: u64 = 0x82;
@ -32,38 +35,44 @@ pub mod auxv {
pub const NULL: u64 = 0x00;
}
/// Represents a process/group object to wait on
#[derive(Debug)]
pub enum ProcessWait {
/// Wait for a specific process
Process(ProcessId),
/// Wait for any process in a group
Group(ProcessGroupId),
/// Wait for any child process
AnyChild,
}
/// Represents a process option being set/retrieved
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum ProcessOption {
/// Signal entry point address
SignalEntry(usize),
/// Current working directory
Directory(FixedString<4096>),
}
/// Defines an optional argument for controlling process creation
#[derive(Debug)]
pub enum SpawnOption {
/// Copy a file descriptor into the child process and close it in the parent
MoveFile {
/// Parent file descriptor
source: RawFd,
/// Child file descriptor
child: RawFd,
},
/// Copy a file descriptor into the child process
CopyFile {
/// Parent file descriptor
source: RawFd,
/// Child file descriptor
child: RawFd,
},
// /// Indicates a new process should inherit a file descriptor from its creator
// InheritFile {
// /// FD on the creator side
// source: RawFd,
// /// What FD number should be used in the child
// child: RawFd,
// },
/// The new process should be placed in the specified group
SetProcessGroup(ProcessGroupId),
/// Gain terminal control for the given FD
@ -96,33 +105,43 @@ pub enum ProcessInfoElement {
Umask(FileMode),
}
/// Process auxiliary value
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct AuxValue {
/// Tag part
pub tag: u64,
/// Value part
pub val: u64,
}
/// An iterator over string-like arguments
#[derive(Clone, Copy)]
pub struct StringArgIter<'a> {
ptr: *const *const u8,
_pd: PhantomData<&'a ProgramArgumentInner>,
}
/// An iterator over auxiliary values
#[derive(Clone, Copy)]
pub struct AuxValueIter<'a> {
ptr: *const AuxValue,
_pd: PhantomData<&'a ProgramArgumentInner>,
}
/// An argument passed from the kernel/loader to the executable
#[repr(C)]
pub struct ProgramArgumentInner {
/// Argument list
pub args: *const *const u8,
/// Environment variable list
pub envs: *const *const u8,
/// Auxiliary value list
pub auxv: *const AuxValue,
}
impl ProcessId {
/// Zero PID
pub const ZERO: Self = Self(0);
}
@ -172,6 +191,7 @@ impl<'a> Iterator for AuxValueIter<'a> {
}
impl ProgramArgumentInner {
/// Returns an iterator over the arguments
pub fn args(&self) -> impl Iterator<Item = &CStr> {
StringArgIter {
ptr: self.args,
@ -179,6 +199,7 @@ impl ProgramArgumentInner {
}
}
/// Returns an iterator over the environment variables
pub fn envs(&self) -> impl Iterator<Item = &CStr> {
StringArgIter {
ptr: self.envs,
@ -186,6 +207,7 @@ impl ProgramArgumentInner {
}
}
/// Returns an iterator over the auxiliary values
pub fn auxv(&self) -> impl Iterator<Item = &AuxValue> {
AuxValueIter {
ptr: self.auxv,
@ -195,10 +217,12 @@ impl ProgramArgumentInner {
}
impl Signal {
/// Returns `true` if the signal is delivered in synchronous fashion
pub fn is_synchronous(&self) -> bool {
matches!(self, Self::MemoryAccessViolation)
}
/// Returns `true` if the signal can be handled by an userspace process
pub fn is_handleable(&self) -> bool {
!matches!(self, Self::Killed)
}

View File

@ -1,6 +1,12 @@
//! Thread data structures
/// Represents a thread option being set/retrieved
#[derive(Debug)]
pub enum ThreadOption<'a> {
/// Thread-local storage base pointer
ThreadPointer(usize),
/// Thread signal entry stack base and size
SignalStack(usize, usize),
/// Thread display name
Name(&'a str),
}

View File

@ -1,3 +1,4 @@
//! Time handling structures and functions
use core::{
ops::{Add, Sub},
time::Duration,
@ -5,19 +6,26 @@ use core::{
use abi_lib::SyscallRegister;
/// Number of nanoseconds in each second
pub const NANOSECONDS_IN_SECOND: u64 = 1_000_000_000;
/// Number of microseconds in each second
pub const MICROSECONDS_IN_SECOND: u64 = 1_000_000;
/// Number of milliseconds in each second
pub const MILLISECONDS_IN_SECOND: u64 = 1_000;
/// Represents a point of time as measured by some system clock
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SystemTime {
seconds: u64,
nanoseconds: u64,
}
/// Represents a certain clock type
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ClockType {
/// Monotonically increasing clock since some arbitrary point in the past
Monotonic,
/// "Real-world" clock, subject to jumps
RealTime,
}
@ -39,11 +47,19 @@ impl SyscallRegister for ClockType {
}
impl SystemTime {
/// Zero time, also represents UNIX Epoch for real-world clocks
pub const ZERO: Self = Self {
seconds: 0,
nanoseconds: 0,
};
/// Constructs a new [SystemTime] from seconds and nanoseconds, without performing
/// any adjustments.
///
/// # Safety
///
/// The caller must guarantee the `nanoseconds` value does not violate the invariant that
/// `nanoseconds` is less than [NANOSECONDS_IN_SECOND].
pub unsafe fn new_unchecked(seconds: u64, nanoseconds: u64) -> Self {
Self {
seconds,
@ -51,10 +67,18 @@ impl SystemTime {
}
}
/// Constructs a new [SystemTime] from seconds and nanoseconds. If `nanoseconds` contains extra
/// full seconds, those are converted to seconds (i.e. the time is "normalized").
///
/// # Panics
///
/// This function will panic if the conversion result overflows [u64] in the `seconds` field.
pub fn new(seconds: u64, nanoseconds: u64) -> Self {
Self::new_opt(seconds, nanoseconds).unwrap()
}
/// Constructs a new [SystemTime] from seconds and nanoseconds. This function returns `None` if
/// conversion fails. See [SystemTime::new].
pub fn new_opt(mut seconds: u64, nanoseconds: u64) -> Option<Self> {
seconds = seconds.checked_add(nanoseconds / NANOSECONDS_IN_SECOND)?;
Some(Self {
@ -63,6 +87,7 @@ impl SystemTime {
})
}
/// Constructs a [SystemTime] from seconds part only
pub fn from_seconds(seconds: u64) -> Self {
Self {
seconds,
@ -70,21 +95,25 @@ impl SystemTime {
}
}
/// Returns the number of full milliseconds represented by this structure
pub fn as_millis(&self) -> u128 {
(self.seconds as u128 * MILLISECONDS_IN_SECOND as u128)
+ (self.nanoseconds as u128 / 1000000)
}
/// Returns the number of sub-second nanoseconds
#[inline(always)]
pub fn subsec_nanos(&self) -> u64 {
self.nanoseconds
}
/// Returns the number of full seconds
#[inline(always)]
pub fn seconds(&self) -> u64 {
self.seconds
}
/// Adds a [Duration] to this [SystemTime], returns `None` if the addition overflows
pub fn checked_add_duration(&self, other: &Duration) -> Option<Self> {
let nanoseconds = self.nanoseconds.checked_add(other.subsec_nanos() as u64)?;
let seconds = nanoseconds / NANOSECONDS_IN_SECOND;
@ -100,6 +129,7 @@ impl SystemTime {
})
}
/// Subtracts a [Duration] from this [SystemTime], returns `None` if the subtraction underflows
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Self> {
let mut seconds = self.seconds.checked_sub(other.as_secs())?;
let nanoseconds = if self.nanoseconds < other.subsec_nanos() as u64 {
@ -115,6 +145,8 @@ impl SystemTime {
})
}
/// Subtracts two [SystemTime]s, returns `Ok(self - other)` if `self >= other`,
/// `Err(other - self)` otherwise.
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
if self >= other {
Ok(self.checked_sub_time(other).unwrap())
@ -126,6 +158,7 @@ impl SystemTime {
}
}
/// Subtracts two [SystemTime]s, returns `None` if the subtraction underflows
pub fn checked_sub_time(&self, other: &SystemTime) -> Option<Duration> {
let mut seconds = self.seconds.checked_sub(other.seconds)?;
let nanoseconds = if self.nanoseconds < other.nanoseconds {

View File

@ -8,7 +8,7 @@
thread_local
)]
#![no_std]
#![deny(missing_docs)]
#![warn(missing_docs)]
#![allow(nonstandard_style, clippy::new_without_default)]
// #[cfg(not(feature = "rustc-dep-of-std"))]