mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-27 19:33:23 +00:00
66 lines
2.6 KiB
Rust
66 lines
2.6 KiB
Rust
//! Providing the utility to run the GDB scripts for the runner.
|
|
|
|
use crate::qemu_grub_efi;
|
|
use std::{fs::OpenOptions, io::Write, path::PathBuf, process::Command};
|
|
|
|
/// Run a GDB client.
|
|
///
|
|
/// If argument `gdb_grub` is set true, it will run GRUB's gdb script.
|
|
///
|
|
/// When debugging grub, the OVMF firmware will load the grub kernel at an
|
|
/// address unknown at the moment. You should use the debug message from our
|
|
/// custom built OVMF firmware and read the entrypoint address
|
|
/// (often `0x0007E685000`). Then use the following GDB command to load symbols:
|
|
/// `dynamic_load_symbols ${ENTRY_ADDRESS}`.
|
|
/// During each run, the address is unlikely to change. But the address will
|
|
/// depend on the versions of grub or OVMF.
|
|
///
|
|
/// Also, do `set breakpoint pending on` when you want to break on GRUB modules.
|
|
pub fn run_gdb_client(path: &PathBuf, gdb_grub: bool) {
|
|
let path = std::fs::canonicalize(path).unwrap();
|
|
let mut gdb_cmd = Command::new("gdb");
|
|
// Set the architecture, otherwise GDB will complain about.
|
|
gdb_cmd.arg("-ex").arg("set arch i386:x86-64:intel");
|
|
let grub_script = "/tmp/jinux-gdb-grub-script";
|
|
if gdb_grub {
|
|
let grub_dir = PathBuf::from(qemu_grub_efi::GRUB_PREFIX)
|
|
.join("lib")
|
|
.join("grub")
|
|
.join(qemu_grub_efi::GRUB_VERSION);
|
|
// Load symbols from GRUB using the provided grub gdb script.
|
|
// Read the contents from `gdb_grub` and
|
|
// replace the lines containing "target remote :1234".
|
|
gdb_cmd.current_dir(&grub_dir);
|
|
let grub_script_content = std::fs::read_to_string(grub_dir.join("gdb_grub")).unwrap();
|
|
let lines = grub_script_content.lines().collect::<Vec<_>>();
|
|
let mut f = OpenOptions::new()
|
|
.write(true)
|
|
.create(true)
|
|
.open(grub_script)
|
|
.unwrap();
|
|
for line in lines {
|
|
if line.contains("target remote :1234") {
|
|
// Connect to the GDB server.
|
|
writeln!(f, "target remote /tmp/jinux-gdb-socket").unwrap();
|
|
} else {
|
|
writeln!(f, "{}", line).unwrap();
|
|
}
|
|
}
|
|
gdb_cmd.arg("-x").arg(grub_script);
|
|
} else {
|
|
// Load symbols from the kernel image.
|
|
gdb_cmd.arg("-ex").arg(format!("file {}", path.display()));
|
|
// Connect to the GDB server.
|
|
gdb_cmd
|
|
.arg("-ex")
|
|
.arg("target remote /tmp/jinux-gdb-socket");
|
|
}
|
|
// Connect to the GDB server and run.
|
|
println!("running:{:#?}", gdb_cmd);
|
|
gdb_cmd.status().unwrap();
|
|
if gdb_grub {
|
|
// Clean the temporary script file then return.
|
|
std::fs::remove_file(grub_script).unwrap();
|
|
}
|
|
}
|