Skip to content

Commit

Permalink
refactor(debugger): use custom errors instead of anyhow errors
Browse files Browse the repository at this point in the history
  • Loading branch information
godzie44 committed Sep 30, 2023
1 parent 9e8a686 commit d2d810e
Show file tree
Hide file tree
Showing 37 changed files with 1,030 additions and 803 deletions.
55 changes: 37 additions & 18 deletions src/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@ use super::debugger::command::Continue;
use crate::console::editor::{create_editor, CommandCompleter, RLHelper};
use crate::console::help::*;
use crate::console::hook::TerminalHook;
use crate::console::print::style::{AddressView, FilePathView, FunctionNameView, KeywordView};
use crate::console::print::style::{
AddressView, ErrorView, FilePathView, FunctionNameView, KeywordView,
};
use crate::console::print::ExternalPrinter;
use crate::console::variable::render_variable_ir;
use crate::debugger;
use crate::debugger::command::r#break::{Break, HandlingResult};
use crate::debugger::command::{
r#break, Arguments, Backtrace, Command, Frame, FrameResult, Run, SharedLib, StepI, StepInto,
StepOut, StepOver, Symbol, ThreadCommand, ThreadResult, Variables,
r#break, Arguments, Backtrace, Command, Frame, FrameResult, HandlingError, Run, SharedLib,
StepI, StepInto, StepOut, StepOver, Symbol, ThreadCommand, ThreadResult, Variables,
};
use crate::debugger::process::{Child, Installed};
use crate::debugger::variable::render::RenderRepr;
use crate::debugger::variable::select::{Expression, VariableSelector};
use crate::debugger::{command, Debugger};
use command::{Memory, Register};
use crossterm::style::Stylize;
use debugger::Error;
use nix::sys::signal::{kill, Signal};
use nix::unistd::Pid;
use os_pipe::PipeReader;
Expand All @@ -25,6 +28,7 @@ use rustyline::error::ReadlineError;
use rustyline::history::MemHistory;
use rustyline::Editor;
use std::io::{BufRead, BufReader};
use std::process::exit;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Receiver, SyncSender};
use std::sync::{mpsc, Arc, Mutex};
Expand Down Expand Up @@ -206,16 +210,19 @@ struct AppLoop {
}

