diff --git a/src/lib.rs b/src/lib.rs index ecb8d54f..bf98de9f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,12 +56,52 @@ unsafe extern "C" fn memcmp(p0: *const c_void, p1: *const c_void, len: usize) -> #[no_mangle] unsafe extern "C" fn memcpy(p0: *mut c_void, p1: *const c_void, len: usize) -> *mut c_void { - compiler_builtins::mem::memcpy(p0 as _, p1 as _, len) as _ + #[cfg(feature = "rustc-dep-of-std")] + { + compiler_builtins::mem::memcpy(p0 as _, p1 as _, len) as _ + } + #[cfg(not(feature = "rustc-dep-of-std"))] + { + let mut i = 0; + while i < len { + *(p0 as *mut u8).add(i) = *(p1 as *const u8).add(i); + i += 1; + } + p0 + } } #[no_mangle] -unsafe extern "C" fn memmove(dst: *mut c_void, src: *const c_void, len: usize) -> *mut c_void { - compiler_builtins::mem::memmove(dst as _, src as _, len) as _ +unsafe extern "C" fn memmove(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void { + #[cfg(feature = "compiler_builtins")] + { + compiler_builtins::mem::memmove(dst as _, src as _, len) as _ + } + #[cfg(not(feature = "compiler_builtins"))] + { + let dst = dst as usize; + let src = src as usize; + + if dst == src { + return dst as _; + } + + if src + n <= dst || dst + n <= src { + return memcpy(dst as _, src as _, n); + } + + if dst < src { + let a = src - dst; + memcpy(dst as _, src as _, a); + memcpy(src as _, (src + a) as _, n - a); + } else { + let a = dst - src; + memcpy((dst + a) as _, dst as _, n - a); + memcpy(dst as _, src as _, a); + } + + dst as _ + } } #[no_mangle] @@ -75,6 +115,14 @@ unsafe extern "C" fn memset(dst: *mut c_void, val: i32, len: usize) -> *mut c_vo } #[no_mangle] -unsafe extern "C" fn strlen(_s: *mut c_char) -> usize { - todo!() +unsafe extern "C" fn strlen(mut s: *mut c_char) -> usize { + if s.is_null() { + return 0; + } + let mut len = 0; + while s.read() != 0 { + len += 1; + s = s.add(1); + } + len } diff --git a/src/process.rs b/src/process.rs index 29a2085c..9e97814b 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,6 +1,6 @@ //! Process management data types pub use abi::process::{ - ExitCode, MutexOperation, ProgramArgumentInner, Signal, SignalEntryData, SpawnOption, - SpawnOptions, ThreadSpawnOptions, + ExecveOptions, ExitCode, MutexOperation, ProgramArgumentInner, Signal, SignalEntryData, + SpawnOption, SpawnOptions, ThreadSpawnOptions, }; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index e6c419cb..5c776811 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -11,7 +11,8 @@ use abi::{ }, mem::MappingSource, process::{ - ExitCode, MutexOperation, Signal, SignalEntryData, SpawnOptions, ThreadSpawnOptions, + ExecveOptions, ExitCode, MutexOperation, Signal, SignalEntryData, SpawnOptions, + ThreadSpawnOptions, }, syscall::SyscallFunction, }; @@ -626,3 +627,44 @@ pub unsafe fn create_pty( argp!(fds as *mut _) )) } + +/// System call: clone a file descriptor into target (if provided) or some free slot (in not +/// specified). +/// +/// # Safety +/// +/// Unsafe: direct system call. +pub unsafe fn clone_fd(source: RawFd, target: Option) -> Result { + let target = target.unwrap_or(RawFd::NONE).0; + RawFd::from_syscall_result(syscall!( + SyscallFunction::CloneFd, + argn!(source.0 as usize), + argn!(target as usize) + )) +} + +/// System call: create an exact copy of the process and return its PID. +/// +/// # Note +/// +/// This system call is part of C compatability functions. +/// +/// # Safety +/// +/// Unsafe: direct system call. +pub unsafe fn fork() -> Result { + u32::from_syscall_result(syscall!(SyscallFunction::Fork)) +} + +/// System call: load a program into the current process address space. +/// +/// # Note +/// +/// This system call is part of C compatability functions. +/// +/// # Safety +/// +/// Unsafe: direct system call. +pub unsafe fn execve(opts: &ExecveOptions) -> Result<(), Error> { + <()>::from_syscall_result(syscall!(SyscallFunction::Exec, argp!(opts as *const _))) +} diff --git a/src/sys/x86_64.rs b/src/sys/x86_64.rs index 65800f20..99df98c1 100644 --- a/src/sys/x86_64.rs +++ b/src/sys/x86_64.rs @@ -3,7 +3,19 @@ macro_rules! syscall { ($num:expr) => {{ let mut res = usize::from($num); - core::arch::asm!("syscall", inlateout("rax") res); + core::arch::asm!( + "syscall", + inlateout("rax") res, + out("rdi") _, + out("rsi") _, + out("rdx") _, + out("r10") _, + out("r8") _, + out("r9") _, + // Clobbered by syscall + out("rcx") _, + out("r11") _, + ); res }}; ($num:expr, $a0:expr) => {{ @@ -11,7 +23,15 @@ macro_rules! syscall { core::arch::asm!( "syscall", inlateout("rax") res, - in("rdi") $a0 + in("rdi") $a0, + out("rsi") _, + out("rdx") _, + out("r10") _, + out("r8") _, + out("r9") _, + // Clobbered by syscall + out("rcx") _, + out("r11") _, ); res }}; @@ -21,7 +41,14 @@ macro_rules! syscall { "syscall", inlateout("rax") res, in("rdi") $a0, - in("rsi") $a1 + in("rsi") $a1, + out("rdx") _, + out("r10") _, + out("r8") _, + out("r9") _, + // Clobbered by syscall + out("rcx") _, + out("r11") _, ); res }}; @@ -32,7 +59,13 @@ macro_rules! syscall { inlateout("rax") res, in("rdi") $a0, in("rsi") $a1, - in("rdx") $a2 + in("rdx") $a2, + out("r10") _, + out("r8") _, + out("r9") _, + // Clobbered by syscall + out("rcx") _, + out("r11") _, ); res }}; @@ -44,7 +77,12 @@ macro_rules! syscall { in("rdi") $a0, in("rsi") $a1, in("rdx") $a2, - in("r10") $a3 + in("r10") $a3, + out("r8") _, + out("r9") _, + // Clobbered by syscall + out("rcx") _, + out("r11") _, ); res }}; @@ -57,7 +95,11 @@ macro_rules! syscall { in("rsi") $a1, in("rdx") $a2, in("r10") $a3, - in("r8") $a4 + in("r8") $a4, + out("r9") _, + // Clobbered by syscall + out("rcx") _, + out("r11") _, ); res }};