diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs new file mode 100644 index 0000000..6243474 --- /dev/null +++ b/kernel/src/backtrace.rs @@ -0,0 +1,48 @@ +extern "C" { + fn stext(); + fn etext(); +} + +/// Returns the current frame pointer. +#[inline(always)] +#[cfg(target_arch = "aarch64")] +pub fn fp() -> usize { + let ptr: usize; + unsafe { + asm!("mov $0, x29" : "=r"(ptr)); + } + + ptr +} + +/// Returns the current link register. +#[inline(always)] +#[cfg(target_arch = "aarch64")] +pub fn lr() -> usize { + let ptr: usize; + unsafe { + asm!("mov $0, x30" : "=r"(ptr)); + } + + ptr +} + +// Print the backtrace starting from the caller +pub fn backtrace() { + #[cfg(target_arch = "aarch64")] + unsafe { + let mut current_pc = lr(); + let mut current_fp = fp(); + let mut stack_num = 0; + println!("pc {:#018X} fp {:#018X}", current_pc, current_fp); + while current_pc >= stext as usize && current_pc <= etext as usize && current_fp as usize != 0 { + println!("#{} {:#018X}", stack_num, current_pc); + stack_num = stack_num + 1; + current_fp = *(current_fp as *const usize); + if current_fp as usize != 0 { + current_pc = *(current_fp as *const usize).offset(1); + } + println!("pc {:#018X} fp {:#018X}", current_pc, current_fp); + } + } +} diff --git a/kernel/src/lang.rs b/kernel/src/lang.rs index 27b0d21..903e137 100644 --- a/kernel/src/lang.rs +++ b/kernel/src/lang.rs @@ -3,6 +3,7 @@ use core::panic::PanicInfo; use core::alloc::Layout; use log::*; +use crate::backtrace; #[lang = "eh_personality"] extern fn eh_personality() { @@ -13,6 +14,7 @@ fn panic(info: &PanicInfo) -> ! { let location = info.location().unwrap(); let message = info.message().unwrap(); error!("\n\nPANIC in {} at line {}\n {}", location.file(), location.line(), message); + backtrace::backtrace(); loop { crate::arch::cpu::halt() } } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index ab18c1c..29e5ce0 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -28,6 +28,7 @@ mod fs; mod sync; mod trap; mod shell; +mod backtrace; #[allow(dead_code)] #[cfg(target_arch = "x86_64")] diff --git a/kernel/targets/aarch64.json b/kernel/targets/aarch64.json index b0c24dc..149246a 100644 --- a/kernel/targets/aarch64.json +++ b/kernel/targets/aarch64.json @@ -31,5 +31,6 @@ "target-endian": "little", "target-pointer-width": "64", "target-family": "unix", - "disable-redzone": true + "disable-redzone": true, + "eliminate-frame-pointer": false }