1#![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 #[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#[derive(Clone, Debug, PartialEq, Eq)]
118pub enum SetThreadFor {
119 Continue,
121 ReadRegister,
123}
124
125#[derive(Clone, Debug, PartialEq)]
126enum Query<'a> {
127 Attached(Option<u64>),
132 CurrentThread,
134 SearchMemory { address: u64, length: u64, bytes: Vec<u8> },
136 SupportedFeatures(Vec<GDBFeatureSupported<'a>>),
143 StartNoAckMode,
145 Invoke(Vec<u8>),
148 AddressRandomization(bool),
150 CatchSyscalls(Option<Vec<u64>>),
152 PassSignals(Vec<u64>),
154 ProgramSignals(Vec<u64>),
156 ThreadInfo(ThreadId),
158 ThreadList(bool),
160 ReadBytes {
162 object: String,
164 annex: String,
166 offset: u64,
168 length: u64,
170 },
171 #[cfg(feature = "lldb")]
173 RegisterInfo(u64),
174 #[cfg(feature = "lldb")]
176 ProcessInfo,
177 Symbol(String, String),
179}
180
181#[derive(Clone, Copy, Debug, PartialEq)]
183pub enum Id {
184 Id(u32),
186 All,
189 Any,
192}
193
194#[derive(Clone, Copy, Debug, PartialEq)]
199pub struct ThreadId {
200 pub pid: Id,
202 pub tid: Id,
204}
205
206#[derive(Clone, Copy, Debug, PartialEq)]
209pub struct Watchpoint {
210 pub addr: u64,
212
213 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#[derive(Clone, Debug, PartialEq)]
225pub struct Bytecode {
226 pub bytecode: Vec<u8>,
228}
229
230#[derive(Clone, Debug, PartialEq)]
233pub struct Breakpoint {
234 pub addr: u64,
236
237 pub kind: u64,
243
244 pub conditions: Option<Vec<Bytecode>>,
249
250 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#[derive(Clone, Debug, PartialEq)]
264pub struct MemoryRegion {
265 pub address: u64,
267 pub length: u64,
269}
270
271impl MemoryRegion {
272 fn new(address: u64, length: u64) -> MemoryRegion {
273 MemoryRegion { address, length }
274 }
275}
276
277#[repr(u8)]
280#[derive(Clone, Copy, Debug, PartialEq)]
281pub enum VContFeature {
282 Continue = b'c',
284 ContinueWithSignal = b'C',
286 Step = b's',
288 StepWithSignal = b'S',
290 Stop = b't',
292 RangeStep = b'r',
294}
295
296#[derive(Clone, Debug, PartialEq)]
298pub enum VCont {
299 Continue,
301 ContinueWithSignal(u8),
304 Step,
306 StepWithSignal(u8),
309 Stop,
312 RangeStep(Range<u64>),
316}
317
318#[derive(Clone, Debug, PartialEq)]
321enum Command<'a> {
322 Detach(Option<u64>),
324 EnableExtendedMode,
326 TargetHaltReason,
328 ReadGeneralRegisters,
330 WriteGeneralRegisters(Vec<u8>),
332 ReadRegister(u64),
334 WriteRegister(u64, Vec<u8>),
336 Kill(Option<u64>),
339 ReadMemory(MemoryRegion),
341 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 SetCurrentThread(SetThreadFor, ThreadId),
354 InsertSoftwareBreakpoint(Breakpoint),
356 InsertHardwareBreakpoint(Breakpoint),
358 InsertWriteWatchpoint(Watchpoint),
360 InsertReadWatchpoint(Watchpoint),
362 InsertAccessWatchpoint(Watchpoint),
364 RemoveSoftwareBreakpoint(Breakpoint),
366 RemoveHardwareBreakpoint(Breakpoint),
368 RemoveWriteWatchpoint(Watchpoint),
370 RemoveReadWatchpoint(Watchpoint),
372 RemoveAccessWatchpoint(Watchpoint),
374 VContSupported,
376 VCont(Vec<(VCont, Option<ThreadId>)>),
379 HostOpen(Vec<u8>, u64, u64),
382 HostClose(u64),
384 HostPRead(u64, u64, u64),
386 HostPWrite(u64, u64, Vec<u8>),
388 HostFStat(u64),
390 HostUnlink(Vec<u8>),
392 HostReadlink(Vec<u8>),
394 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
511named!(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
582named!(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
588named!(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
601named!(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 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 | preceded!(tag!("v"), take_till!(|_| { false })) => {
731 |_| Command::UnknownVCommand
732 })
733}
734
735named!(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
746named!(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 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 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 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 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 _ => 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
918pub enum Error {
920 Error(u8),
924 Unimplemented,
930}
931
932#[derive(Clone, Copy, Debug)]
936pub enum ProcessType {
937 Attached,
939 Created,
941}
942
943#[derive(Clone, Copy, Debug)]
945pub enum StopReason {
946 Signal(u8),
948 Exited(u64, u8),
950 ExitedWithSignal(u64, u8),
953 ThreadExited(ThreadId, u64),
955 NoMoreThreads,
960 }
978
979#[derive(Clone, Debug)]
981pub enum SymbolLookupResponse {
982 Ok,
984 Symbol(String),
986}
987
988pub trait Handler {
994 fn query_supported_features(&self) -> Vec<String> {
999 vec![]
1000 }
1001
1002 fn attached(&self, _pid: Option<u64>) -> Result<ProcessType, Error>;
1005
1006 fn detach(&self, _pid: Option<u64>) -> Result<(), Error> {
1008 Err(Error::Unimplemented)
1009 }
1010
1011 fn kill(&self, _pid: Option<u64>) -> Result<(), Error> {
1016 Err(Error::Unimplemented)
1017 }
1018
1019 fn ping_thread(&self, _id: ThreadId) -> Result<(), Error> {
1022 Err(Error::Unimplemented)
1023 }
1024
1025 fn read_memory(&self, _region: MemoryRegion) -> Result<Vec<u8>, Error> {
1027 Err(Error::Unimplemented)
1028 }
1029
1030 fn write_memory(&self, _address: u64, _bytes: &[u8]) -> Result<(), Error> {
1032 Err(Error::Unimplemented)
1033 }
1034
1035 fn read_register(&self, _register: u64) -> Result<Vec<u8>, Error> {
1040 Err(Error::Unimplemented)
1041 }
1042
1043 fn write_register(&self, _register: u64, _contents: &[u8]) -> Result<(), Error> {
1049 Err(Error::Unimplemented)
1050 }
1051
1052 fn read_general_registers(&self) -> Result<Vec<u8>, Error> {
1057 Err(Error::Unimplemented)
1058 }
1059
1060 fn write_general_registers(&self, _contents: &[u8]) -> Result<(), Error> {
1065 Err(Error::Unimplemented)
1066 }
1067
1068 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 fn current_thread(&self) -> Result<Option<ThreadId>, Error> {
1093 Ok(None)
1094 }
1095
1096 fn set_current_thread(&self, _for: SetThreadFor, _id: ThreadId) -> Result<(), Error> {
1098 Err(Error::Unimplemented)
1099 }
1100
1101 fn search_memory(&self, _address: u64, _length: u64, _bytes: &[u8]) -> Result<Option<u64>, Error> {
1106 Err(Error::Unimplemented)
1107 }
1108
1109 fn halt_reason(&self) -> Result<StopReason, Error>;
1111
1112 fn invoke(&self, _: &[u8]) -> Result<String, Error> {
1117 Err(Error::Unimplemented)
1118 }
1119
1120 fn set_address_randomization(&self, _enable: bool) -> Result<(), Error> {
1123 Err(Error::Unimplemented)
1124 }
1125
1126 fn catch_syscalls(&self, _syscalls: Option<Vec<u64>>) -> Result<(), Error> {
1132 Err(Error::Unimplemented)
1133 }
1134
1135 fn set_pass_signals(&self, _signals: Vec<u64>) -> Result<(), Error> {
1139 Ok(())
1140 }
1141
1142 fn set_program_signals(&self, _signals: Vec<u64>) -> Result<(), Error> {
1146 Ok(())
1147 }
1148
1149 fn thread_info(&self, _thread: ThreadId) -> Result<String, Error> {
1153 Err(Error::Unimplemented)
1154 }
1155
1156 fn thread_list(&self, _reset: bool) -> Result<Vec<ThreadId>, Error> {
1167 Err(Error::Unimplemented)
1168 }
1169
1170 fn insert_software_breakpoint(&self, _breakpoint: Breakpoint) -> Result<(), Error> {
1172 Err(Error::Unimplemented)
1173 }
1174
1175 fn insert_hardware_breakpoint(&self, _breakpoint: Breakpoint) -> Result<(), Error> {
1177 Err(Error::Unimplemented)
1178 }
1179
1180 fn insert_write_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1182 Err(Error::Unimplemented)
1183 }
1184
1185 fn insert_read_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1187 Err(Error::Unimplemented)
1188 }
1189
1190 fn insert_access_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1192 Err(Error::Unimplemented)
1193 }
1194
1195 fn remove_software_breakpoint(&self, _breakpoint: Breakpoint) -> Result<(), Error> {
1197 Err(Error::Unimplemented)
1198 }
1199
1200 fn remove_hardware_breakpoint(&self, _breakpoint: Breakpoint) -> Result<(), Error> {
1202 Err(Error::Unimplemented)
1203 }
1204
1205 fn remove_write_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1207 Err(Error::Unimplemented)
1208 }
1209
1210 fn remove_read_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1212 Err(Error::Unimplemented)
1213 }
1214
1215 fn remove_access_watchpoint(&self, _watchpoint: Watchpoint) -> Result<(), Error> {
1217 Err(Error::Unimplemented)
1218 }
1219
1220 fn query_supported_vcont(&self) -> Result<Cow<'static, [VContFeature]>, Error> {
1222 Err(Error::Unimplemented)
1223 }
1224
1225 fn vcont(&self, _request: Vec<(VCont, Option<ThreadId>)>) -> Result<StopReason, Error> {
1228 Err(Error::Unimplemented)
1229 }
1230
1231 fn fs(&self) -> Result<&dyn FileSystem, ()> {
1237 Err(())
1238 }
1239
1240 #[cfg(feature = "all_stop")]
1242 fn process_continue(&self) -> Result<StopReason, Error> {
1243 Err(Error::Unimplemented)
1244 }
1245
1246 #[cfg(feature = "all_stop")]
1248 fn process_step(&self) -> Result<StopReason, Error> {
1249 Err(Error::Unimplemented)
1250 }
1251
1252 fn process_symbol(&self, _sym_value: &str, _sym_name: &str) -> Result<SymbolLookupResponse, Error> {
1254 Err(Error::Unimplemented)
1255 }
1256
1257 #[cfg(feature = "lldb")]
1259 fn register_info(&self, _reg: u64) -> Result<String, Error> {
1260 Err(Error::Unimplemented)
1261 }
1262
1263 #[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, Error(HostErrno), Integer(u64), Data(Vec<u8>), Stat(HostStat), }
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 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
1388impl<'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
1441struct 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 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 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 match remaining.first() {
1537 Some(byte) => writer.write_all(&[b'}', byte ^ 0x20])?,
1539 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 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 write!(writer, "W{:02x};process:{:x}", status, pid)?;
1609 }
1610 StopReason::ExitedWithSignal(pid, status) => {
1611 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 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
1685fn 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 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 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 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 Command::CtrlC => Response::Empty,
1768
1769 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
1829pub 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 if ack_mode && writer.write_all(&b"+"[..]).is_err() {
1851 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 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 check(vec![1, 2, 3], vec![1, 2, 3]);
2302 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 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 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}