102 lines
2.6 KiB
Rust
102 lines
2.6 KiB
Rust
use bytemuck::Pod;
|
|
use yggdrasil_rt::{
|
|
mem::MappingFlags,
|
|
process::{auxv, AuxValue},
|
|
};
|
|
|
|
use crate::{error::Error, mapping::Mapping};
|
|
|
|
struct ArgPlacer<'a> {
|
|
buffer: &'a mut [u8],
|
|
position: usize,
|
|
}
|
|
|
|
impl<'a> ArgPlacer<'a> {
|
|
fn new(buffer: &'a mut [u8]) -> Self {
|
|
Self {
|
|
buffer,
|
|
position: 0,
|
|
}
|
|
}
|
|
|
|
fn align(&mut self, align: usize) -> Result<(), Error> {
|
|
debug_assert!(align.is_power_of_two());
|
|
let aligned = (self.position + align - 1) & !(align - 1);
|
|
if aligned > self.buffer.len() {
|
|
todo!()
|
|
}
|
|
self.position = aligned;
|
|
Ok(())
|
|
}
|
|
|
|
fn put_str(&mut self, s: &str) -> Result<usize, Error> {
|
|
if self.position + s.len() >= self.buffer.len() {
|
|
todo!()
|
|
}
|
|
let off = self.position;
|
|
self.buffer[off..off + s.len()].copy_from_slice(s.as_bytes());
|
|
self.buffer[off + s.len()] = 0;
|
|
self.position += s.len() + 1;
|
|
Ok(off)
|
|
}
|
|
|
|
fn put<T: Pod>(&mut self, v: &T) -> Result<usize, Error> {
|
|
if self.position + size_of::<T>() > self.buffer.len() {
|
|
todo!()
|
|
}
|
|
let off = self.position;
|
|
self.buffer[off..off + size_of::<T>()].copy_from_slice(bytemuck::bytes_of(v));
|
|
self.position += size_of::<T>();
|
|
Ok(off)
|
|
}
|
|
|
|
fn put_aux_array(&mut self, s: &[AuxValue]) -> Result<usize, Error> {
|
|
self.align(size_of::<u64>())?;
|
|
let off = self.position;
|
|
for item in s {
|
|
self.put(&item.tag)?;
|
|
self.put(&item.val)?;
|
|
}
|
|
self.put(&auxv::NULL)?;
|
|
self.put(&0u64)?;
|
|
Ok(off)
|
|
}
|
|
|
|
fn put_ptr_array(&mut self, s: &[usize]) -> Result<usize, Error> {
|
|
self.align(size_of::<usize>())?;
|
|
let off = self.position;
|
|
for item in s {
|
|
self.put(item)?;
|
|
}
|
|
self.put(&0usize)?;
|
|
Ok(off)
|
|
}
|
|
}
|
|
|
|
pub fn build_argument(args: &[String], auxv: &[AuxValue]) -> Result<usize, Error> {
|
|
let mut buffer = Mapping::new(0x1000, MappingFlags::WRITE)?;
|
|
let arg_base = buffer.as_ptr().addr();
|
|
let mut placer = ArgPlacer::new(&mut buffer[..]);
|
|
|
|
let mut argv = vec![];
|
|
|
|
for arg in args {
|
|
argv.push(placer.put_str(arg)? + arg_base);
|
|
}
|
|
|
|
// TODO env
|
|
let argv = placer.put_ptr_array(&argv)? + arg_base;
|
|
let envp = placer.put_ptr_array(&[])? + arg_base;
|
|
let auxv = placer.put_aux_array(auxv)? + arg_base;
|
|
|
|
let argument = placer.position + arg_base;
|
|
|
|
placer.put(&argv)?;
|
|
placer.put(&envp)?;
|
|
placer.put(&auxv)?;
|
|
|
|
buffer.leak();
|
|
|
|
Ok(argument)
|
|
}
|