Let OSDK print source lines of the panic stack trace

This commit is contained in:
Zhang Junyang
2024-05-17 15:28:29 +00:00
committed by Tate, Hongliang Tian
parent f420286920
commit 8e874e6a88
4 changed files with 69 additions and 3 deletions

View File

@ -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());
}
}
}
}