impl AppLoop {
fn yes(&self, question: &str) -> anyhow::Result<bool> {
fn yes(&self, question: &str) -> bool {
self.printer.print(question);

let act = self.control_rx.recv()?;
let act = self
.control_rx
.recv()
.expect("unexpected sender disconnect");
match act {
Control::Cmd(cmd) => {
let cmd = cmd.to_lowercase();
Ok(cmd == "y" || cmd == "yes")
cmd == "y" || cmd == "yes"
}
Control::Terminate => Ok(false),
Control::Terminate => false,
}
}

Expand All @@ -233,7 +240,7 @@ impl AppLoop {
Ok(())
}

fn handle_command(&mut self, cmd: &str) -> anyhow::Result<()> {
fn handle_command(&mut self, cmd: &str) -> Result<(), HandlingError> {
match Command::parse(cmd)? {
Command::PrintVariables(print_var_command) => Variables::new(&self.debugger)
.handle(print_var_command)?
Expand Down Expand Up @@ -326,7 +333,7 @@ impl AppLoop {
static ALREADY_RUN: AtomicBool = AtomicBool::new(false);

if ALREADY_RUN.load(Ordering::Acquire) {
if self.yes("Restart program? (y or n)")? {
if self.yes("Restart program? (y or n)") {
Run::new(&mut self.debugger).restart()?
}
} else {
Expand Down Expand Up @@ -386,17 +393,15 @@ impl AppLoop {
Ok(r#break::HandlingResult::Dump(brkpts)) => brkpts
.iter()
.for_each(|brkpt| print_bp("- Breakpoint", brkpt)),
Err(r#break::BreakpointError::SetError(
r#break::SetBreakpointError::PlaceNotFound(_),
)) => {
Err(Error::NoSuitablePlace) => {
if self.yes(
"Add deferred breakpoint for future shared library load? (y or n)",
)? {
) {
brkpt_cmd = BreakpointCommand::AddDeferred(
brkpt_cmd
.breakpoint()
.expect("unreachable: deferred breakpoint must based on exists breakpoint"),
);
brkpt_cmd
.breakpoint()
.expect("unreachable: deferred breakpoint must based on exists breakpoint"),
);
continue;
}
}
Expand Down Expand Up @@ -497,7 +502,21 @@ impl AppLoop {
Control::Cmd(command) => {
thread::sleep(Duration::from_millis(1));
if let Err(e) = self.handle_command(&command) {
self.printer.print(format!("error: {:#}", e));
match e {
HandlingError::Parser(_) => {
self.printer.print(ErrorView::from(e));
}
HandlingError::Debugger(ref err) if err.is_fatal() => {
self.printer.print(ErrorView::from("shutdown debugger"));
self.printer
.print(ErrorView::from(format!("fatal debugger error: {e:#}")));
exit(0);
}
HandlingError::Debugger(_) => {
self.printer
.print(ErrorView::from(format!("debugger error: {e:#}")));
}
}
}
}
Control::Terminate => {
Expand Down
5 changes: 3 additions & 2 deletions src/console/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ impl ExternalPrinter {
Ok(Self { printer: None })
}

pub fn print(&self, msg: impl Into<String>) {
let msg = msg.into();
pub fn print(&self, msg: impl ToString) {
let msg = msg.to_string();
match &self.printer {
None => {
println!("{msg}")
Expand Down Expand Up @@ -105,4 +105,5 @@ pub mod style {
view_struct!(FilePathView, Color::Green);
view_struct!(FunctionNameView, Color::Yellow);
view_struct!(KeywordView, Color::Magenta);
view_struct!(ErrorView, Color::Red);
}
34 changes: 32 additions & 2 deletions src/debugger/address.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::debugger::debugee::dwarf::DebugInformation;
use crate::debugger::debugee::Debugee;
use crate::debugger::error::Error;
use gimli::Range;
use std::fmt::{Display, Formatter};

Expand All @@ -13,7 +15,7 @@ impl RelocatedAddress {
GlobalAddress(self.0 - offset)
}

pub fn into_global(self, debugee: &Debugee) -> anyhow::Result<GlobalAddress> {
pub fn into_global(self, debugee: &Debugee) -> Result<GlobalAddress, Error> {
Ok(self.remove_vas_region_offset(debugee.mapping_offset_for_pc(self)?))
}

Expand Down Expand Up @@ -74,10 +76,38 @@ impl Display for RelocatedAddress {
pub struct GlobalAddress(usize);

impl GlobalAddress {
pub fn relocate(self, offset: usize) -> RelocatedAddress {
fn relocate(self, offset: usize) -> RelocatedAddress {
RelocatedAddress(self.0 + offset)
}

/// Relocate address to VAS segment determined by debug information.
///
/// # Errors
///
/// Return error if no VAS offset for debug information.
pub fn relocate_to_segment(
self,
debugee: &Debugee,
segment: &DebugInformation,
) -> Result<RelocatedAddress, Error> {
let offset = debugee.mapping_offset_for_file(segment)?;
Ok(self.relocate(offset))
}

/// Relocate address to VAS segment determined by another address.
///
/// # Errors
///
/// Return error if no VAS offset for address.
pub fn relocate_to_segment_by_pc(
self,
debugee: &Debugee,
pc: RelocatedAddress,
) -> Result<RelocatedAddress, Error> {
let offset = debugee.mapping_offset_for_pc(pc)?;
Ok(self.relocate(offset))
}

pub fn in_range(self, range: &Range) -> bool {
u64::from(self) >= range.begin && u64::from(self) < range.end
}
Expand Down
Loading

0 comments on commit d2d810e

Please sign in to comment.