mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: add backtrace support
This commit is contained in:
parent
e6abb50f86
commit
4647d1fd2a
66
kernel/src/arch/riscv/backtrace.rs
Normal file
66
kernel/src/arch/riscv/backtrace.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
mod backtrace;
|
||||
mod entry;
|
||||
pub mod layout;
|
||||
mod lowlevel;
|
||||
|
@ -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);
|
||||
}
|
||||
|
26
kernel/src/plat/backtrace.rs
Normal file
26
kernel/src/plat/backtrace.rs
Normal 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");
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
pub mod backtrace;
|
||||
pub mod console;
|
||||
pub mod lowlevel;
|
||||
pub mod timer;
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user