Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
271 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use gdbstub::target; | ||
use gdbstub::target::ext::register_info::Register; | ||
|
||
use crate::gdb::Emu; | ||
|
||
// This implementation is for illustrative purposes only. If the .xml target description is used, the qRegisterInfo Packet is not necessary. (Note: This is an LLDB specific packet) | ||
|
||
// We have r0-pc from 0-16 but cpsr is at offset 25*4 in the 'g'/'G' packet, so we add 8 padding | ||
// registers here. Please see gdbstub/examples/armv4t/gdb/target_description_xml_override.rs for | ||
// more info. | ||
const MAX_REG_NUM: u8 = 17 + 8; | ||
const SP: u8 = 13; | ||
const PC: u8 = 15; | ||
const CPSR: u8 = 25; | ||
const REG_NAMES: &[&str] = &[ | ||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", | ||
"pc", "padding", "padding", "padding", "padding", "padding", "padding", "padding", "padding", | ||
"padding", "cpsr", | ||
]; | ||
|
||
impl target::ext::register_info::RegisterInfo for Emu { | ||
fn get_register_info(&mut self, reg_id: u8) -> Result<Option<Register>, Self::Error> { | ||
match reg_id { | ||
0..=MAX_REG_NUM => { | ||
let name = REG_NAMES[reg_id as usize]; | ||
let encoding = if reg_id < 16 || reg_id == CPSR { | ||
"uint" | ||
} else { | ||
"vector" | ||
}; | ||
let format = if reg_id < 16 || reg_id == CPSR { | ||
"hex" | ||
} else { | ||
"vector-uint8" | ||
}; | ||
let set = if reg_id < 16 || reg_id == CPSR { | ||
"General Purpose Registers" | ||
} else { | ||
"Floating Point Registers" | ||
}; | ||
let generic = if reg_id == SP { | ||
Some("sp") | ||
} else if reg_id == PC { | ||
Some("pc") | ||
} else { | ||
None | ||
}; | ||
Ok(Some(Register { | ||
name, | ||
alt_name: name, | ||
bitsize: 32, | ||
offset: (reg_id as u32) * 4, | ||
encoding, | ||
format, | ||
set, | ||
gcc: None, | ||
dwarf: Some(reg_id as u32), | ||
generic, | ||
container_regs: None, | ||
invalidate_regs: None, | ||
})) | ||
} | ||
// Will end the 'qRegisterInfo' query | ||
_ => Ok(None), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
use super::prelude::*; | ||
|
||
#[derive(Debug)] | ||
pub struct qRegisterInfo { | ||
pub reg_id: u8, | ||
} | ||
|
||
impl<'a> ParseCommand<'a> for qRegisterInfo { | ||
#[inline(always)] | ||
fn from_packet(buf: PacketBuf<'a>) -> Option<Self> { | ||
let body = buf.into_body(); | ||
|
||
let reg_id = decode_hex(body).ok()?; | ||
|
||
Some(qRegisterInfo { reg_id }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
use super::prelude::*; | ||
use crate::protocol::commands::ext::RegisterInfo; | ||
|
||
impl<T: Target, C: Connection> GdbStubImpl<T, C> { | ||
pub(crate) fn handle_register_info( | ||
&mut self, | ||
res: &mut ResponseWriter<'_, C>, | ||
target: &mut T, | ||
command: RegisterInfo, | ||
) -> Result<HandlerStatus, Error<T::Error, C::Error>> { | ||
let ops = match target.support_register_info() { | ||
Some(ops) => ops, | ||
None => return Ok(HandlerStatus::Handled), | ||
}; | ||
|
||
crate::__dead_code_marker!("register_info", "impl"); | ||
|
||
let handler_status = match command { | ||
RegisterInfo::qRegisterInfo(cmd) => { | ||
use crate::target::ext::register_info::Register; | ||
|
||
match ops | ||
.get_register_info(cmd.reg_id) | ||
.map_err(Error::TargetError)? | ||
{ | ||
Some(Register { | ||
name, | ||
alt_name, | ||
bitsize, | ||
offset, | ||
encoding, | ||
format, | ||
set, | ||
gcc, | ||
dwarf, | ||
generic, | ||
container_regs, | ||
invalidate_regs, | ||
}) => { | ||
res.write_str("name:")?; | ||
res.write_str(name)?; | ||
res.write_str(";alt-name:")?; | ||
res.write_str(alt_name)?; | ||
res.write_str(";bitsize:")?; | ||
res.write_dec(bitsize)?; | ||
res.write_str(";offset:")?; | ||
res.write_dec(offset)?; | ||
res.write_str(";encoding:")?; | ||
res.write_str(encoding)?; | ||
res.write_str(";format:")?; | ||
res.write_str(format)?; | ||
res.write_str(";set:")?; | ||
res.write_str(set)?; | ||
if let Some(gcc) = gcc { | ||
res.write_str(";gcc:")?; | ||
res.write_dec(gcc)?; | ||
} | ||
if let Some(dwarf) = dwarf { | ||
res.write_str(";dwarf:")?; | ||
res.write_dec(dwarf)?; | ||
} | ||
if let Some(generic) = generic { | ||
res.write_str(";generic:")?; | ||
res.write_str(generic)?; | ||
} | ||
if let Some(mut c_regs) = container_regs { | ||
res.write_str(";container-regs:")?; | ||
res.write_num(c_regs.pop().unwrap())?; | ||
for c_reg in c_regs { | ||
res.write_str(",")?; | ||
res.write_num(c_reg)?; | ||
} | ||
} | ||
if let Some(mut i_regs) = invalidate_regs { | ||
res.write_str(";invalidate-regs:")?; | ||
res.write_num(i_regs.pop().unwrap())?; | ||
for i_reg in i_regs { | ||
res.write_str(",")?; | ||
res.write_num(i_reg)?; | ||
} | ||
} | ||
res.write_str(";")?; | ||
} | ||
// This will end the 'qRegisterInfo' query | ||
None => res.write_str("E45")?, | ||
} | ||
HandlerStatus::Handled | ||
} | ||
}; | ||
|
||
Ok(handler_status) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
//! Provide register information for the target. See https://github.com/llvm/llvm-project/blob/main/lldb/docs/lldb-gdb-remote.txt for more information. | ||
//! | ||
//! Some targets don't have register context in the compiled version of the debugger. Help the debugger by dynamically supplying the register info from the target if the packet 'qXfer:features:read' isn't used to provide a target description. The debugger will request the register info in a sequential manner till an 'E45' packet is received. | ||
//! | ||
//! _Note:_ LLDB specific! This packet is meant as an alternative to the 'qXfer:features:read:target.xml' packet. LLDB will fall back to the .xml file if qRegisterInfo isn't supported on the target. See issue [#99](https://github.com/daniel5151/gdbstub/issues/99) for more info on LLDB compatibility. | ||
//! | ||
use crate::target::Target; | ||
|
||
/// Describes the register info for a single register of the target | ||
pub struct Register { | ||
/// The primary register name | ||
pub name: &'static str, | ||
/// An alternate name for the register | ||
pub alt_name: &'static str, | ||
/// Size in bits of a register (base 10) | ||
pub bitsize: u32, | ||
/// The offset within the 'g' and 'G' packet of the register data for this register (base 10) | ||
pub offset: u32, | ||
/// The encoding type of the register | ||
pub encoding: &'static str, | ||
/// The preferred format for display of this register | ||
pub format: &'static str, | ||
/// The register set name this register belongs to | ||
pub set: &'static str, | ||
/// The GCC compiler registers number for this register | ||
pub gcc: Option<u32>, | ||
/// The DWARF register number for this register that is used for this register in the debug information | ||
pub dwarf: Option<u32>, | ||
/// Specify as a generic register | ||
pub generic: Option<&'static str>, | ||
/// Other concrete register values this register is contained in | ||
pub container_regs: Option<Vec<u8>>, | ||
/// Specifies which register values should be invalidated when this register is modified | ||
pub invalidate_regs: Option<Vec<u8>>, | ||
} | ||
|
||
/// Target Extension - Get register information from the target. | ||
/// | ||
/// Corresponds to the `qRegisterInfo` command. | ||
pub trait RegisterInfo: Target { | ||
/// Return the target's register info for a single register or Ok(None) if <reg_id> is greater than the number of registers to end the request. | ||
fn get_register_info(&mut self, reg_id: u8) -> Result<Option<Register>, Self::Error>; | ||
} | ||
|
||
define_ext!(RegisterInfoOps, RegisterInfo); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters