ckb_gdb_remote_protocol/
lib.rs

1//! An implementation of the server side of the GDB Remote Serial
2//! Protocol -- the protocol used by GDB and LLDB to talk to remote
3//! targets.
4//!
5//! This library attempts to hide many of the protocol warts from
6//! server implementations.  It is also mildly opinionated, in that it
7//! implements certain features itself and requires users of the
8//! library to conform.  For example, it unconditionally implements
9//! the multiprocess and non-stop modes.
10//!
11//! ## Protocol Documentation
12//!
13//! * [Documentation of the protocol](https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html)
14//! * [LLDB extensions](https://github.com/llvm-mirror/lldb/blob/master/docs/lldb-gdb-remote.txt)
15
16#![deny(missing_docs)]
17#![allow(clippy::enum_variant_names, clippy::result_unit_err)]
18
19use log::{debug, trace};
20
21use nom::*;
22use strum_macros::*;
23
24use nom::IResult::*;
25use nom::{IResult, Needed};
26use std::borrow::Cow;
27use std::cmp::min;
28use std::convert::From;
29use std::io::{self, Read, Write};
30use std::ops::Range;
31use std::str::{self, FromStr};
32
33mod fs;
34#[cfg(feature = "libc")]
35mod libc_fs;
36mod sigs;
37
38pub use self::fs::{FileSystem, HostErrno, HostMode, HostOpenFlags, IOResult};
39#[cfg(feature = "libc")]
40pub use self::libc_fs::LibcFS;
41pub use self::sigs::Signal;
42
43use self::fs::{write_stat, HostStat};
44
45const MAX_PACKET_SIZE: usize = 64 * 1024;
46
47named!(checksum<&[u8], u8>,
48       map_res!(map_res!(take!(2), str::from_utf8),
49                |s| u8::from_str_radix(s, 16)));
50
51named!(packet<&[u8], (Vec<u8>, u8)>,
52       preceded!(tag!("$"),
53                 separated_pair!(map!(opt!(is_not!("#")), |o: Option<&[u8]>| {
54                     o.map_or(vec!(), |s| s.to_vec())
55                 }),
56                                 tag!("#"),
57                                 checksum)));
58
59#[derive(Debug, PartialEq, Eq)]
60enum Packet {
61    Ack,
62    Nack,
63    Interrupt,
64    Data(Vec<u8>, u8),
65}
66
67named!(
68    packet_or_response<Packet>,
69    alt!(
70    packet => { |(d, chk)| Packet::Data(d, chk) }
71    | tag!("+") => { |_| Packet::Ack }
72    | tag!("-") => { |_| Packet::Nack }
73    | tag!("\x03") => { |_| Packet::Interrupt }
74    )
75);
76
77#[allow(non_camel_case_types)]
78#[derive(Copy, Clone, Debug, EnumString, PartialEq)]
79enum GDBFeature {
80    multiprocess,
81    xmlRegisters,
82    qRelocInsn,
83    swbreak,
84    hwbreak,
85    #[strum(serialize = "fork-events")]
86    fork_events,
87    #[strum(serialize = "vfork-events")]
88    vfork_events,
89    #[strum(serialize = "exec-events")]
90    exec_events,
91    vContSupported,
92    // these are not listed in the docs but GDB sends them
93    #[strum(serialize = "no-resumed")]
94    no_resumed,
95    QThreadEvents,
96}
97
98#[derive(Clone, Debug, PartialEq)]
99enum Known<'a> {
100    Yes(GDBFeature),
101    No(&'a str),
102}
103
104#[derive(Clone, Debug, PartialEq)]
105struct GDBFeatureSupported<'a>(Known<'a>, FeatureSupported<'a>);
106
107#[derive(Clone, Debug, PartialEq)]
108enum FeatureSupported<'a> {
109    Yes,
110    No,
111    #[allow(unused)]
112    Maybe,
113    Value(&'a str),
114}
115
116/// Defines target for the set_current_thread command.
117#[derive(Clone, Debug, PartialEq, Eq)]
118pub enum SetThreadFor {
119    /// For 'Continue' command.
120    Continue,
121    /// For `ReadRegister` command.
122    ReadRegister,
123}
124
125#[derive(Clone, Debug, PartialEq)]
126enum Query<'a> {
127    /// Return the attached state of the indicated process.
128    // FIXME the PID only needs to be optional in the
129    // non-multi-process case, which we aren't supporting; but we
130    // don't send multiprocess+ in the feature response yet.
131    Attached(Option<u64>),
132    /// Return the current thread ID.
133    CurrentThread,
134    /// Search memory for some bytes.
135    SearchMemory { address: u64, length: u64, bytes: Vec<u8> },
136    /// Compute the CRC checksum of a block of memory.
137    // Uncomment this when qC is implemented.
138    // #[allow(unused)]
139    // CRC { addr: u64, length: u64 },
140    /// Tell the remote stub about features supported by gdb, and query the stub for features
141    /// it supports.
142    SupportedFeatures(Vec<GDBFeatureSupported<'a>>),
143    /// Disable acknowledgments.
144    StartNoAckMode,
145    /// Invoke a command on the server.  The server defines commands
146    /// and how to parse them.
147    Invoke(Vec<u8>),
148    /// Enable or disable address space randomization.
149    AddressRandomization(bool),
150    /// Enable or disable catching of syscalls.
151    CatchSyscalls(Option<Vec<u64>>),
152    /// Set the list of pass signals.
153    PassSignals(Vec<u64>),
154    /// Set the list of program signals.
155    ProgramSignals(Vec<u64>),
156    /// Get a string description of a thread.
157    ThreadInfo(ThreadId),
158    /// Get a list of all active threads
159    ThreadList(bool),
160    /// Read a file such as target.xml from server
161    ReadBytes {
162        /// An object, like "features" for reading target.xml
163        object: String,
164        /// Object-specific data, like the string "target.xml"
165        annex: String,
166        /// Offset in data to start reading from
167        offset: u64,
168        /// How long to read (at most!)
169        length: u64,
170    },
171    /// Register info
172    #[cfg(feature = "lldb")]
173    RegisterInfo(u64),
174    /// Process info
175    #[cfg(feature = "lldb")]
176    ProcessInfo,
177    /// Symbol
178    Symbol(String, String),
179}
180
181/// Part of a process id.
182#[derive(Clone, Copy, Debug, PartialEq)]
183pub enum Id {
184    /// A process or thread id.  This value may not be 0 or -1.
185    Id(u32),
186    /// A special form meaning all processes or all threads of a given
187    /// process.
188    All,
189    /// A special form meaning any process or any thread of a given
190    /// process.
191    Any,
192}
193
194/// A thread identifier.  In the RSP this is just a numeric handle
195/// that is passed across the wire.  It needn't correspond to any real
196/// thread or process id (though obviously it may be more convenient
197/// when it does).
198#[derive(Clone, Copy, Debug, PartialEq)]
199pub struct ThreadId {
200    /// The process id.
201    pub pid: Id,
202    /// The thread id.
203    pub tid: Id,
204}
205
206/// A descriptor for a watchpoint.  The particular semantics of the watchpoint
207/// (watching memory for read or write access) are addressed elsewhere.
208#[derive(Clone, Copy, Debug, PartialEq)]
209pub struct Watchpoint {
210    /// The address.
211    pub addr: u64,
212
213    /// The number of bytes covered.
214    pub n_bytes: u64,
215}
216
217impl Watchpoint {
218    fn new(addr: u64, n_bytes: u64) -> Watchpoint {
219        Watchpoint { addr, n_bytes }
220    }
221}
222
223/// Target-specific bytecode.
224#[derive(Clone, Debug, PartialEq)]
225pub struct Bytecode {
226    /// The bytecodes.
227    pub bytecode: Vec<u8>,
228}
229
230/// A descriptor for a breakpoint.  The particular implementation technique
231/// of the breakpoint, hardware or software, is handled elsewhere.
232#[derive(Clone, Debug, PartialEq)]
233pub struct Breakpoint {
234    /// The address.
235    pub addr: u64,
236
237    /// The kind of breakpoint.  This field is generally 0 and its
238    /// interpretation is target-specific.  A typical use of it is for
239    /// targets that support multiple execution modes (e.g. ARM/Thumb);
240    /// different values for this field would identify the kind of code
241    /// region in which the breakpoint is being inserted.
242    pub kind: u64,
243
244    /// An optional list of target-specific bytecodes representing
245    /// conditions.  Each condition should be evaluated by the target when
246    /// the breakpoint is hit to determine whether the hit should be reported
247    /// back to the debugger.
248    pub conditions: Option<Vec<Bytecode>>,
249
250    /// An optional list of target-specific bytecodes representing commands.
251    /// These commands should be evaluated when a breakpoint is hit; any
252    /// results are not reported back to the debugger.
253    pub commands: Option<Vec<Bytecode>>,
254}
255
256impl Breakpoint {
257    fn new(addr: u64, kind: u64, conditions: Option<Vec<Bytecode>>, commands: Option<Vec<Bytecode>>) -> Breakpoint {
258        Breakpoint { addr, kind, conditions, commands }
259    }
260}
261
262/// A descriptor for a region of memory.
263#[derive(Clone, Debug, PartialEq)]
264pub struct MemoryRegion {
265    /// The base address.
266    pub address: u64,
267    /// The length.
268    pub length: u64,
269}
270
271impl MemoryRegion {
272    fn new(address: u64, length: u64) -> MemoryRegion {
273        MemoryRegion { address, length }
274    }
275}
276
277/// The name of certain vCont features to be addressed when queried
278/// for which are supported.
279#[repr(u8)]
280#[derive(Clone, Copy, Debug, PartialEq)]
281pub enum VContFeature {
282    /// Indicate that you support continuing until breakpoint
283    Continue = b'c',
284    /// Indicate that you support continuing with a signal
285    ContinueWithSignal = b'C',
286    /// Indicate that you support singlestepping one instruction
287    Step = b's',
288    /// Indicate that you support singlestepping with a signal
289    StepWithSignal = b'S',
290    /// Indicate that you support stopping a thread
291    Stop = b't',
292    /// Indicate that you support singlestepping while inside of a range
293    RangeStep = b'r',
294}
295
296/// vCont commands
297#[derive(Clone, Debug, PartialEq)]
298pub enum VCont {
299    /// Continue until breakpoint, signal or exit
300    Continue,
301    /// Like `Continue`, but replace any current signal with a
302    /// specified one
303    ContinueWithSignal(u8),
304    /// Step one machine instruction
305    Step,
306    /// Like `Step`, but replace any current signal with a specified
307    /// one
308    StepWithSignal(u8),
309    /// Only relevant in non-stop mode. Stop a thread and when
310    /// queried, indicate a stop with signal 0
311    Stop,
312    /// Keep stepping until instruction pointer is outside of
313    /// specified range. May also spuriously stop, such as when a
314    /// breakpoint is reached.
315    RangeStep(Range<u64>),
316}
317
318/// GDB remote protocol commands, as defined in (the GDB documentation)[1]
319/// [1]: https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#Packets
320#[derive(Clone, Debug, PartialEq)]
321enum Command<'a> {
322    /// Detach from a process or from all processes.
323    Detach(Option<u64>),
324    /// Enable extended mode.
325    EnableExtendedMode,
326    /// Indicate the reason the target halted.
327    TargetHaltReason,
328    // Read general registers.
329    ReadGeneralRegisters,
330    // Write general registers.
331    WriteGeneralRegisters(Vec<u8>),
332    // Read a single register.
333    ReadRegister(u64),
334    // Write a single register.
335    WriteRegister(u64, Vec<u8>),
336    // Kill request.  The argument is the optional PID, provided when the vKill
337    // packet was used, and None when the k packet was used.
338    Kill(Option<u64>),
339    // Read specified region of memory.
340    ReadMemory(MemoryRegion),
341    // Write specified region of memory.
342    WriteMemory(MemoryRegion, Vec<u8>),
343    Query(Query<'a>),
344    #[cfg(feature = "all_stop")]
345    Continue,
346    #[cfg(feature = "all_stop")]
347    Step,
348    Reset,
349    PingThread(ThreadId),
350    CtrlC,
351    UnknownVCommand,
352    /// Set the current thread for future commands, such as `ReadRegister`.
353    SetCurrentThread(SetThreadFor, ThreadId),
354    /// Insert a software breakpoint.
355    InsertSoftwareBreakpoint(Breakpoint),
356    /// Insert a hardware breakpoint
357    InsertHardwareBreakpoint(Breakpoint),
358    /// Insert a write watchpoint.
359    InsertWriteWatchpoint(Watchpoint),
360    /// Insert a read watchpoint.
361    InsertReadWatchpoint(Watchpoint),
362    /// Insert an access watchpoint.
363    InsertAccessWatchpoint(Watchpoint),
364    /// Remove a software breakpoint.
365    RemoveSoftwareBreakpoint(Breakpoint),
366    /// Remove a hardware breakpoint.
367    RemoveHardwareBreakpoint(Breakpoint),
368    /// Remove a write watchpoint.
369    RemoveWriteWatchpoint(Watchpoint),
370    /// Remove a read watchpoint.
371    RemoveReadWatchpoint(Watchpoint),
372    /// Remove an access watchpoint.
373    RemoveAccessWatchpoint(Watchpoint),
374    /// Query for a list of supported vCont features.
375    VContSupported,
376    /// Resume with different actions for each thread. Choose the
377    /// first matching thread in the list.
378    VCont(Vec<(VCont, Option<ThreadId>)>),
379    /// Open a file on the remote stub's filesystem.
380    /// TODO structured values for the flags and mode.
381    HostOpen(Vec<u8>, u64, u64),
382    /// Close an open filehandle from the remote stub's filesystem.
383    HostClose(u64),
384    /// Read data from an open filehandle from the remote stub's filesystem.
385    HostPRead(u64, u64, u64),
386    /// Write data to an open filehandle from the remote stub's filesystem.
387    HostPWrite(u64, u64, Vec<u8>),
388    /// Stat an open filehandle from the remote stub's filesystem.
389    HostFStat(u64),
390    /// Delete a file on the remote stub's filesystem.
391    HostUnlink(Vec<u8>),
392    /// Read a symbolic link on the remote stub's filesystem.
393    HostReadlink(Vec<u8>),
394    /// Set the filesystem for subsequent Host I/O operations, such as `HostOpen`.
395    HostSetFS(u64),
396}
397
398named!(
399    gdbfeature<Known<'_>>,
400    map!(map_res!(is_not_s!(";="), str::from_utf8), |s| {
401        match GDBFeature::from_str(s) {
402            Ok(f) => Known::Yes(f),
403            Err(_) => Known::No(s),
404        }
405    })
406);
407
408fn gdbfeaturesupported<'a>(i: &'a [u8]) -> IResult<&'a [u8], GDBFeatureSupported<'a>> {
409    flat_map!(i, is_not!(";"), |f: &'a [u8]| {
410        match f.split_last() {
411            None => IResult::Incomplete(Needed::Size(2)),
412            Some((&b'+', first)) => map!(first, gdbfeature, |feat| GDBFeatureSupported(feat, FeatureSupported::Yes)),
413            Some((&b'-', first)) => map!(first, gdbfeature, |feat| GDBFeatureSupported(feat, FeatureSupported::No)),
414            Some((_, _)) => map!(
415                f,
416                separated_pair!(gdbfeature, tag!("="), map_res!(is_not!(";"), str::from_utf8)),
417                |(feat, value)| GDBFeatureSupported(feat, FeatureSupported::Value(value))
418            ),
419        }
420    })
421}
422
423named!(q_search_memory<&[u8], (u64, u64, Vec<u8>)>,
424       complete!(do_parse!(
425           tag!("qSearch:memory:") >>
426           address: hex_value >>
427           tag!(";") >>
428           length: hex_value >>
429           tag!(";") >>
430           data: hex_byte_sequence >>
431           (address, length, data))));
432
433#[cfg(feature = "lldb")]
434fn lldb_query(i: &[u8]) -> IResult<&[u8], Query<'_>> {
435    alt!(i,
436        tag!("qProcessInfo") => { |_| Query::ProcessInfo }
437        | preceded!(tag!("qRegisterInfo"), hex_value) => {
438            |reg| Query::RegisterInfo(reg)
439        }
440    )
441}
442
443#[cfg(not(feature = "lldb"))]
444fn lldb_query(_i: &[u8]) -> IResult<&[u8], Query<'_>> {
445    IResult::Error(error_position!(ErrorKind::Alt, _i))
446}
447
448fn query<'a>(i: &'a [u8]) -> IResult<&'a [u8], Query<'a>> {
449    alt_complete!(i,
450    tag!("qC") => { |_| Query::CurrentThread }
451    | preceded!(tag!("qSupported"),
452                preceded!(tag!(":"),
453                          separated_list_complete!(tag!(";"),
454                                                   gdbfeaturesupported))) => {
455        |features: Vec<GDBFeatureSupported<'a>>| Query::SupportedFeatures(features)
456    }
457    | preceded!(tag!("qRcmd,"), hex_byte_sequence) => {
458        |bytes| Query::Invoke(bytes)
459    }
460    | q_search_memory => {
461        |(address, length, bytes)| Query::SearchMemory { address, length, bytes }
462    }
463    | tag!("QStartNoAckMode") => { |_| Query::StartNoAckMode }
464    | preceded!(tag!("qAttached:"), hex_value) => {
465        |value| Query::Attached(Some(value))
466    }
467    | tag!("qAttached") => { |_| Query::Attached(None) }
468    | tag!("qfThreadInfo") => { |_| Query::ThreadList(true) }
469    | tag!("qsThreadInfo") => { |_| Query::ThreadList(false) }
470    | tag!("QDisableRandomization:0") => { |_| Query::AddressRandomization(true) }
471    | tag!("QDisableRandomization:1") => { |_| Query::AddressRandomization(false) }
472    | tag!("QCatchSyscalls:0") => { |_| Query::CatchSyscalls(None) }
473    | preceded!(tag!("QCatchSyscalls:1"),
474                many0!(preceded!(tag!(";"), hex_value))) => {
475        |syscalls| Query::CatchSyscalls(Some(syscalls))
476    }
477    | preceded!(tag!("QPassSignals:"),
478                separated_list_complete!(tag!(";"), hex_value)) => {
479        |signals| Query::PassSignals(signals)
480    }
481    | preceded!(tag!("QProgramSignals:"),
482                separated_nonempty_list_complete!(tag!(";"), hex_value)) => {
483        |signals| Query::ProgramSignals(signals)
484    }
485    | preceded!(tag!("qThreadExtraInfo,"), parse_thread_id) => {
486        |thread_id| Query::ThreadInfo(thread_id)
487    }
488    | tuple!(
489        preceded!(tag!("qSymbol:"), map_res!(take_until!(":"), str::from_utf8)),
490        preceded!(tag!(":"), map_res!(eof!(), str::from_utf8))) => {
491        |(sym_value, sym_name): (&str, &str)| Query::Symbol(sym_value.to_owned(), sym_name.to_owned())
492    }
493    | tuple!(
494        preceded!(tag!("qXfer:"), map_res!(take_until!(":"), str::from_utf8)),
495        preceded!(tag!(":read:"), map_res!(take_until!(":"), str::from_utf8)),
496        preceded!(tag!(":"), hex_value),
497        preceded!(tag!(","), hex_value)) => {
498        |(object, annex, offset, length): (&str, &str, u64, u64)| Query::ReadBytes {
499            object: object.to_owned(),
500            annex: annex.to_owned(),
501            offset,
502            length,
503        }
504    }
505    | lldb_query => {
506        |q| q
507    }
508    )
509}
510
511// TODO: should the caller be responsible for determining whether they actually
512// wanted a u32, or should we provide different versions of this function with
513// extra checking?
514named!(hex_value<&[u8], u64>,
515map!(take_while1!(&nom::is_hex_digit),
516     |hex| {
517         let s = str::from_utf8(hex).unwrap();
518         let r = u64::from_str_radix(s, 16);
519         r.unwrap()
520     }));
521
522named!(hex_digit<&[u8], char>,
523       one_of!("0123456789abcdefABCDEF"));
524
525named!(hex_byte<&[u8], u8>,
526       do_parse!(
527           digit0: hex_digit >>
528           digit1: hex_digit >>
529           ((16 * digit0.to_digit(16).unwrap() + digit1.to_digit(16).unwrap()) as u8)
530       )
531);
532
533named!(hex_byte_sequence<&[u8], Vec<u8>>,
534       many1!(hex_byte));
535
536named!(write_memory<&[u8], (u64, u64, Vec<u8>)>,
537       complete!(do_parse!(
538           tag!("M") >>
539           address: hex_value >>
540           tag!(",") >>
541           length: hex_value >>
542           tag!(":") >>
543           data: hex_byte_sequence >>
544           (address, length, data))));
545
546named!(binary_byte<&[u8], u8>,
547       alt_complete!(
548           preceded!(tag!("}"), take!(1)) => { |b: &[u8]| b[0] ^ 0x20 } |
549           take!(1) => { |b: &[u8]| b[0] }));
550
551named!(binary_byte_sequence<&[u8], Vec<u8>>,
552       many1!(binary_byte));
553
554named!(write_memory_binary<&[u8], (u64, u64, Vec<u8>)>,
555       complete!(do_parse!(
556           tag!("X") >>
557           address: hex_value >>
558           tag!(",") >>
559           length: hex_value >>
560           tag!(":") >>
561           data: binary_byte_sequence >>
562           (address, length, data))));
563
564named!(read_memory<&[u8], (u64, u64)>,
565       preceded!(tag!("m"),
566                 separated_pair!(hex_value,
567                                 tag!(","),
568                                 hex_value)));
569
570named!(read_register<&[u8], u64>,
571       preceded!(tag!("p"), hex_value));
572
573named!(write_register<&[u8], (u64, Vec<u8>)>,
574       preceded!(tag!("P"),
575                 separated_pair!(hex_value,
576                                 tag!("="),
577                                 hex_byte_sequence)));
578
579named!(write_general_registers<&[u8], Vec<u8>>,
580       preceded!(tag!("G"), hex_byte_sequence));
581
582// Helper for parse_thread_id that parses a single thread-id element.
583named!(parse_thread_id_element<&[u8], Id>,
584       alt_complete!(tag!("0") => { |_| Id::Any }
585                     | tag!("-1") => { |_| Id::All }
586                     | hex_value => { |val: u64| Id::Id(val as u32) }));
587
588// Parse a thread-id.
589named!(parse_thread_id<&[u8], ThreadId>,
590alt_complete!(parse_thread_id_element => { |pid| ThreadId { pid, tid: Id::Any } }
591              | preceded!(tag!("p"),
592                          separated_pair!(parse_thread_id_element,
593                                          tag!("."),
594                                          parse_thread_id_element)) => {
595                  |pair: (Id, Id)| ThreadId { pid: pair.0, tid: pair.1 }
596              }
597              | preceded!(tag!("p"), parse_thread_id_element) => {
598                  |id: Id| ThreadId { pid: id, tid: Id::All }
599              }));
600
601// Parse the T packet.
602named!(parse_ping_thread<&[u8], ThreadId>,
603       preceded!(tag!("T"), parse_thread_id));
604
605fn parse_vfile_open(i: &[u8]) -> IResult<&[u8], Command<'_>> {
606    do_parse!(
607        i,
608        tag!("open:")
609            >> filename: hex_byte_sequence
610            >> tag!(",")
611            >> flags: hex_value
612            >> tag!(",")
613            >> mode: hex_value
614            >> (Command::HostOpen(filename, flags, mode))
615    )
616}
617
618fn parse_vfile_close(i: &[u8]) -> IResult<&[u8], Command> {
619    do_parse!(
620        i,
621        tag!("close:") >> fd: hex_value >> (Command::HostClose(fd))
622    )
623}
624
625fn parse_vfile_pread(i: &[u8]) -> IResult<&[u8], Command<'_>> {
626    do_parse!(
627        i,
628        tag!("pread:")
629            >> fd: hex_value
630            >> tag!(",")
631            >> count: hex_value
632            >> tag!(",")
633            >> offset: hex_value
634            >> (Command::HostPRead(fd, count, offset))
635    )
636}
637
638fn parse_vfile_pwrite(i: &[u8]) -> IResult<&[u8], Command<'_>> {
639    do_parse!(
640        i,
641        tag!("pwrite:")
642            >> fd: hex_value
643            >> tag!(",")
644            >> offset: hex_value
645            >> tag!(",")
646            >> data: binary_byte_sequence
647            >> (Command::HostPWrite(fd, offset, data))
648    )
649}
650
651fn parse_vfile_fstat(i: &[u8]) -> IResult<&[u8], Command<'_>> {
652    do_parse!(
653        i,
654        tag!("fstat:") >> fd: hex_value >> (Command::HostFStat(fd))
655    )
656}
657
658fn parse_vfile_unlink(i: &[u8]) -> IResult<&[u8], Command<'_>> {
659    do_parse!(
660        i,
661        tag!("unlink:") >> filename: hex_byte_sequence >> (Command::HostUnlink(filename))
662    )
663}
664
665fn parse_vfile_readlink(i: &[u8]) -> IResult<&[u8], Command<'_>> {
666    do_parse!(
667        i,
668        tag!("readlink:") >> filename: hex_byte_sequence >> (Command::HostReadlink(filename))
669    )
670}
671
672fn parse_vfile_setfs(i: &[u8]) -> IResult<&[u8], Command<'_>> {
673    do_parse!(
674        i,
675        tag!("setfs:") >> pid: hex_value >> (Command::HostSetFS(pid))
676    )
677}
678
679fn parse_unknown_vfile_op(i: &[u8]) -> IResult<&[u8], Command<'_>> {
680    // TODO: log the unknown operation for debugging purposes.
681    map!(i, take_till!(|_| { false }), { |_: &[u8]| Command::UnknownVCommand })
682}
683
684fn parse_vfile_op(i: &[u8]) -> IResult<&[u8], Command<'_>> {
685    alt_complete!(
686        i,
687        parse_vfile_open
688            | parse_vfile_close
689            | parse_vfile_pread
690            | parse_vfile_pwrite
691            | parse_vfile_fstat
692            | parse_vfile_unlink
693            | parse_vfile_readlink
694            | parse_vfile_setfs
695            | parse_unknown_vfile_op
696    )
697}
698
699fn v_command(i: &[u8]) -> IResult<&[u8], Command<'_>> {
700    alt_complete!(i,
701    tag!("vCtrlC") => { |_| Command::CtrlC }
702    | preceded!(tag!("vCont"),
703                alt_complete!(tag!("?") => { |_| Command::VContSupported }
704                              | many0!(do_parse!(
705                                  tag!(";") >>
706                                  action: alt_complete!(tag!("c") => { |_| VCont::Continue }
707                                                        | preceded!(tag!("C"), hex_byte) => { |sig| VCont::ContinueWithSignal(sig) }
708                                                        | tag!("s") => { |_| VCont::Step }
709                                                        | preceded!(tag!("S"), hex_byte) => { |sig| VCont::StepWithSignal(sig) }
710                                                        | tag!("t") => { |_| VCont::Stop }
711                                                        | do_parse!(tag!("r") >>
712                                                                    start: hex_value >>
713                                                                    tag!(",") >>
714                                                                    end: hex_value >>
715                                                                    (start, end)) => { |(start, end)| VCont::RangeStep(start..end) }
716                                  ) >>
717                                  thread: opt!(complete!(preceded!(tag!(":"), parse_thread_id))) >>
718                                  (action, thread)
719                              )) => { |actions| Command::VCont(actions) }
720                )) => {
721        |c| c
722    }
723    | preceded!(tag!("vKill;"), hex_value) => {
724        |pid| Command::Kill(Some(pid))
725    }
726    | preceded!(tag!("vFile:"), parse_vfile_op) => {
727        |c| c
728    }
729    // TODO: log the unknown command for debugging purposes.
730    | preceded!(tag!("v"), take_till!(|_| { false })) => {
731        |_| Command::UnknownVCommand
732    })
733}
734
735// Parse the H packet.
736named!(parse_h_packet<&[u8], (SetThreadFor, ThreadId)>,
737    alt_complete!(
738       preceded!(tag!("Hg"), parse_thread_id) => {
739        |id| (SetThreadFor::ReadRegister, id)
740       }
741       | preceded!(tag!("Hc"), parse_thread_id) => {
742        |id| (SetThreadFor::Continue, id)
743       }
744));
745
746// Parse the D packet.
747named!(parse_d_packet<&[u8], Option<u64>>,
748       alt_complete!(preceded!(tag!("D;"), hex_value) => {
749           |pid| Some(pid)
750       }
751       | tag!("D") => { |_| None }));
752
753#[derive(Copy, Clone)]
754enum ZAction {
755    Insert,
756    Remove,
757}
758
759named!(parse_z_action<&[u8], ZAction>,
760       alt_complete!(tag!("z") => { |_| ZAction::Remove } |
761                     tag!("Z") => { |_| ZAction::Insert }));
762
763#[derive(Copy, Clone)]
764enum ZType {
765    SoftwareBreakpoint,
766    HardwareBreakpoint,
767    WriteWatchpoint,
768    ReadWatchpoint,
769    AccessWatchpoint,
770}
771
772named!(parse_z_type<&[u8], ZType>,
773       alt_complete!(tag!("0") => { |_| ZType::SoftwareBreakpoint } |
774                     tag!("1") => { |_| ZType::HardwareBreakpoint } |
775                     tag!("2") => { |_| ZType::WriteWatchpoint } |
776                     tag!("3") => { |_| ZType::ReadWatchpoint } |
777                     tag!("4") => { |_| ZType::AccessWatchpoint }));
778
779named!(parse_cond_or_command_expression<&[u8], Bytecode>,
780       do_parse!(tag!("X") >>
781                 len: hex_value >>
782                 tag!(",") >>
783                 expr: take!(len) >>
784                 (Bytecode { bytecode: expr.to_vec() })));
785
786named!(parse_condition_list<&[u8], Vec<Bytecode>>,
787       do_parse!(tag!(";") >>
788                 list: many1!(parse_cond_or_command_expression) >>
789                 (list)));
790
791fn maybe_condition_list(i: &[u8]) -> IResult<&[u8], Option<Vec<Bytecode>>> {
792    // An Incomplete here really means "not enough input to match a
793    // condition list", and that's OK.  An Error is *probably* that the
794    // input contains a command list rather than a condition list; the
795    // two are identical in their first character.  So just ignore that
796    // FIXME.
797    match parse_condition_list(i) {
798        Done(rest, v) => Done(rest, Some(v)),
799        Incomplete(_i) => Done(i, None),
800        Error(_) => Done(i, None),
801    }
802}
803
804named!(parse_command_list<&[u8], Vec<Bytecode>>,
805       // FIXME we drop the persistence flag here. 
806       do_parse!(tag!(";cmds") >>
807                 list: alt_complete!(do_parse!(persist_flag: hex_value >>
808                                               tag!(",") >>
809                                               cmd_list: many1!(parse_cond_or_command_expression) >>
810                                               (cmd_list)) |
811                                     many1!(parse_cond_or_command_expression)) >>
812                 (list)));
813
814fn maybe_command_list(i: &[u8]) -> IResult<&[u8], Option<Vec<Bytecode>>> {
815    // An Incomplete here really means "not enough input to match a
816    // command list", and that's OK.
817    match parse_command_list(i) {
818        Done(rest, v) => Done(rest, Some(v)),
819        Incomplete(_i) => Done(i, None),
820        Error(e) => Error(e),
821    }
822}
823
824named!(parse_cond_and_command_list<&[u8], (Option<Vec<Bytecode>>,
825                                           Option<Vec<Bytecode>>)>,
826       do_parse!(cond_list: maybe_condition_list >>
827                 cmd_list: maybe_command_list >>
828                 (cond_list, cmd_list)));
829
830fn parse_z_packet(i: &[u8]) -> IResult<&[u8], Command<'_>> {
831    let (rest, (action, type_, addr, kind)) = try_parse!(
832        i,
833        do_parse!(
834            action: parse_z_action
835                >> type_: parse_z_type
836                >> tag!(",")
837                >> addr: hex_value
838                >> tag!(",")
839                >> kind: hex_value
840                >> (action, type_, addr, kind)
841        )
842    );
843
844    return match action {
845        ZAction::Insert => insert_command(rest, type_, addr, kind),
846        ZAction::Remove => Done(rest, remove_command(type_, addr, kind)),
847    };
848
849    fn insert_command(rest: &[u8], type_: ZType, addr: u64, kind: u64) -> IResult<&[u8], Command<'_>> {
850        match type_ {
851            // Software and hardware breakpoints both permit optional condition
852            // lists and commands that are evaluated on the target when
853            // breakpoints are hit.
854            ZType::SoftwareBreakpoint | ZType::HardwareBreakpoint => {
855                let (rest, (cond_list, cmd_list)) = parse_cond_and_command_list(rest).unwrap();
856                let c = (match type_ {
857                    ZType::SoftwareBreakpoint => Command::InsertSoftwareBreakpoint,
858                    ZType::HardwareBreakpoint => Command::InsertHardwareBreakpoint,
859                    // Satisfy rustc's checking
860                    _ => panic!("cannot get here"),
861                })(Breakpoint::new(addr, kind, cond_list, cmd_list));
862                Done(rest, c)
863            }
864            ZType::WriteWatchpoint => Done(rest, Command::InsertWriteWatchpoint(Watchpoint::new(addr, kind))),
865            ZType::ReadWatchpoint => Done(rest, Command::InsertReadWatchpoint(Watchpoint::new(addr, kind))),
866            ZType::AccessWatchpoint => Done(rest, Command::InsertAccessWatchpoint(Watchpoint::new(addr, kind))),
867        }
868    }
869
870    fn remove_command<'a>(type_: ZType, addr: u64, kind: u64) -> Command<'a> {
871        match type_ {
872            ZType::SoftwareBreakpoint => Command::RemoveSoftwareBreakpoint(Breakpoint::new(addr, kind, None, None)),
873            ZType::HardwareBreakpoint => Command::RemoveHardwareBreakpoint(Breakpoint::new(addr, kind, None, None)),
874            ZType::WriteWatchpoint => Command::RemoveWriteWatchpoint(Watchpoint::new(addr, kind)),
875            ZType::ReadWatchpoint => Command::RemoveReadWatchpoint(Watchpoint::new(addr, kind)),
876            ZType::AccessWatchpoint => Command::RemoveAccessWatchpoint(Watchpoint::new(addr, kind)),
877        }
878    }
879}
880
881#[cfg(feature = "all_stop")]
882fn all_stop_command(i: &[u8]) -> IResult<&[u8], Command<'_>> {
883    alt!(i,
884         tag!("c") => { |_| Command::Continue }
885         | tag!("s") => { |_| Command::Step }
886    )
887}
888
889#[cfg(not(feature = "all_stop"))]
890fn all_stop_command(_i: &[u8]) -> IResult<&[u8], Command<'_>> {
891    IResult::Error(error_position!(ErrorKind::Alt, _i))
892}
893
894fn command(i: &[u8]) -> IResult<&[u8], Command<'_>> {
895    alt!(i,
896         tag!("!") => { |_|   Command::EnableExtendedMode }
897         | tag!("?") => { |_| Command::TargetHaltReason }
898         | parse_d_packet => { |pid| Command::Detach(pid) }
899         | tag!("g") => { |_| Command::ReadGeneralRegisters }
900         | write_general_registers => { |bytes| Command::WriteGeneralRegisters(bytes) }
901         | parse_h_packet => { |(f, thread_id)| Command::SetCurrentThread(f, thread_id) }
902         | tag!("k") => { |_| Command::Kill(None) }
903         | read_memory => { |(addr, length)| Command::ReadMemory(MemoryRegion::new(addr, length)) }
904         | write_memory => { |(addr, length, bytes)| Command::WriteMemory(MemoryRegion::new(addr, length), bytes) }
905         | read_register => { |regno| Command::ReadRegister(regno) }
906         | write_register => { |(regno, bytes)| Command::WriteRegister(regno, bytes) }
907         | query => { |q| Command::Query(q) }
908         | tag!("r") => { |_| Command::Reset }
909         | preceded!(tag!("R"), take!(2)) => { |_| Command::Reset }
910         | parse_ping_thread => { |thread_id| Command::PingThread(thread_id) }
911         | v_command => { |command| command }
912         | write_memory_binary => { |(addr, length, bytes)| Command::WriteMemory(MemoryRegion::new(addr, length), bytes) }
913         | parse_z_packet => { |command| command }
914         | all_stop_command => { |command| command }
915    )
916}
917
918/// An error as returned by a `Handler` method.
919pub enum Error {
920    /// A plain error.  The meaning of the value is not defined by the
921    /// protocol.  Different values can therefore be used by a handler
922    /// for debugging purposes.
923    Error(u8),
924    /// The request is not implemented.  Note that, in some cases, the
925    /// protocol implementation tells the client that a feature is implemented;
926    /// if the handler method then returns `Unimplemented`, the client will
927    /// be confused.  So, normally it is best either to not implement
928    /// a `Handler` method, or to return `Error` from implementations.
929    Unimplemented,
930}
931
932/// The `qAttached` packet lets the client distinguish between
933/// attached and created processes, so that it knows whether to send a
934/// detach request when disconnecting.
935#[derive(Clone, Copy, Debug)]
936pub enum ProcessType {
937    /// The process already existed and was attached to.
938    Attached,
939    /// The process was created by the server.
940    Created,
941}
942
943/// The possible reasons for a thread to stop.
944#[derive(Clone, Copy, Debug)]
945pub enum StopReason {
946    /// Process stopped due to a signal.
947    Signal(u8),
948    /// The process with the given PID exited with the given status.
949    Exited(u64, u8),
950    /// The process with the given PID terminated due to the given
951    /// signal.
952    ExitedWithSignal(u64, u8),
953    /// The indicated thread exited with the given status.
954    ThreadExited(ThreadId, u64),
955    /// There are no remaining resumed threads.
956    // FIXME we should report the 'no-resumed' feature in response to
957    // qSupports before emitting this; and we should also check that
958    // the client knows about it.
959    NoMoreThreads,
960    // FIXME implement these as well.  These are used by the T packet,
961    // which can also send along registers.
962    // Watchpoint(u64),
963    // ReadWatchpoint(u64),
964    // AccessWatchpoint(u64),
965    // SyscallEntry(u8),
966    // SyscallExit(u8),
967    // LibraryChange,
968    // ReplayLogStart,
969    // ReplayLogEnd,
970    // SoftwareBreakpoint,
971    // HardwareBreakpoint,
972    // Fork(ThreadId),
973    // VFork(ThreadId),
974    // VForkDone,
975    // Exec(String),
976    // NewThread(ThreadId),
977}
978
979/// Symbol lookup response.
980#[derive(Clone, Debug)]
981pub enum SymbolLookupResponse {
982    /// No symbol name.
983    Ok,
984    /// New symbol name.
985    Symbol(String),
986}
987
988/// This trait should be implemented by servers.  Methods in the trait
989/// generally default to returning `Error::Unimplemented`; but some
990/// exceptions are noted below.  Methods that must be implemented in
991/// order for the server to work at all do not have a default
992/// implementation.
993pub trait Handler {
994    /// Return a vector of additional features supported by this handler.
995    /// Note that there currently is no way to override the built-in
996    /// features that are always handled by the protocol
997    /// implementation.
998    fn query_supported_features(&self) -> Vec<String> {
999        vec![]
1000    }
1001
1002    /// Indicate whether the process in question already existed, and
1003    /// was attached to; or whether it was created by this server.
1004    fn attached(&self, _pid: Option<u64>) -> Result<ProcessType, Error>;
1005
1006    /// Detach from the process.
1007    fn detach(&self, _pid: Option<u64>) -> Result<(), Error> {
1008        Err(Error::Unimplemented)
1009    }
1010
1011    /// Kill the indicated process.  If no process is given, then the
1012    /// precise effect is unspecified; but killing any or all
1013    /// processes, or even rebooting an entire bare-metal target,
1014    /// would be appropriate.
1015    fn kill(&self, _pid: Option<u64>) -> Result<(), Error> {
1016        Err(Error::Unimplemented)
1017    }
1018
1019    /// Check whether the indicated thread is alive.  If alive, return
1020    /// `()`.  Otherwise, return an error.
1021    fn ping_thread(&self, _id: ThreadId) -> Result<(), Error> {
1022        Err(Error::Unimplemented)
1023    }
1024
1025    /// Read a memory region.
1026    fn read_memory(&self, _region: MemoryRegion) -> Result<Vec<u8>, Error> {
1027        Err(Error::Unimplemented)
1028    }
1029
1030    /// Write the provided bytes to memory at the given address.
1031    fn write_memory(&self, _address: u64, _bytes: &[u8]) -> Result<(), Error> {
1032        Err(Error::Unimplemented)
1033    }
1034
1035    /// Read the contents of the indicated register.  The results
1036    /// should be in target byte order.  Note that a value-based API
1037    /// is not provided here because on some architectures, there are
1038    /// registers wider than ordinary integer types.
1039    fn read_register(&self, _register: u64) -> Result<Vec<u8>, Error> {
1040        Err(Error::Unimplemented)
1041    }
1042
1043    /// Set the contents of the indicated register to the given
1044    /// contents.  The contents are in target byte order.  Note that a
1045    /// value-based API is not provided here because on some
1046    /// architectures, there are registers wider than ordinary integer
1047    /// types.
1048    fn write_register(&self, _register: u64, _contents: &[u8]) -> Result<(), Error> {
1049        Err(Error::Unimplemented)
1050    }
1051
1052    /// Return the general registers.  The registers are returned as a
1053    /// vector of bytes, with the registers appearing contiguously in
1054    /// a target-specific order, with the bytes laid out in the target
1055    /// byte order.
1056    fn read_general_registers(&self) -> Result<Vec<u8>, Error> {
1057        Err(Error::Unimplemented)
1058    }
1059
1060    /// Write the general registers.  The registers are specified as a
1061    /// vector of bytes, with the registers appearing contiguously in
1062    /// a target-specific order, with the bytes laid out in the target
1063    /// byte order.
1064    fn write_general_registers(&self, _contents: &[u8]) -> Result<(), Error> {
1065        Err(Error::Unimplemented)
1066    }
1067
1068    /// Read raw bytes from an object, such as "target.xml". See
1069    /// https://sourceware.org/gdb/onlinedocs/gdb/General-Query-Packets.html#qXfer-read,
1070    /// which describes which kinds of qXfer packets are available.
1071    ///
1072    /// Return `(buffer, eof)`, a tuple containing the read bytes (at most of
1073    /// size `length`), if any, and also a boolean specifying whether or not
1074    /// you're at the end (true = end of file, false = there's more to
1075    /// read).
1076    ///
1077    /// If you're unsure of what to do, follow the rule `eof =
1078    /// buffer.is_empty()`. You're allowed to lie about EOF when you're at the
1079    /// end, GDB will just send one extra command asking for data, where you
1080    /// must disappoint it by admitting you lied.
1081    fn read_bytes(
1082        &self,
1083        _object: String,
1084        _annex: String,
1085        _offset: u64,
1086        _length: u64,
1087    ) -> Result<(Vec<u8>, bool), Error> {
1088        Err(Error::Unimplemented)
1089    }
1090
1091    /// Return the identifier of the current thread.
1092    fn current_thread(&self) -> Result<Option<ThreadId>, Error> {
1093        Ok(None)
1094    }
1095
1096    /// Set the current thread for future operations.
1097    fn set_current_thread(&self, _for: SetThreadFor, _id: ThreadId) -> Result<(), Error> {
1098        Err(Error::Unimplemented)
1099    }
1100
1101    /// Search memory.  The search begins at the given address, and
1102    /// ends after length bytes have been searched.  If the provided
1103    /// bytes are not seen, `None` should be returned; otherwise, the
1104    /// address at which the bytes were found should be returned.
1105    fn search_memory(&self, _address: u64, _length: u64, _bytes: &[u8]) -> Result<Option<u64>, Error> {
1106        Err(Error::Unimplemented)
1107    }
1108
1109    /// Return the reason that the inferior has halted.
1110    fn halt_reason(&self) -> Result<StopReason, Error>;
1111
1112    /// Invoke a command.  The command is just a sequence of bytes
1113    /// (typically ASCII characters), to be interpreted by the server
1114    /// in any way it likes.  The result is output to send back to the
1115    /// client.  This is used to implement gdb's `monitor` command.
1116    fn invoke(&self, _: &[u8]) -> Result<String, Error> {
1117        Err(Error::Unimplemented)
1118    }
1119
1120    /// Enable or disable address space randomization.  This setting
1121    /// should be used when launching a new process.
1122    fn set_address_randomization(&self, _enable: bool) -> Result<(), Error> {
1123        Err(Error::Unimplemented)
1124    }
1125
1126    /// Start or stop catching syscalls.  If the argument is `None`, then
1127    /// stop catching syscalls.  Otherwise, start catching syscalls.
1128    /// If any syscalls are specified, then only those need be caught;
1129    /// however, it is ok to report syscall stops that aren't in the
1130    /// list if that is convenient.
1131    fn catch_syscalls(&self, _syscalls: Option<Vec<u64>>) -> Result<(), Error> {
1132        Err(Error::Unimplemented)
1133    }
1134
1135    /// Set the list of "pass signals".  A signal marked as a pass
1136    /// signal can be delivered to the inferior.  No stopping or
1137    /// notification of the client is required.
1138    fn set_pass_signals(&self, _signals: Vec<u64>) -> Result<(), Error> {
1139        Ok(())
1140    }
1141
1142    /// Set the list of "program signals".  A signal marked as a
1143    /// program signal can be delivered to the inferior; other signals
1144    /// should be silently discarded.
1145    fn set_program_signals(&self, _signals: Vec<u64>) -> Result<(), Error> {
1146        Ok(())
1147    }
1148
1149    /// Return information about a given thread.  The returned
1150    /// information is just a string description that can be presented
1151    /// to the user.
1152    fn thread_info(&self, _thread: ThreadId) -> Result<String, Error> {
1153        Err(Error::Unimplemented)
1154    }
1155
1156    /// Return a list of all active thread IDs. GDB will call this in
1157    /// a paging fashion: First query has `reset` set to true and
1158    /// should reply with the first chunk of threads. Further queries
1159    /// have `reset` set to false and should respond with a chunk of
1160    /// remaining threads, until completion which should return an
1161    /// empty list to signify it's the end.
1162    ///
1163    /// Each initial GDB connection will query this and the very first
1164    /// thread ID will be stopped - so ensure the first ID is ready to
1165    /// be stopped and inspected by GDB.
1166    fn thread_list(&self, _reset: bool) -> Result<Vec<ThreadId>, Error> {
1167        Err(Error::Unimplemented)
1168    }
1169
1170    /// Insert a software breakpoint.
1171    fn insert_software_breakpoint(&self, _breakpoint: Breakpoint) -> Result<(), Error> {
1172        Err(Error::Unimplemented)
1173    }
1174
1175    /// Insert a hardware breakpoint.
1176    fn insert_hardware_breakpoint(&self, _breakpoint: Breakpoint) -> Result<(), Error> {
1177        Err(Error::Unimplemented)
1178    }
1179
1180    /// Insert a write watchpoint.
1181    fn insert_write_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1182        Err(Error::Unimplemented)
1183    }
1184
1185    /// Insert a read watchpoint.
1186    fn insert_read_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1187        Err(Error::Unimplemented)
1188    }
1189
1190    /// Insert an access watchpoint.
1191    fn insert_access_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1192        Err(Error::Unimplemented)
1193    }
1194
1195    /// Remove a software breakpoint.
1196    fn remove_software_breakpoint(&self, _breakpoint: Breakpoint) -> Result<(), Error> {
1197        Err(Error::Unimplemented)
1198    }
1199
1200    /// Remove a hardware breakpoint.
1201    fn remove_hardware_breakpoint(&self, _breakpoint: Breakpoint) -> Result<(), Error> {
1202        Err(Error::Unimplemented)
1203    }
1204
1205    /// Remove a write watchpoint.
1206    fn remove_write_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1207        Err(Error::Unimplemented)
1208    }
1209
1210    /// Remove a read watchpoint.
1211    fn remove_read_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1212        Err(Error::Unimplemented)
1213    }
1214
1215    /// Remove an access watchpoint.
1216    fn remove_access_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1217        Err(Error::Unimplemented)
1218    }
1219
1220    /// Query for a list of supported vCont features.
1221    fn query_supported_vcont(&self) -> Result<Cow<'static, [VContFeature]>, Error> {
1222        Err(Error::Unimplemented)
1223    }
1224
1225    /// Resume with different actions for each thread. Choose the
1226    /// first matching thread in the list.
1227    fn vcont(&self, _request: Vec<(VCont, Option<ThreadId>)>) -> Result<StopReason, Error> {
1228        Err(Error::Unimplemented)
1229    }
1230
1231    /// Return a filesystem handle to use for `vFile` requests.
1232    ///
1233    /// # Dynamic types
1234    ///
1235    /// The reason this uses a &dyn pointer instead of a generic HostFS type parameter, is that type parameters with default values aren't stable yet
1236    fn fs(&self) -> Result<&dyn FileSystem, ()> {
1237        Err(())
1238    }
1239
1240    /// Continues execution.
1241    #[cfg(feature = "all_stop")]
1242    fn process_continue(&self) -> Result<StopReason, Error> {
1243        Err(Error::Unimplemented)
1244    }
1245
1246    /// Step execution.
1247    #[cfg(feature = "all_stop")]
1248    fn process_step(&self) -> Result<StopReason, Error> {
1249        Err(Error::Unimplemented)
1250    }
1251
1252    /// Notifies about symbol requests.
1253    fn process_symbol(&self, _sym_value: &str, _sym_name: &str) -> Result<SymbolLookupResponse, Error> {
1254        Err(Error::Unimplemented)
1255    }
1256
1257    /// Returns information about specified register.
1258    #[cfg(feature = "lldb")]
1259    fn register_info(&self, _reg: u64) -> Result<String, Error> {
1260        Err(Error::Unimplemented)
1261    }
1262
1263    /// Returns process information.
1264    #[cfg(feature = "lldb")]
1265    fn process_info(&self) -> Result<String, Error> {
1266        Err(Error::Unimplemented)
1267    }
1268}
1269
1270fn compute_checksum_incremental(bytes: &[u8], init: u8) -> u8 {
1271    bytes.iter().fold(init, |sum, &b| sum.wrapping_add(b))
1272}
1273
1274#[derive(Debug)]
1275enum HostIOResult {
1276    Ok,               // close, unlink, setfs
1277    Error(HostErrno), // error result for any operation
1278    Integer(u64),     // open, pwrite
1279    Data(Vec<u8>),    // pread, readlink
1280    Stat(HostStat),   // fstat
1281}
1282
1283#[derive(Debug)]
1284enum Response<'a> {
1285    Empty,
1286    Ok,
1287    Error(u8),
1288    String(Cow<'a, str>),
1289    Output(String),
1290    Bytes(Vec<u8>),
1291    BytesOrEof(Vec<u8>, bool),
1292    CurrentThread(Option<ThreadId>),
1293    ProcessType(ProcessType),
1294    Stopped(StopReason),
1295    SearchResult(Option<u64>),
1296    VContFeatures(Cow<'static, [VContFeature]>),
1297    ThreadList(Vec<ThreadId>),
1298    HostIOResult(HostIOResult),
1299    SymbolName(String),
1300}
1301
1302impl<'a, T> From<Result<T, Error>> for Response<'a>
1303where
1304    Response<'a>: From<T>,
1305{
1306    fn from(result: Result<T, Error>) -> Self {
1307        match result {
1308            Result::Ok(val) => val.into(),
1309            Result::Err(Error::Error(val)) => Response::Error(val),
1310            Result::Err(Error::Unimplemented) => Response::Empty,
1311        }
1312    }
1313}
1314
1315impl<'a, T> From<Result<T, HostErrno>> for HostIOResult
1316where
1317    HostIOResult: From<T>,
1318{
1319    fn from(result: Result<T, HostErrno>) -> Self {
1320        match result {
1321            Result::Ok(val) => val.into(),
1322            Result::Err(errno) => HostIOResult::Error(errno),
1323        }
1324    }
1325}
1326
1327impl From<()> for HostIOResult {
1328    fn from(_: ()) -> Self {
1329        HostIOResult::Ok
1330    }
1331}
1332
1333impl From<u64> for HostIOResult {
1334    fn from(i: u64) -> Self {
1335        HostIOResult::Integer(i)
1336    }
1337}
1338
1339impl From<Vec<u8>> for HostIOResult {
1340    fn from(data: Vec<u8>) -> Self {
1341        HostIOResult::Data(data)
1342    }
1343}
1344
1345impl From<HostStat> for HostIOResult {
1346    fn from(stat: HostStat) -> Self {
1347        HostIOResult::Stat(stat)
1348    }
1349}
1350
1351impl<'a, T> From<IOResult<T>> for Response<'a>
1352where
1353    HostIOResult: From<T>,
1354{
1355    fn from(result: IOResult<T>) -> Self {
1356        match result {
1357            Result::Ok(val) => Response::HostIOResult(val.into()),
1358            // Indicates the operation wasn't supported.
1359            Result::Err(_) => Response::Empty,
1360        }
1361    }
1362}
1363
1364impl<'a> From<()> for Response<'a> {
1365    fn from(_: ()) -> Self {
1366        Response::Ok
1367    }
1368}
1369
1370impl<'a> From<Vec<u8>> for Response<'a> {
1371    fn from(response: Vec<u8>) -> Self {
1372        Response::Bytes(response)
1373    }
1374}
1375
1376impl<'a> From<(Vec<u8>, bool)> for Response<'a> {
1377    fn from((data, eof): (Vec<u8>, bool)) -> Self {
1378        Response::BytesOrEof(data, eof)
1379    }
1380}
1381
1382impl<'a> From<Option<ThreadId>> for Response<'a> {
1383    fn from(response: Option<ThreadId>) -> Self {
1384        Response::CurrentThread(response)
1385    }
1386}
1387
1388// This seems a bit specific -- what if some other handler method
1389// wants to return an Option<u64>?
1390impl<'a> From<Option<u64>> for Response<'a> {
1391    fn from(response: Option<u64>) -> Self {
1392        Response::SearchResult(response)
1393    }
1394}
1395
1396impl<'a> From<ProcessType> for Response<'a> {
1397    fn from(process_type: ProcessType) -> Self {
1398        Response::ProcessType(process_type)
1399    }
1400}
1401
1402impl<'a> From<StopReason> for Response<'a> {
1403    fn from(reason: StopReason) -> Self {
1404        Response::Stopped(reason)
1405    }
1406}
1407
1408impl<'a> From<String> for Response<'a> {
1409    fn from(reason: String) -> Self {
1410        Response::String(Cow::Owned(reason) as Cow<'_, str>)
1411    }
1412}
1413
1414impl<'a> From<Cow<'static, [VContFeature]>> for Response<'a> {
1415    fn from(features: Cow<'static, [VContFeature]>) -> Self {
1416        Response::VContFeatures(features)
1417    }
1418}
1419
1420impl<'a> From<Vec<ThreadId>> for Response<'a> {
1421    fn from(threads: Vec<ThreadId>) -> Self {
1422        Response::ThreadList(threads)
1423    }
1424}
1425
1426impl<'a> From<SymbolLookupResponse> for Response<'a> {
1427    fn from(response: SymbolLookupResponse) -> Self {
1428        match response {
1429            SymbolLookupResponse::Ok => Response::Ok,
1430            SymbolLookupResponse::Symbol(n) => Response::SymbolName(n),
1431        }
1432    }
1433}
1434
1435impl<'a> From<HostIOResult> for Response<'a> {
1436    fn from(result: HostIOResult) -> Self {
1437        Response::HostIOResult(result)
1438    }
1439}
1440
1441// A writer which sends a single packet.
1442struct PacketWriter<'a, W>
1443where
1444    W: Write,
1445{
1446    writer: &'a mut W,
1447    checksum: u8,
1448}
1449
1450impl<'a, W> PacketWriter<'a, W>
1451where
1452    W: Write,
1453{
1454    fn new(writer: &'a mut W) -> PacketWriter<'a, W> {
1455        PacketWriter { writer, checksum: 0 }
1456    }
1457
1458    fn finish(&mut self) -> io::Result<()> {
1459        write!(self.writer, "#{:02x}", self.checksum)?;
1460        self.writer.flush()?;
1461        self.checksum = 0;
1462        Ok(())
1463    }
1464}
1465
1466impl<'a, W> Write for PacketWriter<'a, W>
1467where
1468    W: Write,
1469{
1470    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1471        let count = self.writer.write(buf)?;
1472        self.checksum = compute_checksum_incremental(&buf[0..count], self.checksum);
1473        Ok(count)
1474    }
1475
1476    fn flush(&mut self) -> io::Result<()> {
1477        self.writer.flush()
1478    }
1479}
1480
1481fn write_thread_id<W>(writer: &mut W, thread_id: ThreadId) -> io::Result<()>
1482where
1483    W: Write,
1484{
1485    write!(writer, "p")?;
1486    match thread_id.pid {
1487        Id::All => write!(writer, "-1"),
1488        Id::Any => write!(writer, "0"),
1489        Id::Id(num) => write!(writer, "{:x}", num),
1490    }?;
1491    write!(writer, ".")?;
1492    match thread_id.tid {
1493        Id::All => write!(writer, "-1"),
1494        Id::Any => write!(writer, "0"),
1495        Id::Id(num) => write!(writer, "{:x}", num),
1496    }
1497}
1498
1499impl From<HostStat> for Vec<u8> {
1500    fn from(stat: HostStat) -> Self {
1501        let mut v = vec![];
1502        // XXX: this can technically fail, and we shouldn't be ignoring it.
1503        write_stat(&mut v, stat).unwrap();
1504        v
1505    }
1506}
1507
1508fn write_hex_data<W>(writer: &mut W, data: &[u8]) -> io::Result<()>
1509where
1510    W: Write,
1511{
1512    for b in data {
1513        write!(writer, "{:02x}", b)?;
1514    }
1515    Ok(())
1516}
1517
1518fn write_binary_data<W>(writer: &mut W, data: &[u8]) -> io::Result<()>
1519where
1520    W: Write,
1521{
1522    // Modern GDB way of transmitting bytes: Send it raw, but with } as
1523    // escape character. See
1524    // https://sourceware.org/gdb/onlinedocs/gdb/Overview.html#Binary-Data
1525    let mut remaining = data;
1526    loop {
1527        let unescaped = min(
1528            memchr::memchr3(b'#', b'$', b'}', remaining).unwrap_or(remaining.len()),
1529            memchr::memchr(b'*', remaining).unwrap_or(remaining.len()),
1530        );
1531        writer.write_all(&remaining[..unescaped])?;
1532
1533        remaining = &remaining[unescaped..];
1534
1535        // We only stop when...
1536        match remaining.first() {
1537            // ... a character needs to be escaped
1538            Some(byte) => writer.write_all(&[b'}', byte ^ 0x20])?,
1539            // ... we reach EOF
1540            None => break,
1541        }
1542
1543        remaining = &remaining[1..];
1544    }
1545    Ok(())
1546}
1547
1548fn write_response<W>(response: Response<'_>, writer: &mut W) -> io::Result<()>
1549where
1550    W: Write,
1551{
1552    trace!("Response: {:?}", response);
1553    write!(writer, "$")?;
1554
1555    let mut writer = PacketWriter::new(writer);
1556    match response {
1557        Response::Ok => {
1558            write!(writer, "OK")?;
1559        }
1560        Response::Empty => {}
1561        Response::Error(val) => {
1562            write!(writer, "E{:02x}", val)?;
1563        }
1564        Response::String(s) => {
1565            write!(writer, "{}", s)?;
1566        }
1567        Response::Output(s) => {
1568            write!(writer, "O")?;
1569            for byte in s.as_bytes() {
1570                write!(writer, "{:02x}", byte)?;
1571            }
1572        }
1573        Response::Bytes(bytes) => {
1574            for byte in bytes {
1575                write!(writer, "{:02x}", byte)?;
1576            }
1577        }
1578        Response::BytesOrEof(bytes, eof) => {
1579            write!(writer, "{}", if eof { "l" } else { "m" })?;
1580            write_binary_data(&mut writer, &bytes)?;
1581        }
1582        Response::CurrentThread(tid) => {
1583            // This is incorrect if multiprocess hasn't yet been enabled.
1584            match tid {
1585                None => write!(writer, "OK")?,
1586                Some(thread_id) => {
1587                    write!(writer, "QC")?;
1588                    write_thread_id(&mut writer, thread_id)?;
1589                }
1590            };
1591        }
1592        Response::ProcessType(process_type) => {
1593            match process_type {
1594                ProcessType::Attached => write!(writer, "1")?,
1595                ProcessType::Created => write!(writer, "0")?,
1596            };
1597        }
1598        Response::SearchResult(maybe_addr) => match maybe_addr {
1599            Some(addr) => write!(writer, "1,{:x}", addr)?,
1600            None => write!(writer, "0")?,
1601        },
1602        Response::Stopped(stop_reason) => {
1603            match stop_reason {
1604                StopReason::Signal(signo) => write!(writer, "S{:02x}", signo)?,
1605                StopReason::Exited(pid, status) => {
1606                    // Non-multi-process gdb only accepts 2 hex digits
1607                    // for the status.
1608                    write!(writer, "W{:02x};process:{:x}", status, pid)?;
1609                }
1610                StopReason::ExitedWithSignal(pid, status) => {
1611                    // Non-multi-process gdb only accepts 2 hex digits
1612                    // for the status.
1613                    write!(writer, "X{:x};process:{:x}", status, pid)?;
1614                }
1615                StopReason::ThreadExited(thread_id, status) => {
1616                    write!(writer, "w{:x};", status)?;
1617                    write_thread_id(&mut writer, thread_id)?;
1618                }
1619                StopReason::NoMoreThreads => write!(writer, "N")?,
1620            }
1621        }
1622        Response::VContFeatures(features) => {
1623            write!(writer, "vCont")?;
1624            for &feature in &*features {
1625                write!(writer, ";{}", feature as u8 as char)?;
1626            }
1627        }
1628        Response::ThreadList(threads) => {
1629            if threads.is_empty() {
1630                write!(writer, "l")?;
1631            } else {
1632                write!(writer, "m")?;
1633                for (i, &id) in threads.iter().enumerate() {
1634                    // Write separator
1635                    if i != 0 {
1636                        write!(writer, ",")?;
1637                    }
1638                    write_thread_id(&mut writer, id)?;
1639                }
1640            }
1641        }
1642        Response::SymbolName(name) => {
1643            write!(writer, "qSymbol:")?;
1644            write_hex_data(&mut writer, name.as_bytes())?;
1645        }
1646        Response::HostIOResult(result) => match result {
1647            HostIOResult::Ok => write!(writer, "F0")?,
1648            HostIOResult::Error(errno) => {
1649                write!(writer, "F-1,{:x}", errno as u32)?;
1650            }
1651            HostIOResult::Integer(i) => write!(writer, "F{:x}", i)?,
1652            HostIOResult::Data(v) => {
1653                write!(writer, "F{:x};", v.len())?;
1654                write_binary_data(&mut writer, &v)?;
1655            }
1656            HostIOResult::Stat(stat) => {
1657                let data = <HostStat as Into<Vec<_>>>::into(stat);
1658                write!(writer, "F{:x};", data.len())?;
1659                write_binary_data(&mut writer, &data[..])?
1660            }
1661        },
1662    }
1663
1664    writer.finish()
1665}
1666
1667fn handle_supported_features<'a, H>(handler: &H, _features: &[GDBFeatureSupported<'a>]) -> Response<'static>
1668where
1669    H: Handler,
1670{
1671    let mut features = vec![
1672        format!("PacketSize={:x}", MAX_PACKET_SIZE),
1673        "QStartNoAckMode+".to_string(),
1674        "multiprocess+".to_string(),
1675        "QDisableRandomization+".to_string(),
1676        "QCatchSyscalls+".to_string(),
1677        "QPassSignals+".to_string(),
1678        "QProgramSignals+".to_string(),
1679    ];
1680    let mut new_features = handler.query_supported_features();
1681    features.append(&mut new_features);
1682    Response::String(Cow::Owned(features.join(";")) as Cow<'_, str>)
1683}
1684
1685/// Handle a single packet `data` with `handler` and write a response to `writer`.
1686fn handle_packet<H, W>(data: &[u8], handler: &H, writer: &mut W) -> io::Result<bool>
1687where
1688    H: Handler,
1689    W: Write,
1690{
1691    debug!("Command: {}", String::from_utf8_lossy(data));
1692    let mut no_ack_mode = false;
1693    let response = if let Done(_, command) = command(data) {
1694        match command {
1695            // We unconditionally support extended mode.
1696            Command::EnableExtendedMode => Response::Ok,
1697            Command::TargetHaltReason => handler.halt_reason().into(),
1698            Command::ReadGeneralRegisters => handler.read_general_registers().into(),
1699            Command::WriteGeneralRegisters(bytes) => handler.write_general_registers(&bytes[..]).into(),
1700            Command::Kill(None) => {
1701                // The k packet requires no response, so purposely
1702                // ignore the result.
1703                drop(handler.kill(None));
1704                Response::Empty
1705            }
1706            Command::Kill(pid) => handler.kill(pid).into(),
1707            Command::Reset => Response::Empty,
1708            Command::ReadRegister(regno) => handler.read_register(regno).into(),
1709            Command::WriteRegister(regno, bytes) => handler.write_register(regno, &bytes[..]).into(),
1710            Command::ReadMemory(region) => handler.read_memory(region).into(),
1711            Command::WriteMemory(region, bytes) => {
1712                // The docs don't really say what to do if the given
1713                // length disagrees with the number of bytes sent, so
1714                // just error if they disagree.
1715                if region.length as usize != bytes.len() {
1716                    Response::Error(1)
1717                } else {
1718                    handler.write_memory(region.address, &bytes[..]).into()
1719                }
1720            }
1721            Command::SetCurrentThread(f, thread_id) => handler.set_current_thread(f, thread_id).into(),
1722            Command::Detach(pid) => handler.detach(pid).into(),
1723            #[cfg(feature = "all_stop")]
1724            Command::Continue => handler.process_continue().into(),
1725            #[cfg(feature = "all_stop")]
1726            Command::Step => handler.process_step().into(),
1727
1728            Command::Query(Query::Attached(pid)) => handler.attached(pid).into(),
1729            Command::Query(Query::CurrentThread) => handler.current_thread().into(),
1730            Command::Query(Query::Invoke(cmd)) => match handler.invoke(&cmd[..]) {
1731                Result::Ok(val) => {
1732                    if val.is_empty() {
1733                        Response::Ok
1734                    } else {
1735                        Response::Output(val)
1736                    }
1737                }
1738                Result::Err(Error::Error(val)) => Response::Error(val),
1739                Result::Err(Error::Unimplemented) => Response::Empty,
1740            },
1741            Command::Query(Query::SearchMemory { address, length, bytes }) => {
1742                handler.search_memory(address, length, &bytes[..]).into()
1743            }
1744            Command::Query(Query::SupportedFeatures(features)) => handle_supported_features(handler, &features),
1745            Command::Query(Query::StartNoAckMode) => {
1746                no_ack_mode = true;
1747                Response::Ok
1748            }
1749            Command::Query(Query::AddressRandomization(randomize)) => {
1750                handler.set_address_randomization(randomize).into()
1751            }
1752            Command::Query(Query::CatchSyscalls(calls)) => handler.catch_syscalls(calls).into(),
1753            Command::Query(Query::PassSignals(signals)) => handler.set_pass_signals(signals).into(),
1754            Command::Query(Query::ProgramSignals(signals)) => handler.set_program_signals(signals).into(),
1755            Command::Query(Query::ThreadInfo(thread_info)) => handler.thread_info(thread_info).into(),
1756            Command::Query(Query::ThreadList(reset)) => handler.thread_list(reset).into(),
1757            Command::Query(Query::ReadBytes { object, annex, offset, length }) => {
1758                handler.read_bytes(object, annex, offset, length).into()
1759            }
1760            #[cfg(feature = "lldb")]
1761            Command::Query(Query::RegisterInfo(reg)) => handler.register_info(reg).into(),
1762            #[cfg(feature = "lldb")]
1763            Command::Query(Query::ProcessInfo) => handler.process_info().into(),
1764            Command::Query(Query::Symbol(sym_value, sym_name)) => handler.process_symbol(&sym_value, &sym_name).into(),
1765            Command::PingThread(thread_id) => handler.ping_thread(thread_id).into(),
1766            // Empty means "not implemented".
1767            Command::CtrlC => Response::Empty,
1768
1769            // Unknown v commands are required to give an empty
1770            // response.
1771            Command::UnknownVCommand => Response::Empty,
1772
1773            Command::InsertSoftwareBreakpoint(bp) => handler.insert_software_breakpoint(bp).into(),
1774            Command::InsertHardwareBreakpoint(bp) => handler.insert_hardware_breakpoint(bp).into(),
1775            Command::InsertWriteWatchpoint(wp) => handler.insert_write_watchpoint(wp).into(),
1776            Command::InsertReadWatchpoint(wp) => handler.insert_read_watchpoint(wp).into(),
1777            Command::InsertAccessWatchpoint(wp) => handler.insert_access_watchpoint(wp).into(),
1778            Command::RemoveSoftwareBreakpoint(bp) => handler.remove_software_breakpoint(bp).into(),
1779            Command::RemoveHardwareBreakpoint(bp) => handler.remove_hardware_breakpoint(bp).into(),
1780            Command::RemoveWriteWatchpoint(wp) => handler.remove_write_watchpoint(wp).into(),
1781            Command::RemoveReadWatchpoint(wp) => handler.remove_read_watchpoint(wp).into(),
1782            Command::RemoveAccessWatchpoint(wp) => handler.remove_access_watchpoint(wp).into(),
1783            Command::VContSupported => handler.query_supported_vcont().into(),
1784            Command::VCont(list) => handler.vcont(list).into(),
1785            Command::HostOpen(filename, mode, flags) => handler
1786                .fs()
1787                .and_then(|fs| {
1788                    fs.host_open(
1789                        filename,
1790                        HostOpenFlags::from_bits_truncate(mode as u32),
1791                        HostMode::from_bits_truncate(flags as u32),
1792                    )
1793                })
1794                .into(),
1795            Command::HostClose(fd) => handler.fs().and_then(|fs| fs.host_close(fd)).into(),
1796            Command::HostPRead(fd, count, offset) => {
1797                handler.fs().and_then(|fs| fs.host_pread(fd, count, offset)).into()
1798            }
1799            Command::HostPWrite(fd, offset, data) => {
1800                handler.fs().and_then(|fs| fs.host_pwrite(fd, offset, data)).into()
1801            }
1802            Command::HostFStat(fd) => handler.fs().and_then(|fs| fs.host_fstat(fd)).into(),
1803            Command::HostUnlink(filename) => handler.fs().and_then(|fs| fs.host_unlink(filename)).into(),
1804            Command::HostReadlink(filename) => handler.fs().and_then(|fs| fs.host_readlink(filename)).into(),
1805            Command::HostSetFS(pid) => handler.fs().and_then(|fs| fs.host_setfs(pid)).into(),
1806        }
1807    } else {
1808        Response::Empty
1809    };
1810    write_response(response, writer)?;
1811    Ok(no_ack_mode)
1812}
1813
1814fn offset(from: &[u8], to: &[u8]) -> usize {
1815    let fst = from.as_ptr();
1816    let snd = to.as_ptr();
1817
1818    snd as usize - fst as usize
1819}
1820
1821fn run_parser(buf: &[u8]) -> Option<(usize, Packet)> {
1822    if let Done(rest, packet) = packet_or_response(buf) {
1823        Some((offset(buf, rest), packet))
1824    } else {
1825        None
1826    }
1827}
1828
1829/// Read gdbserver packets from `reader` and call methods on `handler` to handle them and write
1830/// responses to `writer`.
1831pub fn process_packets_from<R, W, H>(mut reader: R, mut writer: W, handler: H)
1832where
1833    R: Read,
1834    W: Write,
1835    H: Handler,
1836{
1837    let mut buf = vec![0; MAX_PACKET_SIZE];
1838    let mut endbuf = 0;
1839    let mut ack_mode = true;
1840    loop {
1841        match reader.read(&mut buf[endbuf..]) {
1842            Ok(n) if n > 0 => endbuf += n,
1843            _ => break,
1844        }
1845
1846        let mut parsed = 0;
1847        while let Some((len, packet)) = run_parser(&buf[parsed..endbuf]) {
1848            if let Packet::Data(ref data, ref _checksum) = packet {
1849                // Write an ACK
1850                if ack_mode && writer.write_all(&b"+"[..]).is_err() {
1851                    // TODO: propagate errors to caller?
1852                    return;
1853                }
1854
1855                let no_ack_mode = handle_packet(&data, &handler, &mut writer).unwrap_or(false);
1856                if no_ack_mode {
1857                    ack_mode = false;
1858                }
1859            }
1860            parsed += len;
1861        }
1862
1863        buf.copy_within(parsed..endbuf, 0);
1864        endbuf -= parsed;
1865    }
1866}
1867
1868#[test]
1869fn test_compute_checksum() {
1870    assert_eq!(compute_checksum_incremental(&b""[..], 0), 0);
1871    assert_eq!(compute_checksum_incremental(&b"qSupported:multiprocess+;xmlRegisters=i386;qRelocInsn+"[..], 0), 0xb5);
1872}
1873
1874#[test]
1875fn test_checksum() {
1876    assert_eq!(checksum(&b"00"[..]), Done(&b""[..], 0));
1877    assert_eq!(checksum(&b"a1"[..]), Done(&b""[..], 0xa1));
1878    assert_eq!(checksum(&b"1d"[..]), Done(&b""[..], 0x1d));
1879    assert_eq!(checksum(&b"ff"[..]), Done(&b""[..], 0xff));
1880}
1881
1882#[test]
1883fn test_packet() {
1884    use nom::Needed;
1885    assert_eq!(packet(&b"$#00"[..]), Done(&b""[..], (b""[..].to_vec(), 0)));
1886    assert_eq!(packet(&b"$xyz#00"[..]), Done(&b""[..], (b"xyz"[..].to_vec(), 0)));
1887    assert_eq!(packet(&b"$a#a1"[..]), Done(&b""[..], (b"a"[..].to_vec(), 0xa1)));
1888    assert_eq!(packet(&b"$foo#ffxyz"[..]), Done(&b"xyz"[..], (b"foo"[..].to_vec(), 0xff)));
1889    assert_eq!(
1890        packet(&b"$qSupported:multiprocess+;xmlRegisters=i386;qRelocInsn+#b5"[..]),
1891        Done(&b""[..], (b"qSupported:multiprocess+;xmlRegisters=i386;qRelocInsn+"[..].to_vec(), 0xb5))
1892    );
1893    assert_eq!(packet(&b"$"[..]), Incomplete(Needed::Size(2)));
1894    assert_eq!(packet(&b"$#"[..]), Incomplete(Needed::Size(4)));
1895    assert_eq!(packet(&b"$xyz"[..]), Incomplete(Needed::Size(5)));
1896    assert_eq!(packet(&b"$xyz#"[..]), Incomplete(Needed::Size(7)));
1897    assert_eq!(packet(&b"$xyz#a"[..]), Incomplete(Needed::Size(7)));
1898}
1899
1900#[test]
1901fn test_packet_or_response() {
1902    assert_eq!(packet_or_response(&b"$#00"[..]), Done(&b""[..], Packet::Data(b""[..].to_vec(), 0)));
1903    assert_eq!(packet_or_response(&b"+"[..]), Done(&b""[..], Packet::Ack));
1904    assert_eq!(packet_or_response(&b"-"[..]), Done(&b""[..], Packet::Nack));
1905}
1906
1907#[test]
1908fn test_gdbfeaturesupported() {
1909    assert_eq!(
1910        gdbfeaturesupported(&b"multiprocess+"[..]),
1911        Done(&b""[..], GDBFeatureSupported(Known::Yes(GDBFeature::multiprocess), FeatureSupported::Yes))
1912    );
1913    assert_eq!(
1914        gdbfeaturesupported(&b"xmlRegisters=i386"[..]),
1915        Done(&b""[..], GDBFeatureSupported(Known::Yes(GDBFeature::xmlRegisters), FeatureSupported::Value("i386")))
1916    );
1917    assert_eq!(
1918        gdbfeaturesupported(&b"qRelocInsn-"[..]),
1919        Done(&b""[..], GDBFeatureSupported(Known::Yes(GDBFeature::qRelocInsn), FeatureSupported::No))
1920    );
1921    assert_eq!(
1922        gdbfeaturesupported(&b"vfork-events+"[..]),
1923        Done(&b""[..], GDBFeatureSupported(Known::Yes(GDBFeature::vfork_events), FeatureSupported::Yes))
1924    );
1925    assert_eq!(
1926        gdbfeaturesupported(&b"vfork-events-"[..]),
1927        Done(&b""[..], GDBFeatureSupported(Known::Yes(GDBFeature::vfork_events), FeatureSupported::No))
1928    );
1929    assert_eq!(
1930        gdbfeaturesupported(&b"unknown-feature+"[..]),
1931        Done(&b""[..], GDBFeatureSupported(Known::No("unknown-feature"), FeatureSupported::Yes))
1932    );
1933    assert_eq!(
1934        gdbfeaturesupported(&b"unknown-feature-"[..]),
1935        Done(&b""[..], GDBFeatureSupported(Known::No("unknown-feature"), FeatureSupported::No))
1936    );
1937}
1938
1939#[test]
1940fn test_gdbfeature() {
1941    assert_eq!(gdbfeature(&b"multiprocess"[..]), Done(&b""[..], Known::Yes(GDBFeature::multiprocess)));
1942    assert_eq!(gdbfeature(&b"fork-events"[..]), Done(&b""[..], Known::Yes(GDBFeature::fork_events)));
1943    assert_eq!(gdbfeature(&b"some-unknown-feature"[..]), Done(&b""[..], Known::No("some-unknown-feature")));
1944}
1945
1946#[test]
1947fn test_query() {
1948    // From a gdbserve packet capture.
1949    let b = concat!(
1950        "qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;",
1951        "vfork-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+;",
1952        "xmlRegisters=i386"
1953    );
1954    assert_eq!(
1955        query(b.as_bytes()),
1956        Done(
1957            &b""[..],
1958            Query::SupportedFeatures(vec![
1959                GDBFeatureSupported(Known::Yes(GDBFeature::multiprocess), FeatureSupported::Yes),
1960                GDBFeatureSupported(Known::Yes(GDBFeature::swbreak), FeatureSupported::Yes),
1961                GDBFeatureSupported(Known::Yes(GDBFeature::hwbreak), FeatureSupported::Yes),
1962                GDBFeatureSupported(Known::Yes(GDBFeature::qRelocInsn), FeatureSupported::Yes),
1963                GDBFeatureSupported(Known::Yes(GDBFeature::fork_events), FeatureSupported::Yes),
1964                GDBFeatureSupported(Known::Yes(GDBFeature::vfork_events), FeatureSupported::Yes),
1965                GDBFeatureSupported(Known::Yes(GDBFeature::exec_events), FeatureSupported::Yes),
1966                GDBFeatureSupported(Known::Yes(GDBFeature::vContSupported), FeatureSupported::Yes),
1967                GDBFeatureSupported(Known::Yes(GDBFeature::QThreadEvents), FeatureSupported::Yes),
1968                GDBFeatureSupported(Known::Yes(GDBFeature::no_resumed), FeatureSupported::Yes),
1969                GDBFeatureSupported(Known::Yes(GDBFeature::xmlRegisters), FeatureSupported::Value("i386")),
1970            ])
1971        )
1972    );
1973}
1974
1975#[test]
1976fn test_hex_value() {
1977    assert_eq!(hex_value(&b""[..]), Incomplete(Needed::Size(1)));
1978    assert_eq!(hex_value(&b","[..]), Error(nom::ErrorKind::TakeWhile1));
1979    assert_eq!(hex_value(&b"a"[..]), Done(&b""[..], 0xa));
1980    assert_eq!(hex_value(&b"10,"[..]), Done(&b","[..], 0x10));
1981    assert_eq!(hex_value(&b"ff"[..]), Done(&b""[..], 0xff));
1982}
1983
1984#[test]
1985fn test_parse_thread_id_element() {
1986    assert_eq!(parse_thread_id_element(&b"0"[..]), Done(&b""[..], Id::Any));
1987    assert_eq!(parse_thread_id_element(&b"-1"[..]), Done(&b""[..], Id::All));
1988    assert_eq!(parse_thread_id_element(&b"23"[..]), Done(&b""[..], Id::Id(0x23)));
1989}
1990
1991#[test]
1992fn test_parse_thread_id() {
1993    assert_eq!(parse_thread_id(&b"0"[..]), Done(&b""[..], ThreadId { pid: Id::Any, tid: Id::Any }));
1994    assert_eq!(parse_thread_id(&b"-1"[..]), Done(&b""[..], ThreadId { pid: Id::All, tid: Id::Any }));
1995    assert_eq!(parse_thread_id(&b"23"[..]), Done(&b""[..], ThreadId { pid: Id::Id(0x23), tid: Id::Any }));
1996
1997    assert_eq!(parse_thread_id(&b"p23"[..]), Done(&b""[..], ThreadId { pid: Id::Id(0x23), tid: Id::All }));
1998
1999    assert_eq!(parse_thread_id(&b"p0.0"[..]), Done(&b""[..], ThreadId { pid: Id::Any, tid: Id::Any }));
2000    assert_eq!(parse_thread_id(&b"p-1.23"[..]), Done(&b""[..], ThreadId { pid: Id::All, tid: Id::Id(0x23) }));
2001    assert_eq!(parse_thread_id(&b"pff.23"[..]), Done(&b""[..], ThreadId { pid: Id::Id(0xff), tid: Id::Id(0x23) }));
2002}
2003
2004#[test]
2005fn test_parse_v_commands() {
2006    assert_eq!(v_command(&b"vKill;33"[..]), Done(&b""[..], Command::Kill(Some(0x33))));
2007    assert_eq!(v_command(&b"vCtrlC"[..]), Done(&b""[..], Command::CtrlC));
2008    assert_eq!(v_command(&b"vMustReplyEmpty"[..]), Done(&b""[..], Command::UnknownVCommand));
2009
2010    assert_eq!(v_command(&b"vCont?"[..]), Done(&b""[..], Command::VContSupported));
2011    assert_eq!(v_command(&b"vCont"[..]), Done(&b""[..], Command::VCont(Vec::new())));
2012    assert_eq!(v_command(&b"vCont;c"[..]), Done(&b""[..], Command::VCont(vec![(VCont::Continue, None)])));
2013    assert_eq!(
2014        v_command(&b"vCont;r1,2:p34.56;SAD:-1;c"[..]),
2015        Done(
2016            &b""[..],
2017            Command::VCont(vec![
2018                (VCont::RangeStep(1..2), Some(ThreadId { pid: Id::Id(0x34), tid: Id::Id(0x56) })),
2019                (VCont::StepWithSignal(0xAD), Some(ThreadId { pid: Id::All, tid: Id::Any })),
2020                (VCont::Continue, None)
2021            ])
2022        )
2023    );
2024
2025    assert_eq!(
2026        v_command(&b"vFile:open:2f766d6c696e757a,0,0"[..]),
2027        Done(&b""[..], Command::HostOpen(vec!(47, 118, 109, 108, 105, 110, 117, 122), 0, 0))
2028    );
2029    assert_eq!(v_command(&b"vFile:close:85"[..]), Done(&b""[..], Command::HostClose(0x85)));
2030    assert_eq!(v_command(&b"vFile:pread:5,96,327"[..]), Done(&b""[..], Command::HostPRead(5, 0x96, 0x327)));
2031    assert_eq!(v_command(&b"vFile:pwrite:6,83,\x00"[..]), Done(&b""[..], Command::HostPWrite(6, 0x83, vec![0])));
2032    assert_eq!(v_command(&b"vFile:pwrite:6,83,\x7d\x5d"[..]), Done(&b""[..], Command::HostPWrite(6, 0x83, vec![0x7d])));
2033    assert_eq!(v_command(&b"vFile:fstat:32"[..]), Done(&b""[..], Command::HostFStat(0x32)));
2034    assert_eq!(
2035        v_command(&b"vFile:unlink:2f766d6c696e757a"[..]),
2036        Done(&b""[..], Command::HostUnlink(vec!(47, 118, 109, 108, 105, 110, 117, 122)))
2037    );
2038    assert_eq!(
2039        v_command(&b"vFile:readlink:2f766d6c696e757a"[..]),
2040        Done(&b""[..], Command::HostReadlink(vec!(47, 118, 109, 108, 105, 110, 117, 122)))
2041    );
2042    assert_eq!(v_command(&b"vFile:setfs:0"[..]), Done(&b""[..], Command::HostSetFS(0)));
2043    assert_eq!(v_command(&b"vFile:fdopen:0"[..]), Done(&b""[..], Command::UnknownVCommand));
2044}
2045
2046#[test]
2047fn test_parse_d_packets() {
2048    assert_eq!(parse_d_packet(&b"D"[..]), Done(&b""[..], None));
2049    assert_eq!(parse_d_packet(&b"D;f0"[..]), Done(&b""[..], Some(240)));
2050}
2051
2052#[test]
2053fn test_parse_write_memory() {
2054    assert_eq!(write_memory(&b"Mf0,3:ff0102"[..]), Done(&b""[..], (240, 3, vec!(255, 1, 2))));
2055}
2056
2057#[test]
2058fn test_parse_write_memory_binary() {
2059    assert_eq!(write_memory_binary(&b"Xf0,1: "[..]), Done(&b""[..], (240, 1, vec!(0x20))));
2060    assert_eq!(write_memory_binary(&b"X90,10:}\x5d"[..]), Done(&b""[..], (144, 16, vec!(0x7d))));
2061    assert_eq!(write_memory_binary(&b"X5,100:}\x5d}\x03"[..]), Done(&b""[..], (5, 256, vec!(0x7d, 0x23))));
2062    assert_eq!(write_memory_binary(&b"Xff,2:}\x04\x9a"[..]), Done(&b""[..], (255, 2, vec!(0x24, 0x9a))));
2063    assert_eq!(write_memory_binary(&b"Xff,2:\xce}\x0a\x9a"[..]), Done(&b""[..], (255, 2, vec!(0xce, 0x2a, 0x9a))));
2064}
2065
2066#[test]
2067fn test_parse_qrcmd() {
2068    assert_eq!(query(&b"qRcmd,736f6d657468696e67"[..]), Done(&b""[..], Query::Invoke(b"something".to_vec())));
2069}
2070
2071#[test]
2072fn test_parse_randomization() {
2073    assert_eq!(query(&b"QDisableRandomization:0"[..]), Done(&b""[..], Query::AddressRandomization(true)));
2074    assert_eq!(query(&b"QDisableRandomization:1"[..]), Done(&b""[..], Query::AddressRandomization(false)));
2075}
2076
2077#[test]
2078fn test_parse_syscalls() {
2079    assert_eq!(query(&b"QCatchSyscalls:0"[..]), Done(&b""[..], Query::CatchSyscalls(None)));
2080    assert_eq!(query(&b"QCatchSyscalls:1"[..]), Done(&b""[..], Query::CatchSyscalls(Some(vec!()))));
2081    assert_eq!(query(&b"QCatchSyscalls:1;0;1;ff"[..]), Done(&b""[..], Query::CatchSyscalls(Some(vec!(0, 1, 255)))));
2082}
2083
2084#[test]
2085fn test_parse_signals() {
2086    assert_eq!(query(&b"QPassSignals:"[..]), Done(&b""[..], Query::PassSignals(vec!())));
2087    assert_eq!(query(&b"QPassSignals:0"[..]), Done(&b""[..], Query::PassSignals(vec!(0))));
2088    assert_eq!(query(&b"QPassSignals:1;2;ff"[..]), Done(&b""[..], Query::PassSignals(vec!(1, 2, 255))));
2089    assert_eq!(query(&b"QProgramSignals:0"[..]), Done(&b""[..], Query::ProgramSignals(vec!(0))));
2090    assert_eq!(query(&b"QProgramSignals:1;2;ff"[..]), Done(&b""[..], Query::ProgramSignals(vec!(1, 2, 255))));
2091}
2092
2093#[test]
2094fn test_thread_info() {
2095    assert_eq!(
2096        query(&b"qThreadExtraInfo,ffff"[..]),
2097        Done(&b""[..], Query::ThreadInfo(ThreadId { pid: Id::Id(65535), tid: Id::Any }))
2098    );
2099}
2100
2101#[test]
2102fn test_thread_list() {
2103    assert_eq!(query(&b"qfThreadInfo"[..]), Done(&b""[..], Query::ThreadList(true)));
2104    assert_eq!(query(&b"qsThreadInfo"[..]), Done(&b""[..], Query::ThreadList(false)));
2105}
2106
2107#[test]
2108fn test_parse_write_register() {
2109    assert_eq!(write_register(&b"Pff=1020"[..]), Done(&b""[..], (255, vec!(16, 32))));
2110}
2111
2112#[test]
2113fn test_parse_write_general_registers() {
2114    assert_eq!(write_general_registers(&b"G0001020304"[..]), Done(&b""[..], vec!(0, 1, 2, 3, 4)));
2115}
2116
2117#[test]
2118fn test_write_response() {
2119    fn write_one(input: Response<'_>) -> io::Result<String> {
2120        let mut result = Vec::new();
2121        write_response(input, &mut result)?;
2122        Ok(String::from_utf8(result).unwrap())
2123    }
2124
2125    assert_eq!(write_one(Response::Empty).unwrap(), "$#00");
2126    assert_eq!(write_one(Response::Ok).unwrap(), "$OK#9a");
2127    assert_eq!(write_one(Response::Error(1)).unwrap(), "$E01#a6");
2128
2129    assert_eq!(
2130        write_one(Response::CurrentThread(Some(ThreadId { pid: Id::Id(255), tid: Id::Id(1) }))).unwrap(),
2131        "$QCpff.1#2f"
2132    );
2133    assert_eq!(
2134        write_one(Response::ThreadList(vec!(
2135            ThreadId { pid: Id::Id(123), tid: Id::Id(123) },
2136            ThreadId { pid: Id::Id(456), tid: Id::Any },
2137        )))
2138        .unwrap(),
2139        "$mp7b.7b,p1c8.0#03"
2140    );
2141    assert_eq!(write_one(Response::ThreadList(vec!())).unwrap(), "$l#6c");
2142    assert_eq!(
2143        write_one(Response::BytesOrEof(Vec::from(&b"{Hello * World} #yee $999.99"[..]), false)).unwrap(),
2144        "$m{Hello }\n World}] }\x03yee }\x04999.99#54"
2145    );
2146    assert_eq!(
2147        write_one(Response::BytesOrEof(Vec::from(&b"does not need to be escaped"[..]), true)).unwrap(),
2148        "$ldoes not need to be escaped#23"
2149    );
2150}
2151
2152#[cfg(test)]
2153macro_rules! bytecode {
2154    ($elem:expr; $n:expr) => (Bytecode { bytecode: vec![$elem; $n] });
2155    ($($x:expr),*) => (Bytecode { bytecode: vec!($($x),*) })
2156}
2157
2158#[test]
2159fn test_breakpoints() {
2160    assert_eq!(
2161        parse_z_packet(&b"Z0,1ff,0"[..]),
2162        Done(&b""[..], Command::InsertSoftwareBreakpoint(Breakpoint::new(0x1ff, 0, None, None)))
2163    );
2164    assert_eq!(
2165        parse_z_packet(&b"z0,1fff,0"[..]),
2166        Done(&b""[..], Command::RemoveSoftwareBreakpoint(Breakpoint::new(0x1fff, 0, None, None)))
2167    );
2168    assert_eq!(
2169        parse_z_packet(&b"Z1,ae,0"[..]),
2170        Done(&b""[..], Command::InsertHardwareBreakpoint(Breakpoint::new(0xae, 0, None, None)))
2171    );
2172    assert_eq!(
2173        parse_z_packet(&b"z1,aec,0"[..]),
2174        Done(&b""[..], Command::RemoveHardwareBreakpoint(Breakpoint::new(0xaec, 0, None, None)))
2175    );
2176    assert_eq!(
2177        parse_z_packet(&b"Z2,4cc,2"[..]),
2178        Done(&b""[..], Command::InsertWriteWatchpoint(Watchpoint::new(0x4cc, 2)))
2179    );
2180    assert_eq!(
2181        parse_z_packet(&b"z2,4ccf,4"[..]),
2182        Done(&b""[..], Command::RemoveWriteWatchpoint(Watchpoint::new(0x4ccf, 4)))
2183    );
2184    assert_eq!(
2185        parse_z_packet(&b"Z3,7777,4"[..]),
2186        Done(&b""[..], Command::InsertReadWatchpoint(Watchpoint::new(0x7777, 4)))
2187    );
2188    assert_eq!(
2189        parse_z_packet(&b"z3,77778,8"[..]),
2190        Done(&b""[..], Command::RemoveReadWatchpoint(Watchpoint::new(0x77778, 8)))
2191    );
2192    assert_eq!(
2193        parse_z_packet(&b"Z4,7777,10"[..]),
2194        Done(&b""[..], Command::InsertAccessWatchpoint(Watchpoint::new(0x7777, 16)))
2195    );
2196    assert_eq!(
2197        parse_z_packet(&b"z4,77778,20"[..]),
2198        Done(&b""[..], Command::RemoveAccessWatchpoint(Watchpoint::new(0x77778, 32)))
2199    );
2200
2201    assert_eq!(
2202        parse_z_packet(&b"Z0,1ff,2;X1,0"[..]),
2203        Done(
2204            &b""[..],
2205            Command::InsertSoftwareBreakpoint(Breakpoint::new(0x1ff, 2, Some(vec!(bytecode!('0' as u8))), None))
2206        )
2207    );
2208    assert_eq!(
2209        parse_z_packet(&b"Z1,1ff,2;X1,0"[..]),
2210        Done(
2211            &b""[..],
2212            Command::InsertHardwareBreakpoint(Breakpoint::new(0x1ff, 2, Some(vec!(bytecode!('0' as u8))), None))
2213        )
2214    );
2215
2216    assert_eq!(
2217        parse_z_packet(&b"Z0,1ff,2;cmdsX1,z"[..]),
2218        Done(
2219            &b""[..],
2220            Command::InsertSoftwareBreakpoint(Breakpoint::new(0x1ff, 2, None, Some(vec!(bytecode!('z' as u8)))))
2221        )
2222    );
2223    assert_eq!(
2224        parse_z_packet(&b"Z1,1ff,2;cmdsX1,z"[..]),
2225        Done(
2226            &b""[..],
2227            Command::InsertHardwareBreakpoint(Breakpoint::new(0x1ff, 2, None, Some(vec!(bytecode!('z' as u8)))))
2228        )
2229    );
2230
2231    assert_eq!(
2232        parse_z_packet(&b"Z0,1ff,2;X1,0;cmdsX1,a"[..]),
2233        Done(
2234            &b""[..],
2235            Command::InsertSoftwareBreakpoint(Breakpoint::new(
2236                0x1ff,
2237                2,
2238                Some(vec!(bytecode!('0' as u8))),
2239                Some(vec!(bytecode!('a' as u8)))
2240            ))
2241        )
2242    );
2243    assert_eq!(
2244        parse_z_packet(&b"Z1,1ff,2;X1,0;cmdsX1,a"[..]),
2245        Done(
2246            &b""[..],
2247            Command::InsertHardwareBreakpoint(Breakpoint::new(
2248                0x1ff,
2249                2,
2250                Some(vec!(bytecode!('0' as u8))),
2251                Some(vec!(bytecode!('a' as u8)))
2252            ))
2253        )
2254    );
2255}
2256
2257#[test]
2258fn test_cond_or_command_list() {
2259    assert_eq!(parse_condition_list(&b";X1,a"[..]), Done(&b""[..], vec!(bytecode!('a' as u8))));
2260    assert_eq!(parse_condition_list(&b";X2,ab"[..]), Done(&b""[..], vec!(bytecode!('a' as u8, 'b' as u8))));
2261    assert_eq!(
2262        parse_condition_list(&b";X1,zX1,y"[..]),
2263        Done(&b""[..], vec!(bytecode!('z' as u8), bytecode!('y' as u8)))
2264    );
2265    assert_eq!(
2266        parse_condition_list(&b";X1,zX10,yyyyyyyyyyyyyyyy"[..]),
2267        Done(&b""[..], vec!(bytecode!('z' as u8), bytecode!['y' as u8; 16]))
2268    );
2269
2270    assert_eq!(parse_command_list(&b";cmdsX1,a"[..]), Done(&b""[..], vec!(bytecode!('a' as u8))));
2271    assert_eq!(parse_command_list(&b";cmdsX2,ab"[..]), Done(&b""[..], vec!(bytecode!('a' as u8, 'b' as u8))));
2272    assert_eq!(
2273        parse_command_list(&b";cmdsX1,zX1,y"[..]),
2274        Done(&b""[..], vec!(bytecode!('z' as u8), bytecode!('y' as u8)))
2275    );
2276    assert_eq!(
2277        parse_command_list(&b";cmdsX1,zX10,yyyyyyyyyyyyyyyy"[..]),
2278        Done(&b""[..], vec!(bytecode!('z' as u8), bytecode!['y' as u8; 16]))
2279    );
2280}
2281
2282#[test]
2283fn test_qxfer() {
2284    assert_eq!(
2285        query(&b"qXfer:features:read:target.xml:0,1000"[..]),
2286        Done(
2287            &b""[..],
2288            Query::ReadBytes {
2289                object: String::from("features"),
2290                annex: String::from("target.xml"),
2291                offset: 0,
2292                length: 4096,
2293            }
2294        )
2295    );
2296}
2297
2298#[test]
2299fn test_write_binary_data() {
2300    // Ordinary data, no escapes.
2301    check(vec![1, 2, 3], vec![1, 2, 3]);
2302    // Escape required at the beginning.
2303    check(vec![0x7d, 2, 3], vec![0x7d, 0x5d, 2, 3]);
2304    check(vec![0x23, 2, 3], vec![0x7d, 0x03, 2, 3]);
2305    check(vec![0x24, 2, 3], vec![0x7d, 0x04, 2, 3]);
2306    check(vec![0x2a, 2, 3], vec![0x7d, 0x0a, 2, 3]);
2307    // Escape required at the end.
2308    check(vec![8, 9, 0x7d], vec![8, 9, 0x7d, 0x5d]);
2309    check(vec![8, 9, 0x23], vec![8, 9, 0x7d, 0x03]);
2310    check(vec![8, 9, 0x24], vec![8, 9, 0x7d, 0x04]);
2311    check(vec![8, 9, 0x2a], vec![8, 9, 0x7d, 0x0a]);
2312    // Escape required in the middle.
2313    check(vec![8, 9, 0x7d, 5, 6], vec![8, 9, 0x7d, 0x5d, 5, 6]);
2314    check(vec![8, 9, 0x23, 5, 6], vec![8, 9, 0x7d, 0x03, 5, 6]);
2315    check(vec![8, 9, 0x24, 5, 6], vec![8, 9, 0x7d, 0x04, 5, 6]);
2316    check(vec![8, 9, 0x2a, 5, 6], vec![8, 9, 0x7d, 0x0a, 5, 6]);
2317
2318    fn check(data: Vec<u8>, output: Vec<u8>) {
2319        let mut v = vec![];
2320        write_binary_data(&mut v, &data).unwrap();
2321        assert_eq!(v, output);
2322    }
2323}