mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-21 08:26:30 +00:00
Let OSDK print source lines of the panic stack trace
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
f420286920
commit
8e874e6a88
15
osdk/Cargo.lock
generated
15
osdk/Cargo.lock
generated
@ -132,6 +132,8 @@ dependencies = [
|
||||
"linux-bzimage-builder",
|
||||
"log",
|
||||
"quote",
|
||||
"regex",
|
||||
"rev_buf_reader",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
@ -388,9 +390,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.3"
|
||||
version = "1.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
|
||||
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@ -415,6 +417,15 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "rev_buf_reader"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c0f2e47e00e29920959826e2e1784728a3780d1a784247be5257258cc75f910"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
|
@ -29,6 +29,8 @@ indexmap = "2.2.1"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.20"
|
||||
quote = "1.0.35"
|
||||
regex = "1.10.4"
|
||||
rev_buf_reader = "0.3.0"
|
||||
serde = { version = "1.0.195", features = ["derive"] }
|
||||
serde_json = "1.0.111"
|
||||
sha2 = "0.10.8"
|
||||
|
@ -247,6 +247,18 @@ impl Bundle {
|
||||
info!("Running QEMU: {:#?}", qemu_cmd);
|
||||
|
||||
let exit_status = qemu_cmd.status().unwrap();
|
||||
|
||||
// Find the QEMU output in "qemu.log", read it and check if it failed with a panic.
|
||||
// Setting a QEMU log is required for source line stack trace because piping the output
|
||||
// is less desirable when running QEMU with serial redirected to standard I/O.
|
||||
let qemu_log_path = config.work_dir.join("qemu.log");
|
||||
if let Ok(file) = std::fs::File::open(qemu_log_path) {
|
||||
if let Some(aster_bin) = &self.manifest.aster_bin {
|
||||
crate::util::trace_panic_from_log(file, self.path.join(aster_bin.path()));
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: When panicking it sometimes returns success, why?
|
||||
if !exit_status.success() {
|
||||
// FIXME: Exit code manipulation is not needed when using non-x86 QEMU
|
||||
let qemu_exit_code = exit_status.code().unwrap();
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
fs,
|
||||
fs::{self, File},
|
||||
io::{BufRead, BufReader, Write},
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
@ -212,3 +213,43 @@ pub fn parse_package_id_string(package_id: &str) -> CrateInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Print source line stack trace if a panic is detected from QEMU log.
|
||||
///
|
||||
/// The source line is produced with the `addr2line` command using the PC values in the panic
|
||||
/// stack trace.
|
||||
pub fn trace_panic_from_log(qemu_log: File, bin_path: PathBuf) {
|
||||
// We read last 500 lines since more than 100 layers of stack trace is unlikely.
|
||||
let reader = rev_buf_reader::RevBufReader::new(qemu_log);
|
||||
let lines: Vec<String> = reader.lines().take(500).map(|l| l.unwrap()).collect();
|
||||
let mut trace_exists = false;
|
||||
let mut stack_num = 0;
|
||||
let pc_matcher = regex::Regex::new(r" - pc (0x[0-9a-fA-F]+)").unwrap();
|
||||
let exe = bin_path.to_string_lossy();
|
||||
let mut addr2line = Command::new("addr2line");
|
||||
addr2line.args(["-e", &exe]);
|
||||
let mut addr2line_proc = addr2line
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
for line in lines.into_iter().rev() {
|
||||
if line.contains("printing stack trace:") {
|
||||
println!("[OSDK] The kernel seems panicked. Parsing stack trace for source lines:");
|
||||
trace_exists = true;
|
||||
}
|
||||
if trace_exists {
|
||||
if let Some(cap) = pc_matcher.captures(&line) {
|
||||
let pc = cap.get(1).unwrap().as_str();
|
||||
let mut stdin = addr2line_proc.stdin.as_ref().unwrap();
|
||||
stdin.write_all(pc.as_bytes()).unwrap();
|
||||
stdin.write_all(b"\n").unwrap();
|
||||
let mut line = String::new();
|
||||
let mut stdout = BufReader::new(addr2line_proc.stdout.as_mut().unwrap());
|
||||
stdout.read_line(&mut line).unwrap();
|
||||
stack_num += 1;
|
||||
println!("({: >3}) {}", stack_num, line.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user