blob: 15b1c35995f0a4f7fc95a9550e5737b7c843eacb [file] [log] [blame]
use super::prelude::*;
use crate::protocol::commands::ext::TargetXml;
use crate::arch::Arch;
impl<T: Target, C: Connection> GdbStubImpl<T, C> {
pub(crate) fn handle_target_xml(
&mut self,
res: &mut ResponseWriter<'_, C>,
target: &mut T,
command: TargetXml<'_>,
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
if !target.use_target_description_xml() {
return Ok(HandlerStatus::Handled);
}
let handler_status = match command {
TargetXml::qXferFeaturesRead(cmd) => {
let ret = if let Some(ops) = target.support_target_description_xml_override() {
ops.target_description_xml(cmd.annex.name, cmd.offset, cmd.length, cmd.buf)
.handle_error()?
} else if let Some(xml) = T::Arch::target_description_xml() {
if cmd.annex.name != b"target.xml" {
// TODO: not the best error... should probably report to the user the
// <xi:include> isn't supported at the Arch level (yet)
return Err(Error::PacketUnexpected);
}
let xml = xml.trim().as_bytes();
let xml_len = xml.len();
let start = xml_len.min(cmd.offset as usize);
let end = xml_len.min(cmd.offset as usize + cmd.length);
// LLVM isn't smart enough to realize that `end` will always be greater than
// `start`, and fails to elide the `slice_index_order_fail` check unless we
// include this seemingly useless call to `max`.
let data = &xml[start..end.max(start)];
let n = data.len().min(cmd.buf.len());
cmd.buf[..n].copy_from_slice(&data[..n]);
n
} else {
// If the target hasn't provided their own XML, then the initial response to
// "qSupported" wouldn't have included "qXfer:features:read", and gdb wouldn't
// send this packet unless it was explicitly marked as supported.
return Err(Error::PacketUnexpected);
};
if ret == 0 {
res.write_str("l")?;
} else {
res.write_str("m")?;
// TODO: add more specific error variant?
res.write_binary(cmd.buf.get(..ret).ok_or(Error::PacketBufferOverflow)?)?;
}
HandlerStatus::Handled
}
};
Ok(handler_status)
}
}