diff options
| -rw-r--r-- | Cargo.lock | 7 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/main.rs | 9 | ||||
| -rw-r--r-- | src/registers.rs | 28 | ||||
| -rw-r--r-- | src/trace.rs | 9 | ||||
| -rw-r--r-- | src/ui.rs | 7 | 
6 files changed, 50 insertions, 11 deletions
@@ -239,6 +239,12 @@ dependencies = [  ]  [[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]]  name = "parking_lot"  version = "0.12.1"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -332,6 +338,7 @@ dependencies = [   "crossterm",   "fork",   "nix", + "owo-colors",   "ratatui",  ] @@ -12,4 +12,5 @@ clap = { version = "4.4.6", features = ["derive"] }  crossterm = "0.27.0"  fork = "0.1.22"  nix = { version = "0.27.1", features = ["ptrace"] } +owo-colors = "3.5.0"  ratatui = "0.23.0" diff --git a/src/main.rs b/src/main.rs index 9e025b7..19a9533 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,13 +37,14 @@ fn main() -> anyhow::Result<()> {          Ok(Fork::Parent(child)) => Pid::from_raw(child),          Err(err) => panic!("fork() failed: {err}"),      }; -    let output = trace(pid, args.file_to_print)?; -    let lines = str::from_utf8(&output)?.trim(); +    let registers = trace(pid, args.file_to_print)?;      if !args.no_tui { -        run_tui(pid, lines)?; +        run_tui(pid, ®isters)?;      } else { -        writeln!(io::stdout(), "{lines}")?; +        for line in registers { +            writeln!(io::stdout(), "{}", line.output())?; +        }      }      Ok(()) diff --git a/src/registers.rs b/src/registers.rs index 80b4a9b..d73424d 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -1,4 +1,9 @@  use nix::libc::user_regs_struct; +use owo_colors::OwoColorize; +use ratatui::{ +    prelude::{Line, Span, Style}, +    style::Modifier, +};  /// Struct used to manipulate registers data from https://docs.rs/libc/0.2.147/libc/struct.user_regs_struct.html  pub struct RegistersData { @@ -25,7 +30,28 @@ impl RegistersData {      pub fn output(&self) -> String {          format!(              "{}({:x}, {:x}, {:x}, ...) = {:x}", -            self.orig_rax, self.rdi, self.rsi, self.rdx, self.rax +            self.orig_rax.bold(), +            self.rdi, +            self.rsi, +            self.rdx, +            self.rax          )      } + +    /// Returns a good line for TUI +    pub fn output_ui(&self) -> Line { +        Line::from(vec![ +            Span::styled( +                format!("{}", self.orig_rax), +                Style::default().add_modifier(Modifier::BOLD), +            ), +            Span::styled( +                format!( +                    "({:x}, {:x}, {:x}, ...) = {:x}", +                    self.rdi, self.rsi, self.rdx, self.rax +                ), +                Style::default(), +            ), +        ]) +    }  } diff --git a/src/trace.rs b/src/trace.rs index 399f1c6..3612519 100644 --- a/src/trace.rs +++ b/src/trace.rs @@ -25,8 +25,8 @@ pub fn exec(command: &str) -> anyhow::Result<()> {      Ok(())  } -/// Trace a process with `pid` ID -pub fn trace(pid: Pid, file_to_print: Option<String>) -> anyhow::Result<Vec<u8>> { +/// Trace a process with `pid` ID and returns a list of `RegistersData` +pub fn trace(pid: Pid, file_to_print: Option<String>) -> anyhow::Result<Vec<RegistersData>> {      // Since you have to do 2 syscalls (start and end) you have to alternate the print value,      // because it could be equals except for the `rax` register.      let mut have_to_print = true; @@ -41,7 +41,7 @@ pub fn trace(pid: Pid, file_to_print: Option<String>) -> anyhow::Result<Vec<u8>>          f = Some(File::create(filename)?);      } -    let mut lines = Vec::new(); +    let mut lines: Vec<RegistersData> = Vec::new();      loop {          have_to_print ^= true; @@ -59,11 +59,12 @@ pub fn trace(pid: Pid, file_to_print: Option<String>) -> anyhow::Result<Vec<u8>>                      Signal::SIGTRAP => {                          if have_to_print {                              let reg = RegistersData::new(ptrace::getregs(pid)?); -                            writeln!(lines, "{}", reg.output())?;                              if let Some(ref mut f) = f {                                  writeln!(f, "{}", reg.output())?;                              } + +                            lines.push(reg);                          }                      }                      _ => {} @@ -1,3 +1,4 @@ +use crate::registers::RegistersData;  use crossterm::{      event::{self, Event, KeyCode},      terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, @@ -55,19 +56,21 @@ fn handle_events(ui: &mut UI) -> io::Result<bool> {      Ok(false)  } -pub fn run_tui(pid: Pid, lines: &str) -> anyhow::Result<()> { +pub fn run_tui(pid: Pid, registers: &Vec<RegistersData>) -> anyhow::Result<()> {      enable_raw_mode()?;      stdout().execute(EnterAlternateScreen)?;      let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;      let mut ui = UI::new(); -    ui.max_lines = lines.split('\n').count() + 1; +    ui.max_lines = registers.len() + 1;      let mut should_quit = false;      while !should_quit {          ui.height = terminal.get_frame().size().height as usize;          terminal.draw(move |frame| {              let size = frame.size(); +            let lines: Vec<Line> = registers.iter().map(|x| x.output_ui()).collect(); +              frame.render_widget(                  Paragraph::new(lines)                      .block(  |