milestone 3

This commit is contained in:
ridethepig 2023-03-05 15:51:20 +00:00
parent ec51b69948
commit e125c072fa
4 changed files with 59 additions and 5 deletions

View File

@ -2,18 +2,30 @@ use crate::debugger_command::DebuggerCommand;
use crate::inferior::{Inferior, Status};
use rustyline::error::ReadlineError;
use rustyline::Editor;
use crate::dwarf_data::{DwarfData, Error as DwarfError};
pub struct Debugger {
target: String,
history_path: String,
readline: Editor<()>,
inferior: Option<Inferior>,
debug_data: DwarfData,
}
impl Debugger {
/// Initializes the debugger.
pub fn new(target: &str) -> Debugger {
// TODO (milestone 3): initialize the DwarfData
let debug_data = match DwarfData::from_file(target) {
Ok(val) => val,
Err(DwarfError::ErrorOpeningFile) => {
println!("Could not open file {}", target);
std::process::exit(1);
}
Err(DwarfError::DwarfFormatError(err)) => {
println!("Could not debugging symbols from {}: {:?}", target, err);
std::process::exit(1);
}
};
let history_path = format!("{}/.deet_history", std::env::var("HOME").unwrap());
let mut readline = Editor::<()>::new();
@ -25,6 +37,7 @@ impl Debugger {
history_path,
readline,
inferior: None,
debug_data,
}
}
@ -98,6 +111,12 @@ impl Debugger {
eprintln!("Error running(continue) subprocess");
}
}
DebuggerCommand::Backtrace => {
let res = self.inferior.as_ref().unwrap().print_backtrace(&self.debug_data);
if let Err(res) = res {
eprintln!("Error backtracing: {}", res);
}
}
}
}
}

View File

@ -2,6 +2,7 @@ pub enum DebuggerCommand {
Quit,
Run(Vec<String>),
Continue,
Backtrace,
}
impl DebuggerCommand {
@ -13,9 +14,12 @@ impl DebuggerCommand {
Some(DebuggerCommand::Run(
args.iter().map(|s| s.to_string()).collect(),
))
}
},
"c" | "cont" | "continue" => {
Some(DebuggerCommand::Continue)
},
"bt" | "back" | "backtrace" => {
Some(DebuggerCommand::Backtrace)
}
// Default case:
_ => None,

View File

@ -3,9 +3,12 @@ use nix::sys::signal;
use nix::sys::signal::Signal;
use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
use nix::unistd::Pid;
use std::convert::TryInto;
use std::os::unix::process::CommandExt;
use std::process::Child;
use std::process::Command;
use crate::dwarf_data::DwarfData;
#[derive(Debug)]
pub enum Status {
/// Indicates inferior stopped. Contains the signal that stopped the process, as well as the
@ -52,8 +55,7 @@ impl Inferior {
eprintln!("child stopped by {}, expected SIGTRAP", signal);
return None;
}
}
else {
} else {
eprintln!("child at status ?, expected to stop");
return None;
}
@ -61,7 +63,7 @@ impl Inferior {
// "Inferior::new not implemented! target={}, args={:?}",
// target, args
// );
Some(Inferior {child})
Some(Inferior { child })
}
/// Returns the pid of this inferior.
@ -93,4 +95,31 @@ impl Inferior {
self.child.kill().expect("Failed to kill subprocess");
self.wait(None)
}
pub fn print_backtrace(&self, debug_data: &DwarfData) -> Result<(), nix::Error> {
let regs = ptrace::getregs(self.pid())?;
let mut pc = regs.rip as usize;
let mut bp = regs.rbp as usize;
loop {
let func_name = debug_data
.get_function_from_addr(pc)
.unwrap_or(String::from("Unknown"));
let file_line = debug_data
.get_line_from_addr(pc)
.unwrap_or(crate::dwarf_data::Line {
file: String::from("Unknown"),
number: 0,
address: 0,
});
// println!("[%rip={:#x}] {} ({})", pc, func_name, file_line);
println!("{} ({})", func_name, file_line);
if func_name == "main" {
break;
}
pc = ptrace::read(self.pid(), (bp + 8) as ptrace::AddressType)? as usize;
bp = ptrace::read(self.pid(), bp as ptrace::AddressType)? as usize;
}
Ok(())
}
}

View File

@ -1,6 +1,8 @@
mod debugger;
mod debugger_command;
mod inferior;
mod dwarf_data;
mod gimli_wrapper;
use crate::debugger::Debugger;
use nix::sys::signal::{signal, SigHandler, Signal};