From e125c072fa67d332690049f998ecdfe6eee5ec29 Mon Sep 17 00:00:00 2001 From: ridethepig Date: Sun, 5 Mar 2023 15:51:20 +0000 Subject: [PATCH] milestone 3 --- proj-1/deet/src/debugger.rs | 21 ++++++++++++++++- proj-1/deet/src/debugger_command.rs | 6 ++++- proj-1/deet/src/inferior.rs | 35 ++++++++++++++++++++++++++--- proj-1/deet/src/main.rs | 2 ++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/proj-1/deet/src/debugger.rs b/proj-1/deet/src/debugger.rs index 9622477..055f8b8 100644 --- a/proj-1/deet/src/debugger.rs +++ b/proj-1/deet/src/debugger.rs @@ -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, + 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); + } + } } } } diff --git a/proj-1/deet/src/debugger_command.rs b/proj-1/deet/src/debugger_command.rs index 01a7494..3c32d92 100644 --- a/proj-1/deet/src/debugger_command.rs +++ b/proj-1/deet/src/debugger_command.rs @@ -2,6 +2,7 @@ pub enum DebuggerCommand { Quit, Run(Vec), 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, diff --git a/proj-1/deet/src/inferior.rs b/proj-1/deet/src/inferior.rs index 3bceee4..c242d33 100644 --- a/proj-1/deet/src/inferior.rs +++ b/proj-1/deet/src/inferior.rs @@ -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(()) + } } diff --git a/proj-1/deet/src/main.rs b/proj-1/deet/src/main.rs index a944ed0..31405e9 100644 --- a/proj-1/deet/src/main.rs +++ b/proj-1/deet/src/main.rs @@ -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};