1 use super::prelude::*; 2 use crate::arch::lldb::Encoding; 3 use crate::arch::lldb::Format; 4 use crate::arch::lldb::Generic; 5 use crate::arch::lldb::Register; 6 use crate::arch::lldb::RegisterInfo as LLDBRegisterInfo; 7 use crate::arch::Arch; 8 use crate::protocol::commands::ext::LldbRegisterInfo; 9 10 impl<T: Target, C: Connection> GdbStubImpl<T, C> { handle_lldb_register_info( &mut self, res: &mut ResponseWriter<'_, C>, target: &mut T, command: LldbRegisterInfo, ) -> Result<HandlerStatus, Error<T::Error, C::Error>>11 pub(crate) fn handle_lldb_register_info( 12 &mut self, 13 res: &mut ResponseWriter<'_, C>, 14 target: &mut T, 15 command: LldbRegisterInfo, 16 ) -> Result<HandlerStatus, Error<T::Error, C::Error>> { 17 if !target.use_lldb_register_info() { 18 return Ok(HandlerStatus::Handled); 19 } 20 21 let handler_status = match command { 22 LldbRegisterInfo::qRegisterInfo(cmd) => { 23 let mut err = Ok(()); 24 let cb = &mut |reg: Option<Register<'_>>| { 25 let res = match reg { 26 // TODO: replace this with a try block (once stabilized) 27 Some(reg) => (|| { 28 res.write_str("name:")?; 29 res.write_str(reg.name)?; 30 if let Some(alt_name) = reg.alt_name { 31 res.write_str(";alt-name:")?; 32 res.write_str(alt_name)?; 33 } 34 res.write_str(";bitsize:")?; 35 res.write_dec(reg.bitsize)?; 36 res.write_str(";offset:")?; 37 res.write_dec(reg.offset)?; 38 res.write_str(";encoding:")?; 39 res.write_str(match reg.encoding { 40 Encoding::Uint => "uint", 41 Encoding::Sint => "sint", 42 Encoding::IEEE754 => "ieee754", 43 Encoding::Vector => "vector", 44 })?; 45 res.write_str(";format:")?; 46 res.write_str(match reg.format { 47 Format::Binary => "binary", 48 Format::Decimal => "decimal", 49 Format::Hex => "hex", 50 Format::Float => "float", 51 Format::VectorSInt8 => "vector-sint8", 52 Format::VectorUInt8 => "vector-uint8", 53 Format::VectorSInt16 => "vector-sint16", 54 Format::VectorUInt16 => "vector-uint16", 55 Format::VectorSInt32 => "vector-sint32", 56 Format::VectorUInt32 => "vector-uint32", 57 Format::VectorFloat32 => "vector-float32", 58 Format::VectorUInt128 => "vector-uint128", 59 })?; 60 res.write_str(";set:")?; 61 res.write_str(reg.set)?; 62 if let Some(gcc) = reg.gcc { 63 res.write_str(";gcc:")?; 64 res.write_dec(gcc)?; 65 } 66 if let Some(dwarf) = reg.dwarf { 67 res.write_str(";dwarf:")?; 68 res.write_dec(dwarf)?; 69 } 70 if let Some(generic) = reg.generic { 71 res.write_str(";generic:")?; 72 res.write_str(match generic { 73 Generic::Pc => "pc", 74 Generic::Sp => "sp", 75 Generic::Fp => "fp", 76 Generic::Ra => "ra", 77 Generic::Flags => "flags", 78 Generic::Arg1 => "arg1", 79 Generic::Arg2 => "arg2", 80 Generic::Arg3 => "arg3", 81 Generic::Arg4 => "arg4", 82 Generic::Arg5 => "arg5", 83 Generic::Arg6 => "arg6", 84 Generic::Arg7 => "arg7", 85 Generic::Arg8 => "arg8", 86 })?; 87 } 88 if let Some(c_regs) = reg.container_regs { 89 res.write_str(";container-regs:")?; 90 res.write_num(c_regs[0])?; 91 for reg in c_regs.iter().skip(1) { 92 res.write_str(",")?; 93 res.write_num(*reg)?; 94 } 95 } 96 if let Some(i_regs) = reg.invalidate_regs { 97 res.write_str(";invalidate-regs:")?; 98 res.write_num(i_regs[0])?; 99 for reg in i_regs.iter().skip(1) { 100 res.write_str(",")?; 101 res.write_num(*reg)?; 102 } 103 } 104 res.write_str(";") 105 })(), 106 // In fact, this doesn't has to be E45! It could equally well be any 107 // other error code or even an eOk, eAck or eNack! It turns out that 108 // 0x45 == 69, so presumably the LLDB people were just having some fun 109 // here. For a little discussion on this and LLDB source code pointers, 110 // see https://github.com/daniel5151/gdbstub/pull/103#discussion_r888590197 111 _ => res.write_str("E45"), 112 }; 113 if let Err(e) = res { 114 err = Err(e); 115 } 116 }; 117 if let Some(ops) = target.support_lldb_register_info_override() { 118 use crate::target::ext::lldb_register_info_override::Callback; 119 use crate::target::ext::lldb_register_info_override::CallbackToken; 120 121 ops.lldb_register_info( 122 cmd.reg_id, 123 Callback { 124 cb, 125 token: CallbackToken(core::marker::PhantomData), 126 }, 127 ) 128 .map_err(Error::TargetError)?; 129 err?; 130 } else if let Some(reg) = T::Arch::lldb_register_info(cmd.reg_id) { 131 match reg { 132 LLDBRegisterInfo::Register(reg) => cb(Some(reg)), 133 LLDBRegisterInfo::Done => cb(None), 134 }; 135 } 136 HandlerStatus::Handled 137 } 138 }; 139 140 Ok(handler_status) 141 } 142 } 143