1use crate::early_println;
6
7extern crate gimli;
8
9#[linkage = "weak"]
14#[unsafe(no_mangle)]
16pub fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! {
17 let _irq_guard = crate::irq::disable_local();
18
19 crate::cpu_local_cell! {
20 static IN_PANIC: bool = false;
21 }
22
23 if IN_PANIC.load() {
24 early_println!("The panic handler panicked {:#?}", info);
25 abort();
26 }
27
28 IN_PANIC.store(true);
29
30 early_println!("Non-resettable panic! {:#?}", info);
31
32 print_stack_trace();
33 abort();
34}
35
36pub fn abort() -> ! {
40 crate::power::poweroff(crate::power::ExitCode::Failure);
44}
45
46#[derive(Debug)]
51pub(crate) struct PanicGuard {
52 _private: (),
53}
54
55impl Drop for PanicGuard {
56 fn drop(&mut self) {
57 early_println!("Panicked in `PanicGuard`, aborting the system");
58 abort();
59 }
60}
61
62impl PanicGuard {
63 pub(crate) fn new() -> Self {
65 PanicGuard { _private: () }
66 }
67
68 pub(crate) fn forget(self) {
73 core::mem::forget(self);
74 }
75}
76
77pub use unwinding::panic::{begin_panic, catch_unwind};
78
79pub fn print_stack_trace() {
83 use core::ffi::c_void;
84
85 use gimli::Register;
86 use unwinding::abi::{
87 _Unwind_Backtrace, _Unwind_FindEnclosingFunction, _Unwind_GetGR, _Unwind_GetIP,
88 UnwindContext, UnwindReasonCode,
89 };
90
91 use crate::{early_print, sync::SpinLock};
92
93 static BACKTRACE_PRINT_LOCK: SpinLock<()> = SpinLock::new(());
96 let _lock = BACKTRACE_PRINT_LOCK.lock();
97
98 early_println!("Printing stack trace:");
99
100 struct CallbackData {
101 counter: usize,
102 }
103 extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
104 let data = unsafe { &mut *(arg as *mut CallbackData) };
105 data.counter += 1;
106 let pc = _Unwind_GetIP(unwind_ctx);
107 if pc > 0 {
108 let fde_initial_address = _Unwind_FindEnclosingFunction(pc as *mut c_void) as usize;
109 early_println!(
110 "{:4}: fn {:#18x} - pc {:#18x} / registers:",
111 data.counter,
112 fde_initial_address,
113 pc,
114 );
115 }
116 for i in 0..8u16 {
119 let reg_name = cfg_select! {
120 target_arch = "x86_64" => gimli::X86_64::register_name(Register(i)),
121 target_arch = "riscv64" => gimli::RiscV::register_name(Register(i)),
122 target_arch = "loongarch64" => gimli::LoongArch::register_name(Register(i)),
123 target_arch = "aarch64" => gimli::AArch64::register_name(Register(i)),
124 _ => None,
125 };
126 let reg_val = _Unwind_GetGR(unwind_ctx, i as i32);
127 if i.is_multiple_of(4) {
128 early_print!("\n ");
129 }
130 early_print!(" {} {:#18x};", reg_name.unwrap_or("unknown"), reg_val);
131 }
132 early_print!("\n\n");
133 UnwindReasonCode::NO_REASON
134 }
135
136 let mut data = CallbackData { counter: 0 };
137 _Unwind_Backtrace(callback, &mut data as *mut _ as _);
138}