Support watchpoints

This commit is contained in:
2025-01-13 00:30:47 -05:00
parent fd7298d24e
commit af9a4ae8ee
4 changed files with 527 additions and 32 deletions
+96 -17
View File
@@ -13,7 +13,9 @@ use tokio::{
sync::{mpsc, oneshot},
};
use crate::emulator::{DebugEvent, DebugStopReason, EmulatorClient, EmulatorCommand, SimId};
use crate::emulator::{
DebugEvent, DebugStopReason, EmulatorClient, EmulatorCommand, SimId, VBWatchpointType,
};
mod registers;
mod request;
@@ -187,7 +189,7 @@ impl GdbConnection {
}
self.stop_reason = Some(reason);
self.response()
.write_str(debug_stop_reason_string(self.stop_reason))
.write_str(&debug_stop_reason_string(self.stop_reason))
}
};
Some(res)
@@ -251,7 +253,7 @@ impl GdbConnection {
bail!("debug process was killed");
} else if req.match_str("?") {
self.response()
.write_str(debug_stop_reason_string(self.stop_reason))
.write_str(&debug_stop_reason_string(self.stop_reason))
} else if req.match_some_str(["c", "vCont;c:"]).is_some() {
self.client
.send_command(EmulatorCommand::DebugContinue(self.sim_id));
@@ -329,18 +331,68 @@ impl GdbConnection {
} else {
self.response()
}
} else if req.match_str("Z0,") {
if let Some(address) = req.match_hex() {
self.client
.send_command(EmulatorCommand::AddBreakpoint(self.sim_id, address));
} else if req.match_str("Z") {
let mut parse_request = || {
let type_ = req.match_hex::<u8>()?;
if !req.match_str(",") {
return None;
}
let address = req.match_hex()?;
if type_ == 0 || type_ == 1 {
return Some(EmulatorCommand::AddBreakpoint(self.sim_id, address));
}
if !req.match_str(",") {
return None;
}
let length = req.match_hex()?;
let watch = match type_ {
2 => VBWatchpointType::Write,
3 => VBWatchpointType::Read,
4 => VBWatchpointType::Access,
_ => return None,
};
Some(EmulatorCommand::AddWatchpoint(
self.sim_id,
address,
length,
watch,
))
};
if let Some(command) = parse_request() {
self.client.send_command(command);
self.response().write_str("OK")
} else {
self.response()
}
} else if req.match_str("z0,") {
if let Some(address) = req.match_hex() {
self.client
.send_command(EmulatorCommand::RemoveBreakpoint(self.sim_id, address));
} else if req.match_str("z") {
let mut parse_request = || {
let type_ = req.match_hex::<u8>()?;
if !req.match_str(",") {
return None;
}
let address = req.match_hex()?;
if type_ == 0 || type_ == 1 {
return Some(EmulatorCommand::RemoveBreakpoint(self.sim_id, address));
}
if !req.match_str(",") {
return None;
}
let length = req.match_hex()?;
let watch = match type_ {
2 => VBWatchpointType::Write,
3 => VBWatchpointType::Read,
4 => VBWatchpointType::Access,
_ => return None,
};
Some(EmulatorCommand::RemoveWatchpoint(
self.sim_id,
address,
length,
watch,
))
};
if let Some(command) = parse_request() {
self.client.send_command(command);
self.response().write_str("OK")
} else {
self.response()
@@ -367,11 +419,38 @@ impl Drop for GdbConnection {
}
}
fn debug_stop_reason_string(reason: Option<DebugStopReason>) -> &'static str {
match reason {
Some(DebugStopReason::Trace) => "T05;thread:p1.t1;threads:p1.t1;reason:trace;",
Some(DebugStopReason::Breakpoint) => "T05;thread:p1.t1;threads:p1.t1;reason:breakpoint;",
Some(DebugStopReason::Trapped) => "T05;swbreak;thread:p1.t1;threads:p1.t1;reason:trap;",
None => "T00;thread:p1.t1;threads:p1.t1;",
fn debug_stop_reason_string(reason: Option<DebugStopReason>) -> String {
let mut result = String::new();
result += if reason.is_some() { "T05;" } else { "T00;" };
if let Some(DebugStopReason::Breakpoint) = reason {
result += "swbreak;";
}
if let Some(DebugStopReason::Watchpoint(watch, address)) = reason {
result += match watch {
VBWatchpointType::Write => "watch:",
VBWatchpointType::Read => "rwatch:",
VBWatchpointType::Access => "awatch:",
};
result += &format!("{address:08x};");
}
result += "thread:p1.t1;threads:p1.t1;";
if let Some(reason) = reason {
result += "reason:";
result += match reason {
DebugStopReason::Trace => "trace;",
DebugStopReason::Breakpoint => "breakpoint;",
DebugStopReason::Watchpoint(_, _) => "watchpoint;",
DebugStopReason::Trapped => "trap;",
};
}
if let Some(DebugStopReason::Watchpoint(_, address)) = reason {
result += "description:";
result += &hex::encode(address.to_string());
result += ";";
}
result
}