Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Host I/O operations #66

Merged
merged 13 commits into from
Aug 20, 2021
4 changes: 1 addition & 3 deletions src/gdbstub_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,9 +561,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
match cmd {
Command::Unknown(cmd) => {
// cmd must be ASCII, as the slice originated from a PacketBuf, which checks for
// ASCII as part of the initial validation.
info!("Unknown command: {}", core::str::from_utf8(cmd).unwrap());
info!("Unknown command: {:?}", core::str::from_utf8(cmd));
Ok(HandlerStatus::Handled)
}
// `handle_X` methods are defined in the `ext` module
Expand Down
4 changes: 3 additions & 1 deletion src/protocol/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use crate::target::Target;
pub(self) mod prelude {
pub use super::ParseCommand;
pub use crate::common::*;
pub use crate::protocol::common::hex::{decode_hex, decode_hex_buf, is_hex, HexString};
pub use crate::protocol::common::hex::{
decode_bin_buf, decode_hex, decode_hex_buf, is_hex, HexString,
};
pub use crate::protocol::common::lists;
pub use crate::protocol::common::thread_id::{
IdKind, SpecificIdKind, SpecificThreadId, ThreadId,
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_pwrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl<'a> ParseCommand<'a> for vFilePwrite<'a> {
let mut body = body.splitn_mut_no_panic(3, |b| *b == b',');
let fd = decode_hex(body.next()?).ok()?;
let offset = decode_hex_buf(body.next()?).ok()?;
let data = body.next()?;
let data = decode_bin_buf(body.next()?).ok()?;
Some(vFilePwrite{fd, offset, data})
},
_ => None,
Expand Down
36 changes: 35 additions & 1 deletion src/protocol/common/hex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,34 @@ pub fn decode_hex_buf(base_buf: &mut [u8]) -> Result<&mut [u8], DecodeHexBufErro
Ok(&mut base_buf[..decoded_len + odd_adust])
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum DecodeBinBufError {
UnexpectedEnd,
}

/// Decode GDB escaped binary bytes into origin bytes _in place_.
pub fn decode_bin_buf(buf: &mut [u8]) -> Result<&mut [u8], DecodeBinBufError> {
daniel5151 marked this conversation as resolved.
Show resolved Hide resolved
use DecodeBinBufError::*;
let mut i = 0;
let mut j = 0;
let len = buf.len();
while i < len {
if buf[i] == b'}' {
if i == len - 1 {
return Err(UnexpectedEnd);
} else {
buf[j] = buf[i + 1] ^ 0x20;
i += 1;
}
} else {
buf[j] = buf[i];
}
i += 1;
j += 1;
}
Ok(&mut buf[..j])
}

#[derive(Debug)]
pub enum EncodeHexBufError {
SmallBuffer,
Expand Down Expand Up @@ -268,4 +295,11 @@ mod tests {
let res = decode_hex_buf(&mut payload).unwrap();
assert_eq!(res, [0x1]);
}

#[test]
fn decode_bin_buf_escaped() {
let mut payload = b"}\x03}\x04}]}\n".to_vec();
let res = decode_bin_buf(&mut payload).unwrap();
assert_eq!(res, [0x23, 0x24, 0x7d, 0x2a]);
}
}
11 changes: 0 additions & 11 deletions src/protocol/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ pub enum PacketParseError {
MissingChecksum,
MalformedChecksum,
MalformedCommand,
NotAscii,
UnexpectedHeader(u8),
}

Expand Down Expand Up @@ -57,11 +56,6 @@ impl<'a> PacketBuf<'a> {
.get(..2)
.ok_or(PacketParseError::MalformedChecksum)?;

// validate that the body is valid ASCII
if !body.is_ascii() {
return Err(PacketParseError::NotAscii);
}

// validate the checksum
let checksum = decode_hex(checksum).map_err(|_| PacketParseError::MalformedChecksum)?;
let calculated = body.iter().fold(0u8, |a, x| a.wrapping_add(*x));
Expand All @@ -84,11 +78,6 @@ impl<'a> PacketBuf<'a> {
/// the header/checksum trimming stage. ASCII validation is still performed.
bet4it marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(test)]
pub fn new_with_raw_body(body: &'a mut [u8]) -> Result<PacketBuf<'a>, PacketParseError> {
// validate the packet is valid ASCII
if !body.is_ascii() {
return Err(PacketParseError::NotAscii);
}

let len = body.len();
Ok(PacketBuf {
buf: body,
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/response_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl<'a, C: Connection + 'a> ResponseWriter<'a, C> {
#[cfg(feature = "std")]
trace!(
"--> ${}#{:02x?}",
core::str::from_utf8(&self.msg).unwrap(), // buffers are always ascii
String::from_utf8_lossy(&self.msg),
checksum
);

Expand Down