Implement GDB/LLDB compatible server #3
|
@ -537,6 +537,12 @@ impl Emulator {
|
|||
let value = sim.read_register(register);
|
||||
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) => {
|
||||
let Some(sim) = self.sims.get_mut(sim_id.to_index()) else {
|
||||
return;
|
||||
|
@ -631,6 +637,7 @@ pub enum EmulatorCommand {
|
|||
DebugContinue(SimId),
|
||||
DebugStep(SimId),
|
||||
ReadRegister(SimId, VBRegister, oneshot::Sender<u32>),
|
||||
WriteRegister(SimId, VBRegister, u32),
|
||||
ReadMemory(SimId, u32, usize, Vec<u8>, oneshot::Sender<Vec<u8>>),
|
||||
AddBreakpoint(SimId, u32),
|
||||
RemoveBreakpoint(SimId, u32),
|
||||
|
|
|
@ -145,6 +145,10 @@ extern "C" {
|
|||
fn vb_set_option(sim: *mut VB, key: VBOption, value: c_int);
|
||||
#[link_name = "vbSetPeer"]
|
||||
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"]
|
||||
fn vb_set_read_callback(sim: *mut VB, callback: Option<OnRead>) -> Option<OnRead>;
|
||||
#[link_name = "vbSetSamples"]
|
||||
|
@ -154,6 +158,8 @@ extern "C" {
|
|||
typ_: VBDataType,
|
||||
capacity: c_uint,
|
||||
) -> c_int;
|
||||
#[link_name = "vbSetSystemRegister"]
|
||||
fn vb_set_system_register(sim: *mut VB, index: c_uint, value: u32) -> u32;
|
||||
#[link_name = "vbSetUserData"]
|
||||
fn vb_set_user_data(sim: *mut VB, tag: *mut c_void);
|
||||
#[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>) {
|
||||
let mut address = start;
|
||||
for _ in 0..length {
|
||||
|
|
|
@ -318,6 +318,32 @@ impl GdbConnection {
|
|||
} else {
|
||||
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"]) {
|
||||
let mut read_memory = || {
|
||||
let start = req.match_hex::<u64>()?;
|
||||
|
|
|
@ -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> {
|
||||
|
|
Loading…
Reference in New Issue