Implement GDB/LLDB compatible server #3

Merged
SonicSwordcane merged 33 commits from debugger into main 2025-01-19 00:13:43 +00:00
4 changed files with 67 additions and 0 deletions
Showing only changes of commit 0fff4d427f - Show all commits

View File

@ -537,6 +537,12 @@ impl Emulator {
let value = sim.read_register(register); let value = sim.read_register(register);
let _ = done.send(value); let _ = done.send(value);
} }
EmulatorCommand::WriteRegister(sim_id, register, value) => {
let Some(sim) = self.sims.get_mut(sim_id.to_index()) else {
return;
};
sim.write_register(register, value);
}
EmulatorCommand::ReadMemory(sim_id, start, length, mut buffer, done) => { EmulatorCommand::ReadMemory(sim_id, start, length, mut buffer, done) => {
let Some(sim) = self.sims.get_mut(sim_id.to_index()) else { let Some(sim) = self.sims.get_mut(sim_id.to_index()) else {
return; return;
@ -631,6 +637,7 @@ pub enum EmulatorCommand {
DebugContinue(SimId), DebugContinue(SimId),
DebugStep(SimId), DebugStep(SimId),
ReadRegister(SimId, VBRegister, oneshot::Sender<u32>), ReadRegister(SimId, VBRegister, oneshot::Sender<u32>),
WriteRegister(SimId, VBRegister, u32),
ReadMemory(SimId, u32, usize, Vec<u8>, oneshot::Sender<Vec<u8>>), ReadMemory(SimId, u32, usize, Vec<u8>, oneshot::Sender<Vec<u8>>),
AddBreakpoint(SimId, u32), AddBreakpoint(SimId, u32),
RemoveBreakpoint(SimId, u32), RemoveBreakpoint(SimId, u32),

View File

@ -145,6 +145,10 @@ extern "C" {
fn vb_set_option(sim: *mut VB, key: VBOption, value: c_int); fn vb_set_option(sim: *mut VB, key: VBOption, value: c_int);
#[link_name = "vbSetPeer"] #[link_name = "vbSetPeer"]
fn vb_set_peer(sim: *mut VB, peer: *mut VB); fn vb_set_peer(sim: *mut VB, peer: *mut VB);
#[link_name = "vbSetProgramCounter"]
fn vb_set_program_counter(sim: *mut VB, value: u32) -> u32;
#[link_name = "vbSetProgramRegister"]
fn vb_set_program_register(sim: *mut VB, index: c_uint, value: i32) -> i32;
#[link_name = "vbSetReadCallback"] #[link_name = "vbSetReadCallback"]
fn vb_set_read_callback(sim: *mut VB, callback: Option<OnRead>) -> Option<OnRead>; fn vb_set_read_callback(sim: *mut VB, callback: Option<OnRead>) -> Option<OnRead>;
#[link_name = "vbSetSamples"] #[link_name = "vbSetSamples"]
@ -154,6 +158,8 @@ extern "C" {
typ_: VBDataType, typ_: VBDataType,
capacity: c_uint, capacity: c_uint,
) -> c_int; ) -> c_int;
#[link_name = "vbSetSystemRegister"]
fn vb_set_system_register(sim: *mut VB, index: c_uint, value: u32) -> u32;
#[link_name = "vbSetUserData"] #[link_name = "vbSetUserData"]
fn vb_set_user_data(sim: *mut VB, tag: *mut c_void); fn vb_set_user_data(sim: *mut VB, tag: *mut c_void);
#[link_name = "vbSetWriteCallback"] #[link_name = "vbSetWriteCallback"]
@ -447,6 +453,20 @@ impl Sim {
} }
} }
pub fn write_register(&mut self, register: VBRegister, value: u32) {
match register {
VBRegister::Program(index) => unsafe {
vb_set_program_register(self.sim, index, value as i32);
},
VBRegister::System(index) => unsafe {
vb_set_system_register(self.sim, index, value);
},
VBRegister::PC => unsafe {
vb_set_program_counter(self.sim, value);
},
}
}
pub fn read_memory(&mut self, start: u32, length: usize, into: &mut Vec<u8>) { pub fn read_memory(&mut self, start: u32, length: usize, into: &mut Vec<u8>) {
let mut address = start; let mut address = start;
for _ in 0..length { for _ in 0..length {

View File

@ -318,6 +318,32 @@ impl GdbConnection {
} else { } else {
self.response() self.response()
} }
} else if req.match_str("P") {
let mut write_register = || {
let register_index = req.match_hex::<usize>()?;
let register = REGISTERS.get(register_index)?.to_vb_register();
if !req.match_str("=") {
return None;
}
let value = {
let mut buffer = [0; 4];
if !req.match_hex_bytes(&mut buffer) {
return None;
}
u32::from_le_bytes(buffer)
};
self.client.send_command(EmulatorCommand::WriteRegister(
self.sim_id,
register,
value,
));
Some(())
};
if let Some(()) = write_register() {
self.response().write_str("OK")
} else {
self.response()
}
} else if let Some(op) = req.match_some_str(["m", "x"]) { } else if let Some(op) = req.match_some_str(["m", "x"]) {
let mut read_memory = || { let mut read_memory = || {
let start = req.match_hex::<u64>()?; let start = req.match_hex::<u64>()?;

View File

@ -60,6 +60,20 @@ impl Request<'_> {
} }
} }
} }
pub fn match_hex_bytes(&mut self, buffer: &mut [u8]) -> bool {
if self.buffer.len() < buffer.len() * 2 {
return false;
}
for (i, item) in buffer.iter_mut().enumerate() {
match u8::from_radix_16(&self.buffer[(i * 2)..(i * 2) + 2]) {
(byte, 2) => *item = byte,
_ => return false,
};
}
self.buffer = self.buffer.split_at(buffer.len()).1;
true
}
} }
pub struct RequestSource<R> { pub struct RequestSource<R> {