feat: add backtrace support

This commit is contained in:
Paul Pan 2024-04-24 16:33:02 +08:00
parent e6abb50f86
commit 4647d1fd2a
6 changed files with 106 additions and 5 deletions

View File

@ -0,0 +1,66 @@
use super::layout::{BSS_END, BSS_START, TEXT_END, TEXT_START};
use crate::plat::backtrace::FrameWalker;
use vspace::addr::{AddressOps, VirtAddr};
impl FrameWalker {
fn read_fp() -> usize {
let fp;
unsafe { core::arch::asm!("mv {}, fp", out(reg) fp) }
fp
}
fn read_ra() -> usize {
let ra;
unsafe { core::arch::asm!("mv {}, ra", out(reg) ra) }
ra
}
fn is_valid(&self) -> bool {
let fp_valid = unsafe { BSS_START.as_virt_addr() <= self.current_fp && self.current_fp < BSS_END.as_virt_addr() };
let pc_valid = unsafe { TEXT_START.as_virt_addr() <= self.current_pc && self.current_pc < TEXT_END.as_virt_addr() };
fp_valid && pc_valid
}
pub fn new() -> Self {
// current_{fp, pc} is deliberately missed for printing
Self {
current_fp: VirtAddr::from(FrameWalker::read_fp()),
current_pc: VirtAddr::from(FrameWalker::read_ra()),
}
}
}
impl Iterator for crate::plat::backtrace::FrameWalker {
type Item = Self;
fn next(&mut self) -> Option<Self::Item> {
/*
* Prologue like this:
* > addi sp,sp,-16
* > sd ra,8(sp)
* > sd s0,0(sp)
* > addi s0,sp,16
*
* Epilogue like this:
* > ld ra,8(sp)
* > ld s0,0(sp)
* > addi sp,sp,16
* > jr ra
*
* prev_fp = *(current_fp - 16)
* prev_pc = *(current_fp - 8)
*/
if !self.is_valid() {
return None;
}
let prev_fp = unsafe { *(self.current_fp.as_const_ptr() as *const usize).offset(-2) };
let prev_pc = unsafe { *(self.current_fp.as_const_ptr() as *const usize).offset(-1) };
self.current_fp = VirtAddr::from(prev_fp);
self.current_pc = VirtAddr::from(prev_pc);
Some(*self)
}
}

View File

@ -11,6 +11,7 @@ cfg_if! {
}
}
mod backtrace;
mod entry;
pub mod layout;
mod lowlevel;

View File

@ -1,9 +1,10 @@
use crate::plat::{
backtrace::dump_backtrace,
lowlevel::{Hardware, LowLevel},
};
use core::panic::PanicInfo;
use log::error;
use crate::plat::lowlevel::{Hardware, LowLevel};
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
error!("Kernel panic!");
@ -19,5 +20,7 @@ fn panic(info: &PanicInfo) -> ! {
None => error!("[lang] Panicked: {}", info.message().unwrap()),
}
unsafe { dump_backtrace() };
Hardware::shutdown(true);
}

View File

@ -0,0 +1,26 @@
use log::error;
use vspace::addr::VirtAddr;
#[derive(Clone, Copy)]
pub struct FrameWalker {
pub current_fp: VirtAddr,
pub current_pc: VirtAddr,
}
pub unsafe fn dump_backtrace() {
let mut depth = 0;
error!("Dumping stack trace ...");
let walker = FrameWalker::new();
for frame in walker {
error!("#{:02} PC: {:#x?} FP: {:#x?}", depth, frame.current_pc, frame.current_fp);
depth += 1;
if depth >= 100 {
error!("Backtrace is too deep, aborting ...");
return;
}
}
error!("Backtrace complete");
}

View File

@ -1,3 +1,4 @@
pub mod backtrace;
pub mod console;
pub mod lowlevel;
pub mod timer;

View File

@ -19,8 +19,12 @@ impl Arch {
"-Zbuild-std=core,compiler_builtins,alloc",
"-Zbuild-std-features=compiler-builtins-mem",
];
const FLAGS_RELOCATION: [&'static str; 3] =
["-Crelocation-model=static", "-Ccode-model=medium", "-Ctarget-feature=+relax"];
const FLAGS_RELOCATION: [&'static str; 4] = [
"-Crelocation-model=static",
"-Ccode-model=medium",
"-Ctarget-feature=+relax",
"-Cforce-frame-pointers=yes",
];
pub fn cargo_args(&self, test: bool) -> Vec<String> {
let mut args: Vec<String> = Vec::new();