Skip to content

Commit

Permalink
begin gdb client
Browse files Browse the repository at this point in the history
  • Loading branch information
bates64 committed Jan 31, 2024
1 parent 49632d0 commit be58185
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 15 deletions.
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ clap = { version = "4.4.18", features = ["derive"] }
goblin = "0.8"
notify-debouncer-mini = "0.4.1"
paris = { version = "1.5.15", features = [ "macros" ] }
thiserror = "1.0.56"
16 changes: 6 additions & 10 deletions src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use crate::program::{Item, Program};

#[derive(Debug, Clone)]
pub enum Diff<'old, 'new> {
Added(&'new Item<'new>),
Removed(&'old Item<'old>),
Changed(&'old Item<'old>, &'new Item<'new>),
Add(&'new Item<'new>),
Remove(&'old Item<'old>),
Change(&'old Item<'old>, &'new Item<'new>),
}

/// Finds the difference between two [Programs](crate::program::Program).
Expand All @@ -16,27 +16,23 @@ pub fn diff<'old: 'new, 'new>(

// Find items that were removed
for (name, old_item) in &old.items {
if name.contains("main") {
dbg!(name);
}

if !new.items.contains_key(name) {
diffs.push(Diff::Removed(old_item));
diffs.push(Diff::Remove(old_item));
}
}

// Find items that were added
for (name, new_item) in &new.items {
if !old.items.contains_key(name) {
diffs.push(Diff::Added(new_item));
diffs.push(Diff::Add(new_item));
}
}

// Find items that were changed
for (name, old_item) in &old.items {
if let Some(new_item) = new.items.get(name) {
if old_item != new_item {
diffs.push(Diff::Changed(old_item, new_item));
diffs.push(Diff::Change(old_item, new_item));
}
}
}
Expand Down
34 changes: 34 additions & 0 deletions src/gdb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::io::prelude::*;
use std::io::{Read, Result, Write};
use std::net::TcpStream;

/// A connection to a GDB server over the GDB Remote Serial Protocol. This is the client.
///
/// See https://sourceware.org/gdb/current/onlinedocs/gdb.html/Remote-Protocol.html
pub struct Gdb {
stream: TcpStream,
}

// For an example of a GDB server, see https://github.com/ares-emulator/ares/tree/master/nall/gdb

impl Gdb {
pub fn new(address: &str) -> Result<Self> {
let stream = TcpStream::connect(address)?;
Ok(Self { stream })
}

// https://sourceware.org/gdb/current/onlinedocs/gdb.html/Packets.html
pub fn write_packet(&mut self, packet: &[u8]) -> Result<()> {
let checksum = packet
.iter()
.fold(0, |acc: u8, &byte| acc.wrapping_add(byte));

self.stream.write_all(b"$")?;
self.stream.write_all(packet)?;
self.stream.write_all(b"#")?;
self.stream
.write_all(format!("{:02}", checksum).as_bytes())?;

Ok(())
}
}
17 changes: 16 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
mod diff;
mod gdb;
mod patch;
mod program;

use clap::Parser;
Expand Down Expand Up @@ -39,6 +41,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.arg(&args.emulator)
.spawn()?;

// Wait for port to open
// TODO: make this better
for _ in 0..10 {
if std::net::TcpStream::connect("[::1]:9123").is_ok() {
break;
}
std::thread::sleep(Duration::from_millis(100));
}

// Connect to GDB server
let mut gdb = gdb::Gdb::new("[::1]:9123")?;

// Parse ELF file
let elf_file = std::fs::read(&args.elf)?;
let elf = goblin::elf::Elf::parse(&elf_file)?;
Expand Down Expand Up @@ -68,7 +82,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let new_program = program::Program::from(&elf);
println!("New program! Loaded {} items", new_program.items.len());

dbg!(diff::diff(&program, &new_program));
let diff = diff::diff(&program, &new_program);
patch::apply(&mut gdb, &diff)?;
}

Ok(())
Expand Down
33 changes: 33 additions & 0 deletions src/patch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::diff::Diff;
use crate::gdb::Gdb;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error {
#[error("not supported, restart the emulator")]
NotSupported,
}

/// Apply a diff to a process.
pub fn apply(gdb: &mut Gdb, diff: &[Diff<'_, '_>]) -> Result<(), Error> {
for change in diff {
match change {
Diff::Add(_) => return Err(Error::NotSupported),
Diff::Remove(_) => return Err(Error::NotSupported),
Diff::Change(old_item, new_item) => {
if old_item.size != new_item.size {
// TODO resizes
return Err(Error::NotSupported);
}

if old_item.ram_addr != new_item.ram_addr {
// TODO moves
return Err(Error::NotSupported);
}

// TODO
}
}
}
Ok(())
}
8 changes: 4 additions & 4 deletions src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ pub struct Program<'a> {

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Item<'a> {
section_name: Option<&'a str>,
ram_addr: u64,
rom_addr: u64,
size: u64,
pub section_name: Option<&'a str>,
pub ram_addr: u64,
pub rom_addr: u64,
pub size: u64,
}

impl<'a> From<&Elf<'a>> for Program<'a> {
Expand Down

0 comments on commit be58185

Please sign in to comment.