implement more things

This commit is contained in:
nora 2023-10-07 21:50:57 +02:00
parent 119d0f1443
commit 9e2cf38cd5
11 changed files with 177 additions and 12 deletions

View file

@ -97,6 +97,50 @@ pub unsafe fn free(ptr: *mut u8) {
ALLOCATOR.dealloc(start, layout);
}
fn array_size(nmemb: usize, size: usize) -> Option<usize> {
let total = nmemb.checked_mul(size)?;
if total > (isize::MAX as usize) {
return None;
}
Some(total)
}
pub unsafe fn malloc_zeroed_array(nmemb: usize, size: usize, align: usize) -> *mut u8 {
let Some(total) = nmemb.checked_mul(size) else {
return core::ptr::null_mut();
};
if total > (isize::MAX as usize) {
return core::ptr::null_mut();
}
malloc_zeroed(total, align)
}
pub unsafe fn realloc(ptr: *mut u8, size: usize, align: usize) -> *mut u8 {
let new = malloc_zeroed(size, align);
if !new.is_null() {
core::ptr::copy_nonoverlapping(ptr, new, size);
}
free(ptr);
new
}
pub unsafe extern "C" fn reallocarray(
ptr: *mut u8,
nmemb: usize,
size: usize,
align: usize,
) -> *mut u8 {
let new = malloc_zeroed_array(size, size, align);
if !new.is_null() {
let Some(total) = array_size(nmemb, size) else {
return core::ptr::null_mut();
};
core::ptr::copy_nonoverlapping(ptr, new, total);
}
free(ptr);
new
}
#[cfg_attr(miri, allow(unused_variables, unreachable_code))]
pub unsafe fn sys_mmap(
addr: *const u8,

View file

@ -273,8 +273,8 @@ impl super::Error {
pub const HWPOISON: Self = Self(EHWPOISON);
pub const NOTSUP: Self = Self(ENOTSUP);
pub fn simple_str(self) -> &'static str {
match self {
pub fn simple_str(self) -> Option<&'static str> {
Some(match self {
Self::PERM => "EPERM",
Self::NOENT => "ENOENT",
Self::SRCH => "ESRCH",
@ -406,7 +406,7 @@ impl super::Error {
Self::NOTRECOVERABLE => "ENOTRECOVERABLE",
Self::RFKILL => "ERFKILL",
Self::HWPOISON => "EHWPOISON",
_ => "<invalid error>",
}
_ => return None,
})
}
}

View file

@ -20,12 +20,17 @@ pub fn set_errno(errno: i32) {
unsafe { ERRNO.0.get().write(errno) }
}
pub fn strerror(errnum: Error) -> Option<&'static str> {
errnum.simple_str()
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct Error(pub i32);
impl Debug for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(self.simple_str())
f.write_str(self.simple_str().unwrap_or("<error: invalid error>"))
}
}

View file

