From 0c69d7db10e289a24fbc2f71a5867e010938d1b4 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 29 Sep 2023 22:20:14 +0200 Subject: [PATCH] reading env vars --- example-user/src/main.rs | 10 +++++-- src/basic_mem.rs | 10 +++++++ src/env.rs | 59 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ src/start.rs | 18 +++++++----- src/sys/x86_64/start.rs | 10 ++----- src/utils/mod.rs | 28 +++++++++++++++++++ 7 files changed, 121 insertions(+), 16 deletions(-) create mode 100644 src/env.rs create mode 100644 src/utils/mod.rs diff --git a/example-user/src/main.rs b/example-user/src/main.rs index e13e9fd..06d1cda 100644 --- a/example-user/src/main.rs +++ b/example-user/src/main.rs @@ -1,3 +1,4 @@ +#![feature(panic_info_message)] #![cfg_attr(not(test), no_std)] #![no_main] @@ -9,8 +10,13 @@ extern crate libuwuc; #[panic_handler] #[cfg(not(test))] -fn handler(_arg: &core::panic::PanicInfo) -> ! { - libuwuc::io::println!("panic!"); +fn handler(arg: &core::panic::PanicInfo) -> ! { + let args = format_args!(""); + let payload = arg.message().unwrap_or(&args); + libuwuc::io::println!("panicked: {payload}"); + if let Some(loc) = arg.location() { + libuwuc::io::println!(" at {}:{}:{}", loc.file(), loc.line(), loc.column()); + } libuwuc::start::exit(1); } diff --git a/src/basic_mem.rs b/src/basic_mem.rs index 3e73d2a..369ea26 100644 --- a/src/basic_mem.rs +++ b/src/basic_mem.rs @@ -6,3 +6,13 @@ pub(crate) unsafe extern "C" fn memset(ptr: *mut u8, constant: u8, len: usize) { } } } + +#[no_mangle] +pub(crate) unsafe extern "C" fn strlen(mut s: *const u8) -> usize { + let mut len = 0; + while s.read() != 0 { + len += 1; + s = s.add(1); + } + len +} diff --git a/src/env.rs b/src/env.rs new file mode 100644 index 0000000..c6ecd67 --- /dev/null +++ b/src/env.rs @@ -0,0 +1,59 @@ +use core::ffi::CStr; + +use crate::{println, utils::SharedThinCstr}; + +mod global { + use core::cell::UnsafeCell; + + use crate::utils::{SharedThinCstr, SyncUnsafeCell}; + + use super::EnvP; + + static ENVP: SyncUnsafeCell = + SyncUnsafeCell(UnsafeCell::new(EnvP(core::ptr::null_mut()))); + + pub(super) unsafe fn init(envp: *mut SharedThinCstr) { + assert!((*ENVP.0.get()).0.is_null()); + *ENVP.0.get() = EnvP(envp); + } + + pub(super) fn get() -> EnvP { + let ptr = unsafe { *ENVP.0.get() }; + assert!(!ptr.0.is_null()); + ptr + } +} + +pub(crate) unsafe fn init(envp: *mut SharedThinCstr) { + global::init(envp); +} + +#[derive(Clone, Copy)] +struct EnvP(*mut SharedThinCstr); + +unsafe impl Sync for EnvP {} + +impl Iterator for EnvP { + type Item = SharedThinCstr; + + fn next(&mut self) -> Option { + unsafe { + let value: SharedThinCstr = self.0.read(); + if value.0.is_null() { + None + } else { + self.0 = self.0.add(1); + Some(value) + } + } + } +} + +pub(crate) fn debug_env() { + println!("start vars"); + global::get().for_each(|s| { + let str = <&CStr>::from(s).to_str().unwrap(); + println!("{str}"); + }); + println!("end vars"); +} diff --git a/src/lib.rs b/src/lib.rs index 2390d0a..4341d02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,10 +2,12 @@ #![warn(unreachable_pub)] mod basic_mem; +mod env; pub mod io; pub mod start; mod stubs; mod sys; +mod utils; pub mod syscall { pub use crate::sys::syscall::*; diff --git a/src/start.rs b/src/start.rs index a5ef808..ba46dac 100644 --- a/src/start.rs +++ b/src/start.rs @@ -1,18 +1,22 @@ use core::ffi::{c_char, c_int}; +use crate::utils::SharedThinCstr; + /// The entrypoint of the program. /// This is called by a bit of assembly handling architecture-specific _start. -pub(crate) unsafe extern "C" fn start( - argc: i32, - argv: *const *const c_char, - _envp: *const *const c_char, -) -> ! { +pub(crate) unsafe extern "C" fn start(argc: u64, argv: *const *const c_char, rsp: u64) -> ! { + let envp = (8 + 8 * argc + rsp + 8) as *mut SharedThinCstr; + + crate::env::init(envp); + extern "C" { fn main(argc: c_int, argv: *const *const c_char) -> c_int; } - let result = main(argc, argv); - + crate::env::debug_env(); + + let result = main(argc as i32, argv); + exit(result as u64); } diff --git a/src/sys/x86_64/start.rs b/src/sys/x86_64/start.rs index 7c1ba43..777e1b0 100644 --- a/src/sys/x86_64/start.rs +++ b/src/sys/x86_64/start.rs @@ -10,16 +10,12 @@ core::arch::global_asm!( // Pass the variables to the start function arguments. "mov rdi, [rsp]", // &argc = rsp "mov rsi, [rsp+8]", // &argv = rsp+8 - - "mov rdx, rdi", // &envp = rsp+8*argc+8 - "mov rax, 8", - "mul rdx", - "add rdx, 8", - "add rdx, rsp", - "mov rdx, [rdx]", // &envp = rsp+8*argc+8 + "mov rdx, rsp", // The stack will be 16-byte aligned at process entry already. // So we're good to go! "call {start}", + // Our start never returns, but just to be sure... + "ud2", start = sym crate::start::start ); diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..280b7c5 --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1,28 @@ +use core::{ + cell::UnsafeCell, + ffi::{c_char, CStr}, +}; + +#[repr(transparent)] +#[derive(Default)] +pub(crate) struct SyncUnsafeCell(pub(crate) UnsafeCell); + +unsafe impl Sync for SyncUnsafeCell {} + +#[repr(transparent)] +pub(crate) struct SharedThinCstr(pub(crate) *const c_char); + +unsafe impl Send for SharedThinCstr {} +unsafe impl Sync for SharedThinCstr {} + +impl From for &CStr { + fn from(value: SharedThinCstr) -> Self { + unsafe { CStr::from_ptr(value.0) } + } +} + +#[repr(transparent)] +pub(crate) struct SyncPtr(pub(crate) *mut T); + +unsafe impl Send for SyncPtr {} +unsafe impl Sync for SyncPtr {}