reading env vars

This commit is contained in:
nora 2023-09-29 22:20:14 +02:00
parent ddba35d06b
commit 0c69d7db10
7 changed files with 121 additions and 16 deletions

View file

@ -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!("<no message>");
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);
}

View file

@ -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
}

59
src/env.rs Normal file
View file

@ -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<EnvP> =
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<Self::Item> {
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");
}

View file

@ -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::*;

View file

@ -1,17 +1,21 @@
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);
}

View file

@ -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
);

28
src/utils/mod.rs Normal file
View file

@ -0,0 +1,28 @@
use core::{
cell::UnsafeCell,
ffi::{c_char, CStr},
};
#[repr(transparent)]
#[derive(Default)]
pub(crate) struct SyncUnsafeCell<T>(pub(crate) UnsafeCell<T>);
unsafe impl<T: Sync> Sync for SyncUnsafeCell<T> {}
#[repr(transparent)]
pub(crate) struct SharedThinCstr(pub(crate) *const c_char);
unsafe impl Send for SharedThinCstr {}
unsafe impl Sync for SharedThinCstr {}
impl From<SharedThinCstr> for &CStr {
fn from(value: SharedThinCstr) -> Self {
unsafe { CStr::from_ptr(value.0) }
}
}
#[repr(transparent)]
pub(crate) struct SyncPtr<T>(pub(crate) *mut T);
unsafe impl<T> Send for SyncPtr<T> {}
unsafe impl<T> Sync for SyncPtr<T> {}