mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-26 19:03:27 +00:00
Print backtrace when there is uncaught panic
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
ec3daca5fd
commit
c776954dfc
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -640,6 +640,7 @@ dependencies = [
|
|||||||
"bitvec",
|
"bitvec",
|
||||||
"buddy_system_allocator",
|
"buddy_system_allocator",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"gimli",
|
||||||
"inherit-methods-macro",
|
"inherit-methods-macro",
|
||||||
"int-to-c-enum",
|
"int-to-c-enum",
|
||||||
"intrusive-collections",
|
"intrusive-collections",
|
||||||
|
@ -12,6 +12,7 @@ bitflags = "1.3"
|
|||||||
bitvec = { version = "1.0", default-features = false, features = ["alloc"] }
|
bitvec = { version = "1.0", default-features = false, features = ["alloc"] }
|
||||||
buddy_system_allocator = "0.9.0"
|
buddy_system_allocator = "0.9.0"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
|
gimli = { version = "0.28", default-features = false, features = ["read-core"] }
|
||||||
inherit-methods-macro = { git = "https://github.com/jinzhao-dev/inherit-methods-macro", rev = "98f7e3e" }
|
inherit-methods-macro = { git = "https://github.com/jinzhao-dev/inherit-methods-macro", rev = "98f7e3e" }
|
||||||
int-to-c-enum = { path = "../../services/libs/int-to-c-enum" }
|
int-to-c-enum = { path = "../../services/libs/int-to-c-enum" }
|
||||||
intrusive-collections = "0.9.5"
|
intrusive-collections = "0.9.5"
|
||||||
|
@ -1,9 +1,27 @@
|
|||||||
//! Panic support.
|
//! Panic support.
|
||||||
|
|
||||||
use alloc::{boxed::Box, string::ToString};
|
use alloc::{boxed::Box, string::ToString};
|
||||||
|
use core::ffi::c_void;
|
||||||
|
|
||||||
use crate::arch::qemu::{exit_qemu, QemuExitCode};
|
use crate::arch::qemu::{exit_qemu, QemuExitCode};
|
||||||
use crate::println;
|
use crate::{print, println};
|
||||||
|
use log::error;
|
||||||
|
|
||||||
|
extern crate cfg_if;
|
||||||
|
extern crate gimli;
|
||||||
|
use gimli::Register;
|
||||||
|
|
||||||
|
use unwinding::{
|
||||||
|
abi::{
|
||||||
|
UnwindContext, UnwindReasonCode, _Unwind_Backtrace, _Unwind_FindEnclosingFunction,
|
||||||
|
_Unwind_GetGR, _Unwind_GetIP,
|
||||||
|
},
|
||||||
|
panic::begin_panic,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn abort() -> ! {
|
||||||
|
exit_qemu(QemuExitCode::Failed);
|
||||||
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
||||||
@ -14,9 +32,48 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
|||||||
col: info.location().unwrap().column() as usize,
|
col: info.location().unwrap().column() as usize,
|
||||||
};
|
};
|
||||||
// Throw an exception and expecting it to be caught.
|
// Throw an exception and expecting it to be caught.
|
||||||
unwinding::panic::begin_panic(Box::new(throw_info.clone()));
|
begin_panic(Box::new(throw_info.clone()));
|
||||||
// If the exception is not caught (e.g. by ktest), then print the information
|
// If the exception is not caught (e.g. by ktest) and resumed,
|
||||||
// and exit failed using the debug device.
|
// then print the information and abort.
|
||||||
println!("[uncaught panic] {}", info);
|
error!("Uncaught panic!");
|
||||||
exit_qemu(QemuExitCode::Failed);
|
println!("{}", info);
|
||||||
|
println!("printing stack trace:");
|
||||||
|
print_stack_trace();
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_stack_trace() {
|
||||||
|
struct CallbackData {
|
||||||
|
counter: usize,
|
||||||
|
}
|
||||||
|
extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
|
||||||
|
let data = unsafe { &mut *(arg as *mut CallbackData) };
|
||||||
|
data.counter += 1;
|
||||||
|
let pc = _Unwind_GetIP(unwind_ctx);
|
||||||
|
let fde_initial_address = _Unwind_FindEnclosingFunction(pc as *mut c_void) as usize;
|
||||||
|
println!(
|
||||||
|
"{:4}: fn {:#18x} - pc {:#18x} / registers:",
|
||||||
|
data.counter, fde_initial_address, pc,
|
||||||
|
);
|
||||||
|
// Print the first 8 general registers for any architecture. The register number follows
|
||||||
|
// the DWARF standard.
|
||||||
|
for i in 0..8u16 {
|
||||||
|
let reg_i = _Unwind_GetGR(unwind_ctx, i as i32);
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_arch = "x86_64")] {
|
||||||
|
let reg_name = gimli::X86_64::register_name(Register(i)).unwrap_or("unknown");
|
||||||
|
} else {
|
||||||
|
let reg_name = "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i % 4 == 0 {
|
||||||
|
print!("\n ");
|
||||||
|
}
|
||||||
|
print!(" {} {:#18x};", reg_name, reg_i);
|
||||||
|
}
|
||||||
|
print!("\n\n");
|
||||||
|
UnwindReasonCode::NO_REASON
|
||||||
|
}
|
||||||
|
let mut data = CallbackData { counter: 0 };
|
||||||
|
_Unwind_Backtrace(callback, &mut data as *mut _ as _);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user