Implement GDB/LLDB compatible server #3

Merged
SonicSwordcane merged 33 commits from debugger into main 2025-01-19 00:13:43 +00:00
1 changed files with 58 additions and 8 deletions
Showing only changes of commit 24487b21b7 - Show all commits

View File

@ -71,7 +71,6 @@ async fn run_server(
port: u16, port: u16,
status: &Mutex<GdbServerStatus>, status: &Mutex<GdbServerStatus>,
) { ) {
client.send_command(EmulatorCommand::Pause);
let Some(stream) = try_connect(port, status).await else { let Some(stream) = try_connect(port, status).await else {
return; return;
}; };
@ -142,43 +141,88 @@ impl GdbConnection {
} }
async fn run(mut self) -> Result<()> { async fn run(mut self) -> Result<()> {
println!("Connected for {}", self.sim_id); println!("Connected for {}", self.sim_id);
self.client.send_command(EmulatorCommand::Resume); self.client.send_command(EmulatorCommand::Pause);
loop { loop {
let message = self.read_message().await?; let message = self.read_message().await?;
println!("received {:?}", message); println!("received {:?}", message);
let mut res = ResponseWriter::new(&mut self.stream_out); //let mut res = ResponseWriter::new(&mut self.stream_out);
res.init(self.ack_messages).await?; //res.init(self.ack_messages).await?;
let body = match &message { let body = match &message {
Message::String(str) => str.as_str(), Message::String(str) => str.as_str(),
Message::Signal => { Message::Signal => {
// TODO: handle this self.client.send_command(EmulatorCommand::Pause);
let mut res = self.respond().await?;
res.write_str("T05;thread:p1.t1;threads:p1.t1;reason:trap;")
.await?;
res.send().await?; res.send().await?;
continue; continue;
} }
}; };
if body == "QStartNoAckMode" { if body == "QStartNoAckMode" {
let mut res = ResponseWriter::new(&mut self.stream_out);
res.init(self.ack_messages).await?;
self.ack_messages = false; self.ack_messages = false;
res.send_ok().await?; res.send_ok().await?;
} else if body.starts_with("qSupported:") { } else if body.starts_with("qSupported:") {
let mut res = self.respond().await?;
res.write_str("multiprocess+;swbreak+;vContSupported+") res.write_str("multiprocess+;swbreak+;vContSupported+")
.await?; .await?;
res.send().await?; res.send().await?;
} else if body == "QThreadSuffixSupported" || body == "QListThreadsInStopReply" { } else if body == "QThreadSuffixSupported"
|| body == "QListThreadsInStopReply"
|| body == "QEnableErrorStrings"
{
let res = self.respond().await?;
res.send_ok().await?; res.send_ok().await?;
} else if body == "qHostInfo" || body == "qProcessInfo" { } else if body == "qHostInfo" {
let mut res = self.respond().await?;
res.write_str(&format!( res.write_str(&format!(
"triple:{};endian:little;ptrsize:4;", "triple:{};endian:little;ptrsize:4;",
hex::encode("v810-unknown-vb") hex::encode("v810-unknown-vb")
)) ))
.await?; .await?;
res.send().await?; res.send().await?;
} else if body == "qProcessInfo" {
let mut res = self.respond().await?;
res.write_str(&format!(
"pid:1;triple:{};endian:little;ptrsize:4;",
hex::encode("v810-unknown-vb")
))
.await?;
res.send().await?;
} else if body == "vCont?" {
let mut res = self.respond().await?;
res.write_str("vCont;c;").await?;
res.send().await?;
} else if body == "qC" {
// The v810 has no threads, so report that the "current thread" is 1.
let mut res = self.respond().await?;
res.write_str("QCp1.t1").await?;
res.send().await?;
} else if body == "qfThreadInfo" {
let mut res = self.respond().await?;
res.write_str("mp1.t1").await?;
res.send().await?;
} else if body == "qsThreadInfo" {
let mut res = self.respond().await?;
res.write_str("l").await?;
res.send().await?;
} else if body == "k" { } else if body == "k" {
return Ok(()); bail!("debug process was killed");
} else if body == "?" {
let mut res = self.respond().await?;
res.write_str("T00;thread:p1.t1;threads:p1.t1;").await?;
res.send().await?;
} else if body == "c" || body.starts_with("vCont;c:") {
// Continue running the game until we're interrupted again
self.client.send_command(EmulatorCommand::Resume);
continue;
} else { } else {
// unrecognized command // unrecognized command
let res = self.respond().await?;
res.send().await?; res.send().await?;
} }
} }
@ -235,6 +279,12 @@ impl GdbConnection {
async fn read_byte(&mut self) -> std::io::Result<u8> { async fn read_byte(&mut self) -> std::io::Result<u8> {
self.stream_in.read_u8().await self.stream_in.read_u8().await
} }
async fn respond(&mut self) -> std::io::Result<ResponseWriter<'_>> {
let mut res = ResponseWriter::new(&mut self.stream_out);
res.init(self.ack_messages).await?;
Ok(res)
}
} }
struct ResponseWriter<'a> { struct ResponseWriter<'a> {