Implement reading from real memory
This commit is contained in:
+64
-16
@@ -135,6 +135,7 @@ struct GdbConnection {
|
||||
ack_messages: bool,
|
||||
request_buf: Vec<u8>,
|
||||
response_buf: Option<Vec<u8>>,
|
||||
memory_buf: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl GdbConnection {
|
||||
@@ -148,6 +149,7 @@ impl GdbConnection {
|
||||
ack_messages: true,
|
||||
request_buf: vec![],
|
||||
response_buf: None,
|
||||
memory_buf: None,
|
||||
}
|
||||
}
|
||||
async fn run(mut self) -> Result<()> {
|
||||
@@ -155,7 +157,7 @@ impl GdbConnection {
|
||||
self.client.send_command(EmulatorCommand::Pause);
|
||||
loop {
|
||||
let mut req = Request::read(&mut self.stream_in, &mut self.request_buf).await?;
|
||||
println!("received {:?}", req);
|
||||
println!("received {:02x?}", req);
|
||||
|
||||
if req.kind == RequestKind::Signal {
|
||||
self.client.send_command(EmulatorCommand::Pause);
|
||||
@@ -173,7 +175,7 @@ impl GdbConnection {
|
||||
} else if req.match_str("qSupported:") {
|
||||
let res = self
|
||||
.response()
|
||||
.write_str("multiprocess+;swbreak+;vContSupported+");
|
||||
.write_str("multiprocess+;swbreak+;vContSupported+;PacketSize=10000");
|
||||
self.send(res).await?;
|
||||
} else if req.match_str("QThreadSuffixSupported")
|
||||
|| req.match_str("QListThreadsInStopReply")
|
||||
@@ -199,8 +201,7 @@ impl GdbConnection {
|
||||
REGISTERS.get(register)
|
||||
};
|
||||
let Some(reg_info) = get_reg_info() else {
|
||||
let res = self.response();
|
||||
self.send(res).await?;
|
||||
self.send_empty().await?;
|
||||
continue;
|
||||
};
|
||||
let res = self.response().write_str(®_info.to_description());
|
||||
@@ -239,39 +240,83 @@ impl GdbConnection {
|
||||
rx.recv().ok()
|
||||
};
|
||||
let Some(value) = read_register() else {
|
||||
let res = self.response();
|
||||
self.send(res).await?;
|
||||
self.send_empty().await?;
|
||||
continue;
|
||||
};
|
||||
let res = self.response().write_hex(value);
|
||||
self.send(res).await?;
|
||||
} else if req.match_str("m") {
|
||||
let mut read_params = || {
|
||||
let mut read_memory = || {
|
||||
let start = req.match_hex::<u32>()?;
|
||||
if !req.match_str(",") {
|
||||
return None;
|
||||
};
|
||||
let size = req.match_hex::<u32>()?;
|
||||
Some((start, size))
|
||||
let mut buf = self.memory_buf.take().unwrap_or_default();
|
||||
buf.clear();
|
||||
let (tx, rx) = ::oneshot::channel();
|
||||
self.client.send_command(EmulatorCommand::ReadMemory(
|
||||
self.sim_id,
|
||||
start..(start + size),
|
||||
buf,
|
||||
tx,
|
||||
));
|
||||
rx.recv().ok()
|
||||
};
|
||||
let Some((start, size)) = read_params() else {
|
||||
let res = self.response();
|
||||
self.send(res).await?;
|
||||
let Some(memory) = read_memory() else {
|
||||
self.send_empty().await?;
|
||||
continue;
|
||||
};
|
||||
let mut res = self.response();
|
||||
for i in 0..size {
|
||||
res = res.write_hex((start + i) as u8);
|
||||
for byte in &memory {
|
||||
res = res.write_hex(*byte);
|
||||
}
|
||||
self.memory_buf = Some(memory);
|
||||
self.send(res).await?;
|
||||
} else if req.match_str("x") {
|
||||
let mut read_memory = || {
|
||||
let start = req.match_hex::<u32>()?;
|
||||
if !req.match_str(",") {
|
||||
return None;
|
||||
};
|
||||
let size = req.match_hex::<u32>()?;
|
||||
let mut buf = self.memory_buf.take().unwrap_or_default();
|
||||
buf.clear();
|
||||
let (tx, rx) = ::oneshot::channel();
|
||||
self.client.send_command(EmulatorCommand::ReadMemory(
|
||||
self.sim_id,
|
||||
start..(start + size),
|
||||
buf,
|
||||
tx,
|
||||
));
|
||||
rx.recv().ok()
|
||||
};
|
||||
let Some(memory) = read_memory() else {
|
||||
self.send_empty().await?;
|
||||
continue;
|
||||
};
|
||||
let mut res = self.response();
|
||||
if memory.is_empty() {
|
||||
res = res.write_str("OK");
|
||||
} else {
|
||||
for byte in &memory {
|
||||
res = res.write_byte(*byte);
|
||||
}
|
||||
}
|
||||
self.memory_buf = Some(memory);
|
||||
self.send(res).await?;
|
||||
} else {
|
||||
// unrecognized command
|
||||
let res = self.response();
|
||||
self.send(res).await?;
|
||||
self.send_empty().await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_empty(&mut self) -> std::io::Result<()> {
|
||||
let res = self.response();
|
||||
self.send(res).await
|
||||
}
|
||||
|
||||
fn response(&mut self) -> Response {
|
||||
Response::new(
|
||||
self.response_buf.take().unwrap_or_default(),
|
||||
@@ -281,7 +326,10 @@ impl GdbConnection {
|
||||
|
||||
async fn send(&mut self, res: Response) -> std::io::Result<()> {
|
||||
let buffer = res.finish();
|
||||
println!("{:?}", std::str::from_utf8(&buffer));
|
||||
match std::str::from_utf8(&buffer) {
|
||||
Ok(text) => println!("response: {text}"),
|
||||
Err(_) => println!("response: {buffer:02x?}"),
|
||||
}
|
||||
self.stream_out.write_all(&buffer).await?;
|
||||
self.response_buf = Some(buffer);
|
||||
self.stream_out.flush().await
|
||||
|
||||
Reference in New Issue
Block a user