blob: 2b27f7ce7aecf42570ccf3638901a609a4bc0f15 [file] [log] [blame]
use super::prelude::*;
use crate::protocol::commands::ext::LldbRegisterInfo;
use crate::arch::lldb::{Encoding, Format, Generic, Register, RegisterInfo as LLDBRegisterInfo};
use crate::arch::Arch;
impl<T: Target, C: Connection> GdbStubImpl<T, C> {
pub(crate) fn handle_lldb_register_info(
&mut self,
res: &mut ResponseWriter<'_, C>,
target: &mut T,
command: LldbRegisterInfo,
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
if !target.use_lldb_register_info() {
return Ok(HandlerStatus::Handled);
}
let handler_status = match command {
LldbRegisterInfo::qRegisterInfo(cmd) => {
let mut err = Ok(());
let cb = &mut |reg: Option<Register<'_>>| {
let res = match reg {
// TODO: replace this with a try block (once stabilized)
Some(reg) => (|| {
res.write_str("name:")?;
res.write_str(reg.name)?;
if let Some(alt_name) = reg.alt_name {
res.write_str(";alt-name:")?;
res.write_str(alt_name)?;
}
res.write_str(";bitsize:")?;
res.write_dec(reg.bitsize)?;
res.write_str(";offset:")?;
res.write_dec(reg.offset)?;
res.write_str(";encoding:")?;
res.write_str(match reg.encoding {
Encoding::Uint => "uint",
Encoding::Sint => "sint",
Encoding::IEEE754 => "ieee754",
Encoding::Vector => "vector",
})?;
res.write_str(";format:")?;
res.write_str(match reg.format {
Format::Binary => "binary",
Format::Decimal => "decimal",
Format::Hex => "hex",
Format::Float => "float",
Format::VectorSInt8 => "vector-sint8",
Format::VectorUInt8 => "vector-uint8",
Format::VectorSInt16 => "vector-sint16",
Format::VectorUInt16 => "vector-uint16",
Format::VectorSInt32 => "vector-sint32",
Format::VectorUInt32 => "vector-uint32",
Format::VectorFloat32 => "vector-float32",
Format::VectorUInt128 => "vector-uint128",
})?;
res.write_str(";set:")?;
res.write_str(reg.set)?;
if let Some(gcc) = reg.gcc {
res.write_str(";gcc:")?;
res.write_dec(gcc)?;
}
if let Some(dwarf) = reg.dwarf {
res.write_str(";dwarf:")?;
res.write_dec(dwarf)?;
}
if let Some(generic) = reg.generic {
res.write_str(";generic:")?;
res.write_str(match generic {
Generic::Pc => "pc",
Generic::Sp => "sp",
Generic::Fp => "fp",
Generic::Ra => "ra",
Generic::Flags => "flags",
Generic::Arg1 => "arg1",
Generic::Arg2 => "arg2",
Generic::Arg3 => "arg3",
Generic::Arg4 => "arg4",
Generic::Arg5 => "arg5",
Generic::Arg6 => "arg6",
Generic::Arg7 => "arg7",
Generic::Arg8 => "arg8",
})?;
}
if let Some(c_regs) = reg.container_regs {
res.write_str(";container-regs:")?;
res.write_num(c_regs[0])?;
for reg in c_regs.iter().skip(1) {
res.write_str(",")?;
res.write_num(*reg)?;
}
}
if let Some(i_regs) = reg.invalidate_regs {
res.write_str(";invalidate-regs:")?;
res.write_num(i_regs[0])?;
for reg in i_regs.iter().skip(1) {
res.write_str(",")?;
res.write_num(*reg)?;
}
}
res.write_str(";")
})(),
// In fact, this doesn't has to be E45! It could equally well be any
// other error code or even an eOk, eAck or eNack! It turns out that
// 0x45 == 69, so presumably the LLDB people were just having some fun
// here. For a little discussion on this and LLDB source code pointers,
// see https://github.com/daniel5151/gdbstub/pull/103#discussion_r888590197
_ => res.write_str("E45"),
};
if let Err(e) = res {
err = Err(e);
}
};
if let Some(ops) = target.support_lldb_register_info_override() {
use crate::target::ext::lldb_register_info_override::{
Callback, CallbackToken,
};
ops.lldb_register_info(
cmd.reg_id,
Callback {
cb,
token: CallbackToken(core::marker::PhantomData),
},
)
.map_err(Error::TargetError)?;
err?;
} else if let Some(reg) = T::Arch::lldb_register_info(cmd.reg_id) {
match reg {
LLDBRegisterInfo::Register(reg) => cb(Some(reg)),
LLDBRegisterInfo::Done => cb(None),
};
}
HandlerStatus::Handled
}
};
Ok(handler_status)
}
}