@ -39,13 +39,17 @@ pub use println;
use self::fd::Fd;
pub unsafe fn sys_write(fd: i32, buf: &[u8]) -> Result<usize, Error> {
syscall::syscall!(syscall::SYS_WRITE, fd, buf.as_ptr(), buf.len()).syscall_resultify()
pub unsafe fn sys_read(fd: Fd, buf: &mut [u8]) -> Result<usize, Error> {
syscall::syscall!(syscall::SYS_READ, fd.0, buf.as_ptr(), buf.len()).syscall_resultify()
}
pub unsafe fn sys_write(fd: Fd, buf: &[u8]) -> Result<usize, Error> {
syscall::syscall!(syscall::SYS_WRITE, fd.0, buf.as_ptr(), buf.len()).syscall_resultify()
}
pub unsafe fn write_all(fd: Fd, mut buf: &[u8]) -> Result<(), Error> {
while !buf.is_empty() {
let result = sys_write(fd.0, buf)?;
let result = sys_write(fd, buf)?;
buf = &buf[result..];
}
Ok(())

View file

@ -27,7 +27,7 @@ impl FileStream {
impl IoWrite for &FileStream {
fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
unsafe { super::sys_write(self.fd.0, buf) }
unsafe { super::sys_write(self.fd, buf) }
}
}

View file

@ -16,6 +16,31 @@ pub unsafe fn memcpy(dest: *mut u8, src: *const u8, size: usize) -> *mut u8 {
dest
}
#[inline]
pub unsafe fn memmove(dest: *mut u8, src: *const u8, size: usize) -> *mut u8 {
if dest as usize > src as usize {
// 1 2 3 4 5 6 7
// ^---- dest
// ^---- src
// We need to move backwards, first copying the 5 to 6, then 4 to 5 etc.
// Iterating fowards would overwrite 4 with 3 before we can copy 4.
for i in (0..size).rev() {
dest.add(i).write(src.add(i).read());
}
} else {
// 1 2 3 4 5 6 7
// ^---- dest
// ^---- src
// We need to move forwards from src. This way we never overwrite values
// before we would need to read them.
for i in 0..size {
dest.add(i).write(src.add(i).read());
}
}
dest
}
#[inline]
pub unsafe fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 {
for i in 0..size {
@ -56,6 +81,38 @@ mod tests {
assert_eq!(dest, src);
}
#[test]
fn memmove_null() {
unsafe { super::memmove(std::ptr::null_mut(), std::ptr::null_mut(), 0) };
}
#[test]
fn memmove_one_forwards() {
let mut arr = [1, 2, 3, 4, 5];
let src = arr.as_mut_ptr();
let dest = unsafe { src.add(1) };
unsafe { super::memmove(dest, src, 4) };
assert_eq!(arr, [1, 1, 2, 3, 4]);
}
#[test]
fn memmove_one_backwards() {
let mut arr = [1, 2, 3, 4, 5];
let src = unsafe { arr.as_mut_ptr().add(1) };
let dest = unsafe { src.sub(1) };
unsafe { super::memmove(dest, src, 4) };
assert_eq!(arr, [2, 3, 4, 5, 5]);
}
#[test]
fn memmove_full_overlap() {
let mut arr = [1, 2, 3, 4, 5];
let src = arr.as_mut_ptr();
let dest = src;
unsafe { super::memmove(src, dest, 4) };
assert_eq!(arr, [1, 2, 3, 4, 5]);
}
#[test]
fn memset_null() {
unsafe { super::memset(std::ptr::null_mut(), 0, 0) };

View file

@ -8,6 +8,7 @@ mod rt;
mod stdio;
mod stdlib;
mod string;
mod unistd;
// libcore seems to require this symbol, even though it's unused.
#[no_mangle]

View file

@ -2,9 +2,13 @@ use core::ffi::{c_int, c_long};
use libuwuc::{error::IntoOkOrErrno, utils::SharedThinCstr};
// Allocation functions
const MAX_ALIGN: usize = 16;
#[no_mangle]
pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 {
libuwuc::alloc::malloc_zeroed(size, 16)
libuwuc::alloc::malloc_zeroed(size, MAX_ALIGN)
}
#[no_mangle]
@ -13,10 +17,22 @@ pub unsafe extern "C" fn free(ptr: *mut u8) {
}
#[no_mangle]
pub unsafe extern "C" fn exit(code: i32) -> ! {
libuwuc::start::sys_exit(code as i64 as _)
pub unsafe extern "C" fn calloc(nmemb: usize, size: usize) -> *mut u8 {
libuwuc::alloc::malloc_zeroed_array(nmemb, size, MAX_ALIGN)
}
#[no_mangle]
pub unsafe extern "C" fn realloc(ptr: *mut u8, size: usize) -> *mut u8 {
libuwuc::alloc::realloc(ptr, size, MAX_ALIGN)
}
#[no_mangle]
pub unsafe extern "C" fn reallocarray(ptr: *mut u8, nmemb: usize, size: usize) -> *mut u8 {
libuwuc::alloc::reallocarray(ptr, nmemb, size, MAX_ALIGN)
}
// Integer parsing functions
#[no_mangle]
pub unsafe extern "C" fn strtol(nptr: *const u8, endptr: *mut *const u8, base: c_int) -> c_long {
let str = SharedThinCstr::from_raw(nptr);
@ -33,9 +49,16 @@ pub unsafe extern "C" fn strtoll(nptr: *const u8, endptr: *mut *const u8, base:
strtol(nptr, endptr, base)
}
// Other functions
#[no_mangle]
pub unsafe extern "C" fn getenv(name: *const u8) -> *const u8 {
libuwuc::env::getenv(SharedThinCstr::from_raw(name))
.map(SharedThinCstr::as_raw)
.unwrap_or(core::ptr::null())
}
#[no_mangle]
pub unsafe extern "C" fn exit(code: i32) -> ! {
libuwuc::start::sys_exit(code as i64 as _)
}

View file

@ -1,3 +1,5 @@
use libuwuc::error::Error;
#[no_mangle]
pub unsafe extern "C" fn memset(ptr: *mut u8, constant: u8, len: usize) {
libuwuc::mem::memset(ptr, constant, len)
@ -8,6 +10,11 @@ pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, size: usize) -> *
libuwuc::mem::memcpy(dest, src, size)
}
#[no_mangle]
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, size: usize) -> *mut u8 {
libuwuc::mem::memmove(dest, src, size)
}
#[no_mangle]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 {
libuwuc::mem::memcmp(s1, s2, size)
@ -22,3 +29,10 @@ pub unsafe extern "C" fn bcmp(s1: *const u8, s2: *const u8, size: usize) -> i32
pub unsafe extern "C" fn strlen(s: *const u8) -> usize {
libuwuc::mem::strlen(s)
}
#[no_mangle]
pub unsafe extern "C" fn strerror(errnum: Error) -> *const u8 {
libuwuc::error::strerror(errnum)
.map(str::as_ptr)
.unwrap_or(core::ptr::null())
}

16
rawc/src/unistd.rs Normal file
View file

@ -0,0 +1,16 @@
use libuwuc::error::IntoOkOrErrno;
use libuwuc::io::fd::Fd;
#[no_mangle]
pub unsafe extern "C" fn read(fd: Fd, buf: *mut u8, count: usize) -> isize {
libuwuc::io::sys_read(fd, core::slice::from_raw_parts_mut(buf, count))
.map(|n| n as isize)
.into_ok_or_errno()
}
#[no_mangle]
pub unsafe extern "C" fn write(fd: Fd, buf: *const u8, count: usize) -> isize {
libuwuc::io::sys_write(fd, core::slice::from_raw_parts(buf, count))
.map(|n| n as isize)
.into_ok_or_errno()
}

View file

@ -15,3 +15,4 @@ ensure_cloned() {
}
ensure_cloned "https://github.com/tsoding/noed.git" "tsoding_noed" "1c2bd182139080a8448a59589e8d457a7019d553"
ensure_cloned "https://github.com/zesterer/tosh.git" "zest_tosh" "fa43ee9ec01a625f6a96cb48662f6c8911d8cc8c"