Implement writing memory
This commit is contained in:
+50
-14
@@ -346,22 +346,9 @@ impl GdbConnection {
|
||||
}
|
||||
} else if let Some(op) = req.match_some_str(["m", "x"]) {
|
||||
let mut read_memory = || {
|
||||
let start = req.match_hex::<u64>()?;
|
||||
if !req.match_str(",") {
|
||||
return None;
|
||||
};
|
||||
let length = req.match_hex::<usize>()?;
|
||||
|
||||
let (start, length) = parse_memory_range(&mut req)?;
|
||||
let mut buf = self.memory_buf.take().unwrap_or_default();
|
||||
buf.clear();
|
||||
|
||||
// The v810 has a 32-bit address space.
|
||||
// Addresses wrap within that space, but we don't need to implement that for 64-bit addresses.
|
||||
// Just refuse to return any info for addresses above 0xffffffff.
|
||||
let Ok(start) = u32::try_from(start) else {
|
||||
return Some(buf);
|
||||
};
|
||||
let length = length.min((u32::MAX - start) as usize + 1);
|
||||
if length == 0 {
|
||||
return Some(buf);
|
||||
}
|
||||
@@ -395,6 +382,38 @@ impl GdbConnection {
|
||||
} else {
|
||||
self.response()
|
||||
}
|
||||
} else if let Some(op) = req.match_some_str(["M", "X"]) {
|
||||
let mut write_memory = || {
|
||||
let (start, length) = parse_memory_range(&mut req)?;
|
||||
if length == 0 {
|
||||
return Some(());
|
||||
}
|
||||
if !req.match_str(":") {
|
||||
return None;
|
||||
}
|
||||
let mut buf = self.memory_buf.take().unwrap_or_default();
|
||||
buf.resize(length, 0);
|
||||
let successful_read = if op == "M" {
|
||||
req.match_hex_bytes(&mut buf)
|
||||
} else {
|
||||
req.match_bytes(&mut buf)
|
||||
};
|
||||
if !successful_read {
|
||||
self.memory_buf = Some(buf);
|
||||
return None;
|
||||
}
|
||||
let (tx, rx) = ::oneshot::channel();
|
||||
self.client
|
||||
.send_command(EmulatorCommand::WriteMemory(self.sim_id, start, buf, tx));
|
||||
let buf = rx.recv().ok()?;
|
||||
self.memory_buf = Some(buf);
|
||||
Some(())
|
||||
};
|
||||
if write_memory().is_some() {
|
||||
self.response().write_str("OK")
|
||||
} else {
|
||||
self.response()
|
||||
}
|
||||
} else if req.match_str("Z") {
|
||||
let mut parse_request = || {
|
||||
let type_ = req.match_hex::<u8>()?;
|
||||
@@ -483,6 +502,23 @@ impl Drop for GdbConnection {
|
||||
}
|
||||
}
|
||||
|
||||
// parse a memory range into a start and a length.
|
||||
fn parse_memory_range(req: &mut Request<'_>) -> Option<(u32, usize)> {
|
||||
let start = req.match_hex::<u64>()?;
|
||||
if !req.match_str(",") {
|
||||
return None;
|
||||
};
|
||||
let length = req.match_hex::<usize>()?;
|
||||
let Ok(start) = u32::try_from(start) else {
|
||||
// The v810 has a 32-bit address space.
|
||||
// Addresses wrap within that space, but we don't need to implement that for 64-bit addresses.
|
||||
// Just refuse to return any info for addresses above 0xffffffff.
|
||||
return Some((0, 0));
|
||||
};
|
||||
let length = length.min((u32::MAX - start) as usize + 1);
|
||||
Some((start, length))
|
||||
}
|
||||
|
||||
fn debug_stop_reason_string(reason: Option<DebugStopReason>) -> String {
|
||||
let mut result = String::new();
|
||||
result += if reason.is_some() { "T05;" } else { "T00;" };
|
||||
|
||||
Reference in New Issue
Block a user