diff --git a/src/arch/aarch64/device/irqchip/gicv3.rs b/src/arch/aarch64/device/irqchip/gicv3.rs index 026c548f18..abe5cf71a1 100644 --- a/src/arch/aarch64/device/irqchip/gicv3.rs +++ b/src/arch/aarch64/device/irqchip/gicv3.rs @@ -3,7 +3,6 @@ use core::arch::asm; use fdt::{node::NodeProperty, Fdt}; use super::gic::GicDistIf; -use log::info; use syscall::{ error::{Error, EINVAL}, Result, diff --git a/src/arch/aarch64/interrupt/exception.rs b/src/arch/aarch64/interrupt/exception.rs index dd30441888..bde5567c6c 100644 --- a/src/arch/aarch64/interrupt/exception.rs +++ b/src/arch/aarch64/interrupt/exception.rs @@ -2,8 +2,8 @@ use rmm::VirtualAddress; use crate::{ exception_stack, - interrupt::stack_trace, memory::{ArchIntCtx, GenericPfFlags}, + panic::stack_trace, syscall, syscall::flag::*, }; diff --git a/src/arch/aarch64/interrupt/mod.rs b/src/arch/aarch64/interrupt/mod.rs index d21263637c..5fee770a53 100644 --- a/src/arch/aarch64/interrupt/mod.rs +++ b/src/arch/aarch64/interrupt/mod.rs @@ -12,7 +12,7 @@ pub mod trace; use crate::cpu_set::LogicalCpuId; -pub use self::{handler::InterruptStack, trace::stack_trace}; +pub use self::handler::InterruptStack; /// Clear interrupts #[inline(always)] diff --git a/src/arch/aarch64/interrupt/trace.rs b/src/arch/aarch64/interrupt/trace.rs index d14085bc67..b5ddb71a82 100644 --- a/src/arch/aarch64/interrupt/trace.rs +++ b/src/arch/aarch64/interrupt/trace.rs @@ -1,38 +1,28 @@ use core::{arch::asm, mem}; -use crate::{memory::KernelMapper, paging::VirtualAddress}; +pub struct StackTrace { + pub fp: usize, + pub pc_ptr: *const usize, +} -/// Get a stack trace -//TODO: Check for stack being mapped before dereferencing -#[inline(never)] -pub unsafe fn stack_trace() { - let mut fp: usize; - asm!("mov {}, fp", out(reg) fp); +impl StackTrace { + #[inline(always)] + pub unsafe fn start() -> Option { + let fp: usize; + asm!("mov {}, fp", out(reg) fp); + let pc_ptr = fp.checked_add(mem::size_of::())?; + Some(StackTrace { + fp, + pc_ptr: pc_ptr as *const usize, + }) + } - println!("TRACE: {:>016x}", fp); - - let mapper = KernelMapper::lock(); - - //Maximum 64 frames - for _frame in 0..64 { - if let Some(pc_fp) = fp.checked_add(mem::size_of::()) { - if mapper.translate(VirtualAddress::new(fp)).is_some() - && mapper.translate(VirtualAddress::new(pc_fp)).is_some() - { - let pc = *(pc_fp as *const usize); - if pc == 0 { - println!(" {:>016x}: EMPTY RETURN", fp); - break; - } - println!(" FP {:>016x}: PC {:>016x}", fp, pc); - fp = *(fp as *const usize); - //TODO symbol_trace(pc); - } else { - println!(" {:>016x}: GUARD PAGE", fp); - break; - } - } else { - println!(" {:>016x}: fp OVERFLOW", fp); - } + pub unsafe fn next(self) -> Option { + let fp = *(self.fp as *const usize); + let pc_ptr = fp.checked_add(mem::size_of::())?; + Some(StackTrace { + fp: fp, + pc_ptr: pc_ptr as *const usize, + }) } } diff --git a/src/arch/aarch64/rmm.rs b/src/arch/aarch64/rmm.rs index cb5395fbba..8a1e3016a9 100644 --- a/src/arch/aarch64/rmm.rs +++ b/src/arch/aarch64/rmm.rs @@ -4,7 +4,7 @@ use rmm::{ VirtualAddress, KILOBYTE, MEGABYTE, }; -use crate::{cpu_set::LogicalCpuId, init::device_tree::MEMORY_MAP, paging::entry::EntryFlags}; +use crate::{init::device_tree::MEMORY_MAP, paging::entry::EntryFlags}; use super::CurrentRmmArch as RmmA; diff --git a/src/arch/x86/interrupt/exception.rs b/src/arch/x86/interrupt/exception.rs index cc3732cc76..25bfb45693 100644 --- a/src/arch/x86/interrupt/exception.rs +++ b/src/arch/x86/interrupt/exception.rs @@ -1,8 +1,8 @@ use x86::irq::PageFaultError; use crate::{ - interrupt::stack_trace, interrupt_error, interrupt_stack, ksignal, memory::GenericPfFlags, - paging::VirtualAddress, ptrace, syscall::flag::*, + interrupt_error, interrupt_stack, ksignal, memory::GenericPfFlags, paging::VirtualAddress, + panic::stack_trace, ptrace, syscall::flag::*, }; interrupt_stack!(divide_by_zero, |stack| { diff --git a/src/arch/x86_64/interrupt/exception.rs b/src/arch/x86_64/interrupt/exception.rs index e1eadb09f6..575e256bba 100644 --- a/src/arch/x86_64/interrupt/exception.rs +++ b/src/arch/x86_64/interrupt/exception.rs @@ -1,8 +1,8 @@ use x86::irq::PageFaultError; use crate::{ - interrupt::stack_trace, interrupt_error, interrupt_stack, ksignal, memory::GenericPfFlags, - paging::VirtualAddress, ptrace, syscall::flag::*, + interrupt_error, interrupt_stack, ksignal, memory::GenericPfFlags, paging::VirtualAddress, + panic::stack_trace, ptrace, syscall::flag::*, }; interrupt_stack!(divide_by_zero, |stack| { diff --git a/src/arch/x86_shared/interrupt/mod.rs b/src/arch/x86_shared/interrupt/mod.rs index 7836ea3dce..adb659c542 100644 --- a/src/arch/x86_shared/interrupt/mod.rs +++ b/src/arch/x86_shared/interrupt/mod.rs @@ -3,8 +3,6 @@ pub mod ipi; pub mod trace; -pub use self::trace::stack_trace; - pub use super::{ device::local_apic::bsp_apic_id, idt::{available_irqs_iter, is_reserved, set_reserved}, diff --git a/src/arch/x86_shared/interrupt/trace.rs b/src/arch/x86_shared/interrupt/trace.rs index b09107d53f..9df85d66a6 100644 --- a/src/arch/x86_shared/interrupt/trace.rs +++ b/src/arch/x86_shared/interrupt/trace.rs @@ -1,107 +1,31 @@ -use core::{mem, str}; +use core::mem; -use goblin::elf::sym; -use rustc_demangle::demangle; - -use crate::{memory::KernelMapper, paging::VirtualAddress, USER_END_OFFSET}; - -/// Get a stack trace -//TODO: Check for stack being mapped before dereferencing -#[inline(never)] -pub unsafe fn stack_trace() { - let mut sp: usize; - #[cfg(target_arch = "x86")] - core::arch::asm!("mov {}, ebp", out(reg) sp); - #[cfg(target_arch = "x86_64")] - core::arch::asm!("mov {}, rbp", out(reg) sp); - - println!("TRACE: {:>016X}", sp); - //Maximum 64 frames - - let mapper = KernelMapper::lock(); - - for _frame in 0..64 { - if let Some(ip_bp) = sp.checked_add(mem::size_of::()) { - let bp_virt = VirtualAddress::new(sp); - let ip_bp_virt = VirtualAddress::new(ip_bp); - if bp_virt.data() >= USER_END_OFFSET - && ip_bp_virt.data() >= USER_END_OFFSET - && mapper.translate(bp_virt).is_some() - && mapper.translate(ip_bp_virt).is_some() - { - let ip = (ip_bp as *const usize).read(); - if ip == 0 { - println!(" {:>016X}: EMPTY RETURN", sp); - break; - } - println!(" {:>016X}: {:>016X}", sp, ip); - sp = (sp as *const usize).read(); - symbol_trace(ip); - } else { - println!(" {:>016X}: GUARD PAGE", sp); - break; - } - } else { - println!(" {:>016X}: RBP OVERFLOW", sp); - break; - } - } +pub struct StackTrace { + pub fp: usize, + pub pc_ptr: *const usize, } -/// Get a symbol -//TODO: Do not create Elf object for every symbol lookup -#[inline(never)] -pub unsafe fn symbol_trace(addr: usize) { - use core::{slice, sync::atomic::Ordering}; +impl StackTrace { + #[inline(always)] + pub unsafe fn start() -> Option { + let mut fp: usize; + #[cfg(target_arch = "x86")] + core::arch::asm!("mov {}, ebp", out(reg) fp); + #[cfg(target_arch = "x86_64")] + core::arch::asm!("mov {}, rbp", out(reg) fp); + let pc_ptr = fp.checked_add(mem::size_of::())?; + Some(Self { + fp, + pc_ptr: pc_ptr as *const usize, + }) + } - use crate::{ - elf::Elf, - start::{KERNEL_BASE, KERNEL_SIZE}, - }; - - let kernel_ptr = (KERNEL_BASE.load(Ordering::SeqCst) + crate::PHYS_OFFSET) as *const u8; - let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst)); - if let Ok(elf) = Elf::from(kernel_slice) { - let mut strtab_opt = None; - for section in elf.sections() { - if section.sh_type == ::goblin::elf::section_header::SHT_STRTAB { - strtab_opt = Some(section); - break; - } - } - - if let Some(symbols) = elf.symbols() { - for sym in symbols { - if sym::st_type(sym.st_info) == sym::STT_FUNC - && addr >= sym.st_value as usize - && addr < (sym.st_value + sym.st_size) as usize - { - println!( - " {:>016X}+{:>04X}", - sym.st_value, - addr - sym.st_value as usize - ); - - if let Some(strtab) = strtab_opt { - let start = strtab.sh_offset as usize + sym.st_name as usize; - let mut end = start; - while end < elf.data.len() { - let b = elf.data[end]; - end += 1; - if b == 0 { - break; - } - } - - if end > start { - let sym_slice = &elf.data[start..end - 1]; - if let Ok(sym_name) = str::from_utf8(sym_slice) { - println!(" {:#}", demangle(sym_name)); - } - } - } - } - } - } + pub unsafe fn next(self) -> Option { + let fp = *(self.fp as *const usize); + let pc_ptr = fp.checked_add(mem::size_of::())?; + Some(Self { + fp: fp, + pc_ptr: pc_ptr as *const usize, + }) } } diff --git a/src/main.rs b/src/main.rs index 0a6eaf1ca0..ee3fc28da8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -124,7 +124,6 @@ use spinning_top::RwSpinlock; mod memory; /// Panic -#[cfg(not(test))] mod panic; mod percpu; diff --git a/src/panic.rs b/src/panic.rs index 92cb9879f2..3c5442f6b5 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,16 +1,28 @@ //! Intrinsics for panic handling -use core::panic::PanicInfo; +use core::{panic::PanicInfo, slice, str, sync::atomic::Ordering}; +use goblin::elf::sym; +use rmm::VirtualAddress; +use rustc_demangle::demangle; -use crate::{context, cpu_id, interrupt, syscall}; +use crate::{ + arch::{consts::USER_END_OFFSET, interrupt::trace::StackTrace}, + context, cpu_id, + elf::Elf, + interrupt, + memory::KernelMapper, + start::KERNEL_SIZE, + syscall, +}; /// Required to handle panics +#[cfg(not(test))] #[panic_handler] fn rust_begin_unwind(info: &PanicInfo) -> ! { println!("KERNEL PANIC: {}", info); unsafe { - interrupt::stack_trace(); + stack_trace(); } let context_lock = context::current(); @@ -33,3 +45,93 @@ fn rust_begin_unwind(info: &PanicInfo) -> ! { } } } + +/// Get a stack trace +#[inline(never)] +pub unsafe fn stack_trace() { + let mapper = KernelMapper::lock(); + + let mut frame = StackTrace::start(); + + //Maximum 64 frames + for _ in 0..64 { + if let Some(frame_) = frame { + let fp_virt = VirtualAddress::new(frame_.fp); + let pc_virt = VirtualAddress::new(frame_.pc_ptr as usize); + if fp_virt.data() >= USER_END_OFFSET + && pc_virt.data() >= USER_END_OFFSET + && (fp_virt.data() as *const usize).is_aligned() + && (pc_virt.data() as *const usize).is_aligned() + && mapper.translate(fp_virt).is_some() + && mapper.translate(pc_virt).is_some() + { + let pc = *frame_.pc_ptr; + if pc == 0 { + println!(" {:>016x}: EMPTY RETURN", frame_.fp); + break; + } else { + println!(" FP {:>016x}: PC {:>016x}", frame_.fp, pc); + symbol_trace(pc); + frame = frame_.next(); + } + } else { + println!(" {:>016x}: GUARD PAGE", frame_.fp); + break; + } + } else { + break; + } + } +} +/// +/// Get a symbol +//TODO: Do not create Elf object for every symbol lookup +#[inline(never)] +pub unsafe fn symbol_trace(addr: usize) { + let kernel_ptr = crate::KERNEL_OFFSET as *const u8; + let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst)); + + if let Ok(elf) = Elf::from(kernel_slice) { + let mut strtab_opt = None; + for section in elf.sections() { + if section.sh_type == ::goblin::elf::section_header::SHT_STRTAB { + strtab_opt = Some(section); + break; + } + } + + if let Some(symbols) = elf.symbols() { + for sym in symbols { + if sym::st_type(sym.st_info) == sym::STT_FUNC + && addr >= sym.st_value as usize + && addr < (sym.st_value + sym.st_size) as usize + { + println!( + " {:>016X}+{:>04X}", + sym.st_value, + addr - sym.st_value as usize + ); + + if let Some(strtab) = strtab_opt { + let start = strtab.sh_offset as usize + sym.st_name as usize; + let mut end = start; + while end < elf.data.len() { + let b = elf.data[end]; + end += 1; + if b == 0 { + break; + } + } + + if end > start { + let sym_slice = &elf.data[start..end - 1]; + if let Ok(sym_name) = str::from_utf8(sym_slice) { + println!(" {:#}", demangle(sym_name)); + } + } + } + } + } + } + } +}