milestone 3
This commit is contained in:
parent
ec51b69948
commit
e125c072fa
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user