diff --git a/Cargo.toml b/Cargo.toml index 9a9ee00..1676e3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,5 @@ log = "0.4" critical-section = { version = "1", features = ["restore-state-bool"] } bffs = { path = "../../../code/bffs", features = ["alloc"] } shared = { path = "crates/shared" } +# ELF parsing helper +goblin = { version = "0.7", default-features = false, features = ["elf32", "elf64", "endian_fd"] } diff --git a/crates/os-std/src/lib.rs b/crates/os-std/src/lib.rs index c821822..6d7f864 100644 --- a/crates/os-std/src/lib.rs +++ b/crates/os-std/src/lib.rs @@ -20,7 +20,6 @@ macro_rules! custom_std_setup { unsafe impl core::alloc::GlobalAlloc for GlobalAllocator { unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { - syscall::write_string_temp("Alloc user called"); $crate::syscall::alloc(layout) } @@ -51,11 +50,11 @@ macro_rules! print { #[macro_export] macro_rules! println { () => { - // $crate::print!(""); - $crate::print!("\n\r"); + $crate::print!(""); + // $crate::print!("\n\r"); }; ($($args:expr),*) => { $crate::print!($($args),*); - $crate::println!(); + // $crate::println!(); }; } diff --git a/justfile b/justfile index f1880fe..4116fe9 100644 --- a/justfile +++ b/justfile @@ -12,11 +12,11 @@ sync_filesystem: sync build_user_prog prog: - RUSTFLAGS="-C relocation-model=pic -C link-arg=-Tuser.ld" cargo b {{ cargo_flags }} --package {{ prog }} - # cp {{ bin_path / prog }} {{ "mnt/usr/bin" / prog }} - riscv64-elf-objcopy -O binary {{ bin_path / prog }} {{ "mnt/usr/bin" / prog }} + RUSTFLAGS="-C relocation-model=pic -C link-arg=-Tuser.ld -C link-arg=-pie" cargo b {{ cargo_flags }} --package {{ prog }} + cp {{ bin_path / prog }} {{ "mnt/usr/bin" / prog }} + # riscv64-elf-objcopy -O binary {{ bin_path / prog }} {{ "mnt/usr/bin" / prog }} -build: mount_filesystem (map_dir "user" "build_user_prog") +build: mount_filesystem (map_dir "user" f"just cargo_flags=\"{{cargo_flags}}\" build_user_prog") cargo b {{ cargo_flags }} just sync_filesystem @@ -25,7 +25,7 @@ run: build map_dir dir recipe: @for file in `ls {{ dir }}`; do \ - just cargo_flags="{{ cargo_flags }}" {{ recipe }} $file ; \ + {{ recipe }} $file ; \ done qemu := "qemu-system-riscv64 -machine virt -device bochs-display -bios none -m 512M -device loader,file=disk.img,addr=0x90000000" diff --git a/src/main.rs b/src/main.rs index 3b30a56..5efd99d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,6 @@ ptr_metadata )] -use alloc::string::String; use embedded_alloc::LlffHeap as Heap; use log::info; diff --git a/src/process.rs b/src/process.rs index 2b20be4..6e223ee 100644 --- a/src/process.rs +++ b/src/process.rs @@ -11,6 +11,7 @@ use core::time::Duration; use alloc::{boxed::Box, format, string::String, vec::Vec}; use bffs::{io::Read, path::Path}; +use goblin::elf::reloc::R_RISCV_RELATIVE; use shared::syscall::exit; use crate::{ @@ -134,6 +135,78 @@ pub fn create_process_from_file<'a, T: Into>>(path: T) -> i64 { println!("Loading binary at address: {:x?}", content.as_ptr()); + // If ELF, use goblin to load PT_LOAD segments and apply relocations + if let Ok(gelf) = goblin::elf::Elf::parse(&content) { + // Determine memory bounds from program headers + let mut min_vaddr = u64::MAX; + let mut max_vaddr = 0u64; + for ph in gelf.program_headers.iter() { + if ph.p_type == goblin::elf::program_header::PT_LOAD && ph.p_memsz > 0 { + min_vaddr = core::cmp::min(min_vaddr, ph.p_vaddr); + max_vaddr = core::cmp::max(max_vaddr, ph.p_vaddr + ph.p_memsz); + } + } + + if min_vaddr != u64::MAX { + let size = (max_vaddr - min_vaddr) as usize; + use alloc::alloc::{alloc_zeroed, Layout}; + let layout = Layout::from_size_align(size, 0x1000).unwrap(); + let base = unsafe { alloc_zeroed(layout) }; + + // Copy segments + for ph in gelf.program_headers.iter() { + if ph.p_type == goblin::elf::program_header::PT_LOAD { + let dst = unsafe { base.add((ph.p_vaddr - min_vaddr) as usize) }; + let src_off = ph.p_offset as usize; + let copy_len = ph.p_filesz as usize; + if copy_len > 0 { + unsafe { + core::ptr::copy_nonoverlapping( + content.as_ptr().add(src_off), + dst, + copy_len, + ) + } + } + if ph.p_memsz as usize > copy_len { + unsafe { + core::slice::from_raw_parts_mut( + dst.add(copy_len), + ph.p_memsz as usize - copy_len, + ) + .fill(0) + } + } + } + } + + // Apply relocations using our parser (handles RELA entries) + for rela in gelf.dynrelas.iter() { + let r_type = rela.r_type; + match r_type { + x if x == R_RISCV_RELATIVE => { + let where_off = (rela.r_offset - min_vaddr) as usize; + let where_ptr = unsafe { base.add(where_off) } as *mut u64; + let val = (base as u64).wrapping_add(rela.r_addend.unwrap() as u64); + unsafe { core::ptr::write_unaligned(where_ptr, val) }; + } + _ => {} + } + } + + // Entry point + let entry_va = gelf.entry; + let entry_addr = unsafe { base.add((entry_va - min_vaddr) as usize) } as *const u8; + let entry_fn = + unsafe { core::mem::transmute::<*const u8, extern "C" fn()>(entry_addr) }; + let wrapper = Box::leak(Box::new(move || { + entry_fn(); + })); + println!("Program loaded at : {:x?}", entry_addr); + return create_process(wrapper, name); + } + } + // Fallback: treat the file as a raw binary blob and execute in-place let entry_point = unsafe { core::mem::transmute::<*const u8, extern "C" fn()>(Vec::leak(content).as_ptr()) }; diff --git a/user/test_pic/src/main.rs b/user/test_pic/src/main.rs index 44f294c..a8d9d06 100644 --- a/user/test_pic/src/main.rs +++ b/user/test_pic/src/main.rs @@ -1,10 +1,5 @@ #![no_std] #![no_main] -#![feature(fmt_internals)] - -use core::fmt::{write, Arguments, Write}; - -use os_std::syscall; os_std::custom_std_setup! {} fn main() { @@ -14,14 +9,5 @@ fn main() { for _ in 0..50 { test.push('C'); } - let mut b = String::from("test"); - b.write_str("string: uaeuieuei"); - // (&mut b as &mut dyn Write).write_str("string: uaeuieuei"); - syscall::write_string_temp(&b); - // write(&mut b, Arguments::from_str_nonconst("string: uaeuieuei")); - // write(&mut b, format_args!("string: uaeuie{}", "uei")); - // syscall::write_int_temp(b.capacity() as u64); - // syscall::write_string_temp(&b); - // println!("{}", test); - // println!("Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls !"); + println!("Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls !"); }