From d3b17177b2c2d561d821c5828fa3e5deb621e661 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 14 Sep 2025 12:50:43 +0200 Subject: [PATCH] Avoid allocating during panics and infer kernel image size without explicitly storing it --- src/arch/aarch64/start.rs | 7 +---- src/arch/riscv64/start.rs | 5 ---- src/arch/x86_shared/start.rs | 8 +----- src/panic.rs | 53 +++++++++++++++++++++++++----------- 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/arch/aarch64/start.rs b/src/arch/aarch64/start.rs index 9fea42d816..17647e1acc 100644 --- a/src/arch/aarch64/start.rs +++ b/src/arch/aarch64/start.rs @@ -4,7 +4,7 @@ //! defined in other files inside of the `arch` module use core::{ slice, - sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}, + sync::atomic::{AtomicBool, AtomicU32, Ordering}, }; use fdt::Fdt; @@ -25,8 +25,6 @@ static mut BSS_TEST_ZERO: usize = 0; /// Test of non-zero values in data. static mut DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF; -pub static KERNEL_BASE: AtomicUsize = AtomicUsize::new(0); -pub static KERNEL_SIZE: AtomicUsize = AtomicUsize::new(0); pub static CPU_COUNT: AtomicU32 = AtomicU32::new(0); pub static AP_READY: AtomicBool = AtomicBool::new(false); static BSP_READY: AtomicBool = AtomicBool::new(false); @@ -64,9 +62,6 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! { assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF); } - KERNEL_BASE.store(args.kernel_base, Ordering::SeqCst); - KERNEL_SIZE.store(args.kernel_size, Ordering::SeqCst); - // Convert env to slice let env = slice::from_raw_parts( (crate::PHYS_OFFSET + args.env_base) as *const u8, diff --git a/src/arch/riscv64/start.rs b/src/arch/riscv64/start.rs index 74dfa46472..286b5da599 100644 --- a/src/arch/riscv64/start.rs +++ b/src/arch/riscv64/start.rs @@ -24,8 +24,6 @@ static mut BSS_TEST_ZERO: usize = 0; /// Test of non-zero values in data. static mut DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF; -pub static KERNEL_BASE: AtomicUsize = AtomicUsize::new(0); -pub static KERNEL_SIZE: AtomicUsize = AtomicUsize::new(0); pub static CPU_COUNT: AtomicU32 = AtomicU32::new(0); pub static BOOT_HART_ID: AtomicUsize = AtomicUsize::new(0); @@ -81,9 +79,6 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! { assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF); } - KERNEL_BASE.store(args.kernel_base, Ordering::SeqCst); - KERNEL_SIZE.store(args.kernel_size, Ordering::SeqCst); - let env = slice::from_raw_parts( (crate::PHYS_OFFSET + args.env_base) as *const u8, args.env_size, diff --git a/src/arch/x86_shared/start.rs b/src/arch/x86_shared/start.rs index 30a1124c36..d17b4e5888 100644 --- a/src/arch/x86_shared/start.rs +++ b/src/arch/x86_shared/start.rs @@ -5,7 +5,7 @@ use core::{ cell::SyncUnsafeCell, hint, slice, - sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}, + sync::atomic::{AtomicBool, AtomicU32, Ordering}, }; #[cfg(feature = "acpi")] @@ -26,9 +26,6 @@ static BSS_TEST_ZERO: SyncUnsafeCell = SyncUnsafeCell::new(0); /// Test of non-zero values in data. static DATA_TEST_NONZERO: SyncUnsafeCell = SyncUnsafeCell::new(usize::max_value()); -pub static KERNEL_BASE: AtomicUsize = AtomicUsize::new(0); -pub static KERNEL_SIZE: AtomicUsize = AtomicUsize::new(0); - // TODO: This probably shouldn't be an atomic. Only the BSP starts APs. pub static CPU_COUNT: AtomicU32 = AtomicU32::new(0); @@ -75,9 +72,6 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! { assert_eq!(DATA_TEST_NONZERO.get().read(), usize::max_value()); } - KERNEL_BASE.store(args.kernel_base as usize, Ordering::SeqCst); - KERNEL_SIZE.store(args.kernel_size as usize, Ordering::SeqCst); - // Convert env to slice let env = slice::from_raw_parts( (args.env_base as usize + crate::PHYS_OFFSET) as *const u8, diff --git a/src/panic.rs b/src/panic.rs index 208f0e2458..ff527f40f7 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,12 +1,16 @@ //! Intrinsics for panic handling -use core::{panic::PanicInfo, slice, sync::atomic::Ordering}; +use core::{panic::PanicInfo, slice}; #[cfg(target_pointer_width = "32")] -use object::read::elf::ElfFile32 as ElfFile; +use object::elf::FileHeader32 as FileHeader; #[cfg(target_pointer_width = "64")] -use object::read::elf::ElfFile64 as ElfFile; -use object::{elf::STT_FUNC, NativeEndian, Object, ObjectSymbol}; +use object::elf::FileHeader64 as FileHeader; +use object::{ + elf, + read::elf::{FileHeader as _, Sym as _}, + NativeEndian, +}; use rmm::VirtualAddress; use rustc_demangle::demangle; @@ -14,7 +18,6 @@ use crate::{ arch::{consts::USER_END_OFFSET, interrupt::trace::StackTrace}, context, cpu_id, interrupt, memory::KernelMapper, - start::KERNEL_SIZE, syscall, }; @@ -66,8 +69,25 @@ pub unsafe fn stack_trace() { let mapper = KernelMapper::lock(); let kernel_ptr = crate::KERNEL_OFFSET as *const u8; - let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst)); - let obj = ElfFile::::parse(kernel_slice).unwrap(); + let elf_header: &FileHeader = object::pod::from_bytes(slice::from_raw_parts( + kernel_ptr, + size_of::>(), + )) + .unwrap() + .0; + + // This assumes that the linker places .shstrtab as last section. If it + // isn't, that just causes a recursive panic, not UB. + let kernel_size = elf_header.e_shoff(NativeEndian) as usize + + usize::from(elf_header.e_shnum(NativeEndian)) + * usize::from(elf_header.e_shentsize(NativeEndian)); + let kernel_slice = slice::from_raw_parts(kernel_ptr, kernel_size); + + let symbols = elf_header + .sections(NativeEndian, kernel_slice) + .unwrap() + .symbols(NativeEndian, kernel_slice, elf::SHT_SYMTAB) + .unwrap(); let mut frame = StackTrace::start(); @@ -97,21 +117,22 @@ pub unsafe fn stack_trace() { println!(" FP {:>016x}: PC {:>016x}", frame_.fp, pc); - for sym in obj.symbols() { - if sym.elf_symbol().st_type() != STT_FUNC { + for sym in symbols.iter() { + if sym.st_type() != elf::STT_FUNC { continue; } - if !(pc >= sym.address() as usize && pc < (sym.address() + sym.size()) as usize) { + let sym_addr = sym.st_value.get(NativeEndian) as usize; + if !(pc >= sym_addr && pc < sym_addr + sym.st_size.get(NativeEndian) as usize) { continue; } - println!( - " {:>016X}+{:>04X}", - sym.address(), - pc - sym.address() as usize - ); + println!(" {:>016X}+{:>04X}", sym_addr, pc - sym_addr); - if let Ok(sym_name) = sym.name() { + if let Some(sym_name) = sym + .name(NativeEndian, symbols.strings()) + .ok() + .and_then(|name| core::str::from_utf8(name).ok()) + { println!(" {:#}", demangle(sym_name)); } }