ckb_vm_debug_utils/
gdbstub.rs

1use ckb_vm::{
2    Bytes, Error, Memory, Register,
3    decoder::{Decoder, build_decoder},
4    instructions::{execute, extract_opcode, insts},
5    machine::{CoreMachine, DefaultMachine, Machine, SupportMachine},
6    registers::A7,
7};
8use gdbstub::{
9    arch::Arch,
10    common::Signal,
11    conn::{Connection, ConnectionExt},
12    stub::{
13        SingleThreadStopReason,
14        run_blocking::{BlockingEventLoop, Event, WaitForStopReasonError},
15    },
16    target::{
17        Target, TargetError, TargetResult,
18        ext::{
19            base::{
20                BaseOps,
21                single_register_access::{SingleRegisterAccess, SingleRegisterAccessOps},
22                singlethread::{
23                    SingleThreadBase, SingleThreadRangeStepping, SingleThreadRangeSteppingOps, SingleThreadResume,
24                    SingleThreadResumeOps, SingleThreadSingleStep, SingleThreadSingleStepOps,
25                },
26            },
27            breakpoints::{
28                Breakpoints, BreakpointsOps, HwWatchpoint, HwWatchpointOps, SwBreakpoint, SwBreakpointOps, WatchKind,
29            },
30            catch_syscalls::{CatchSyscallPosition, CatchSyscalls, CatchSyscallsOps, SyscallNumbers},
31        },
32    },
33};
34use gdbstub_arch::riscv::reg::{RiscvCoreRegs, id::RiscvRegId};
35use std::collections::HashSet;
36use std::fmt::Debug;
37use std::hash::Hash as StdHash;
38use std::marker::PhantomData;
39
40#[derive(Debug, Clone)]
41pub enum ExecMode<R: Register> {
42    Step,
43    Continue,
44    RangeStep(R, R),
45}
46
47pub enum FilteredSyscalls<R> {
48    None,
49    All,
50    Filter(HashSet<R>),
51}
52
53impl<R: StdHash + Eq> FilteredSyscalls<R> {
54    pub fn filtered(&self, syscall_number: &R) -> bool {
55        match self {
56            FilteredSyscalls::None => false,
57            FilteredSyscalls::All => true,
58            FilteredSyscalls::Filter(filter) => filter.contains(syscall_number),
59        }
60    }
61}
62
63pub struct GdbStubHandler<M: SupportMachine, A> {
64    exec_mode: ExecMode<M::REG>,
65    machine: DefaultMachine<M>,
66    decoder: Decoder,
67    breakpoints: Vec<M::REG>,
68    catch_syscalls: FilteredSyscalls<M::REG>,
69    watchpoints: Vec<(M::REG, WatchKind)>,
70    memory_writes: Vec<M::REG>,
71    memory_reads: Vec<M::REG>,
72    _arch: PhantomData<A>,
73}
74
75// Note a lot of code in this file is copied over from
76// https://github.com/daniel5151/gdbstub/blob/36f166e1aabe47ea2f0508207372e4a302fbac87/examples/armv4t/emu.rs
77#[derive(Debug, Clone, PartialEq, Eq)]
78enum VmEvent<R: Register> {
79    IncomingData,
80    DoneStep,
81    Exited(u8),
82    Break,
83    WatchWrite(R),
84    WatchRead(R),
85    CatchSyscall(R),
86    Error(Error),
87}
88
89impl<R: Register, M: SupportMachine + CoreMachine<REG = R>, A: Arch<Usize = R>> GdbStubHandler<M, A> {
90    pub fn new(machine: DefaultMachine<M>) -> Self {
91        let decoder = build_decoder::<M::REG>(machine.isa(), machine.version());
92        Self {
93            machine,
94            decoder,
95            exec_mode: ExecMode::Continue,
96            breakpoints: vec![],
97            catch_syscalls: FilteredSyscalls::None,
98            watchpoints: vec![],
99            memory_writes: vec![],
100            memory_reads: vec![],
101            _arch: PhantomData,
102        }
103    }
104
105    fn clear_memory_ops(&mut self) {
106        self.memory_writes.clear();
107        self.memory_reads.clear();
108    }
109}
110
111impl<R: Register + Debug + Eq + StdHash, M: SupportMachine + CoreMachine<REG = R>, A: Arch<Usize = R>>
112    GdbStubHandler<M, A>
113{
114    pub fn run_till_exited(mut self) -> Result<(i8, u64), Error> {
115        while self.machine.running() {
116            self.step_inner()?;
117        }
118        Ok((self.machine.exit_code(), self.machine.cycles()))
119    }
120
121    fn next_opcode(&mut self) -> Option<u16> {
122        let pc = self.machine.inner_mut().pc().to_u64();
123        let memory = self.machine.inner_mut().memory_mut();
124        let inst = self.decoder.decode(memory, pc).ok()?;
125        Some(extract_opcode(inst))
126    }
127
128    fn step_inner(&mut self) -> Result<(), Error> {
129        let instruction = {
130            let pc = self.machine.inner_mut().pc().to_u64();
131            let memory = self.machine.inner_mut().memory_mut();
132            self.decoder.decode(memory, pc)?
133        };
134        let cycles = self.machine.instruction_cycle_func()(instruction);
135        self.machine.add_cycles(cycles)?;
136        self.clear_memory_ops();
137        execute(instruction, self)
138    }
139
140    fn step(&mut self) -> Option<VmEvent<M::REG>> {
141        if self.machine.reset_signal() {
142            self.decoder.reset_instructions_cache()
143        }
144        if !self.machine.running() {
145            return Some(VmEvent::Exited(self.machine.exit_code() as u8));
146        }
147        match self.step_inner() {
148            Ok(_) => {
149                if let Some(opcode) = self.next_opcode() {
150                    if opcode == insts::OP_ECALL {
151                        let number = self.machine.inner_mut().registers()[A7].clone();
152                        if self.catch_syscalls.filtered(&number) {
153                            return Some(VmEvent::CatchSyscall(number));
154                        }
155                    }
156                }
157                if self.breakpoints.contains(self.machine.inner_mut().pc()) {
158                    return Some(VmEvent::Break);
159                }
160                if !self.memory_writes.is_empty() {
161                    return Some(VmEvent::WatchWrite(self.memory_writes.pop().unwrap()));
162                }
163                if !self.memory_reads.is_empty() {
164                    return Some(VmEvent::WatchRead(self.memory_reads.pop().unwrap()));
165                }
166                None
167            }
168            Err(e) => Some(VmEvent::Error(e)),
169        }
170    }
171
172    fn execute(&mut self, mut poll_incoming_data: impl FnMut() -> bool) -> VmEvent<M::REG> {
173        if poll_incoming_data() {
174            return VmEvent::IncomingData;
175        }
176        match self.exec_mode.clone() {
177            ExecMode::Step => self.step().unwrap_or(VmEvent::DoneStep),
178            ExecMode::Continue => {
179                let mut executed_cycles = 0;
180                loop {
181                    if let Some(event) = self.step() {
182                        let mut continue_step = true;
183
184                        match event {
185                            VmEvent::DoneStep | VmEvent::Exited(_) | VmEvent::Break | VmEvent::Error(_) => {
186                                continue_step = false;
187                            }
188                            _ => {}
189                        };
190
191                        if !continue_step {
192                            break event;
193                        }
194                    }
195
196                    executed_cycles += 1;
197                    if executed_cycles % 1024 == 0 && poll_incoming_data() {
198                        break VmEvent::IncomingData;
199                    }
200                }
201            }
202            ExecMode::RangeStep(start, end) => {
203                let mut executed_cycles = 0;
204                loop {
205                    if let Some(event) = self.step() {
206                        break event;
207                    }
208
209                    if !(start.to_u64()..end.to_u64()).contains(&self.machine.inner_mut().pc().to_u64()) {
210                        break VmEvent::DoneStep;
211                    }
212
213                    executed_cycles += 1;
214                    if executed_cycles % 1024 == 0 && poll_incoming_data() {
215                        break VmEvent::IncomingData;
216                    }
217                }
218            }
219        }
220    }
221}
222
223impl<
224    R: Register + Debug + Eq + StdHash,
225    M: SupportMachine + CoreMachine<REG = R>,
226    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
227> Target for GdbStubHandler<M, A>
228{
229    type Arch = A;
230    type Error = Error;
231
232    fn base_ops(&mut self) -> BaseOps<Self::Arch, Self::Error> {
233        BaseOps::SingleThread(self)
234    }
235
236    fn support_breakpoints(&mut self) -> Option<BreakpointsOps<'_, Self>> {
237        Some(self)
238    }
239
240    fn support_catch_syscalls(&mut self) -> Option<CatchSyscallsOps<'_, Self>> {
241        Some(self)
242    }
243}
244
245impl<
246    R: Register + Debug + Eq + StdHash,
247    M: SupportMachine + CoreMachine<REG = R>,
248    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
249> SingleThreadBase for GdbStubHandler<M, A>
250{
251    fn read_registers(&mut self, regs: &mut <Self::Arch as Arch>::Registers) -> TargetResult<(), Self> {
252        for (i, val) in self.machine.registers().iter().enumerate() {
253            regs.x[i] = val.clone();
254        }
255        regs.pc = self.machine.pc().clone();
256        Ok(())
257    }
258
259    fn write_registers(&mut self, regs: &<Self::Arch as Arch>::Registers) -> TargetResult<(), Self> {
260        regs.x.iter().enumerate().for_each(|(i, val)| {
261            self.machine.set_register(i, val.clone());
262        });
263        self.machine.update_pc(regs.pc.clone());
264        self.machine.commit_pc();
265        Ok(())
266    }
267
268    fn read_addrs(&mut self, start_addr: <Self::Arch as Arch>::Usize, data: &mut [u8]) -> TargetResult<usize, Self> {
269        for i in 0..data.len() {
270            data[i] = self
271                .machine
272                .memory_mut()
273                .load8(&M::REG::from_u64(start_addr.to_u64() + i as u64))
274                .map_err(TargetError::Fatal)?
275                .to_u8();
276        }
277        Ok(data.len())
278    }
279
280    fn write_addrs(&mut self, start_addr: <Self::Arch as Arch>::Usize, data: &[u8]) -> TargetResult<(), Self> {
281        self.machine.memory_mut().store_bytes(start_addr.to_u64(), data).map_err(TargetError::Fatal)
282    }
283
284    fn support_single_register_access(&mut self) -> Option<SingleRegisterAccessOps<'_, (), Self>> {
285        Some(self)
286    }
287
288    fn support_resume(&mut self) -> Option<SingleThreadResumeOps<'_, Self>> {
289        Some(self)
290    }
291}
292
293impl<
294    R: Register + Debug + Eq + StdHash,
295    M: SupportMachine + CoreMachine<REG = R>,
296    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
297> SingleRegisterAccess<()> for GdbStubHandler<M, A>
298{
299    fn read_register(
300        &mut self,
301        _tid: (),
302        reg_id: <Self::Arch as Arch>::RegId,
303        buf: &mut [u8],
304    ) -> TargetResult<usize, Self> {
305        let value = match reg_id {
306            RiscvRegId::Pc => self.machine.pc(),
307            RiscvRegId::Gpr(idx) => &self.machine.registers()[idx as usize],
308            _ => return Err(TargetError::Fatal(Error::External(format!("Invalid register id: {:?}", reg_id)))),
309        };
310        buf.copy_from_slice(&value.to_u64().to_le_bytes()[0..(R::BITS as usize / 8)]);
311        Ok(buf.len())
312    }
313
314    fn write_register(&mut self, _tid: (), reg_id: <Self::Arch as Arch>::RegId, val: &[u8]) -> TargetResult<(), Self> {
315        let mut u64_buf = [0u8; 8];
316        u64_buf[0..val.len()].copy_from_slice(val);
317        let v = R::from_u64(u64::from_le_bytes(u64_buf));
318        match reg_id {
319            RiscvRegId::Pc => {
320                self.machine.update_pc(v);
321                self.machine.commit_pc();
322            }
323            RiscvRegId::Gpr(idx) => {
324                self.machine.set_register(idx as usize, v);
325            }
326            _ => return Err(TargetError::Fatal(Error::External(format!("Invalid register id: {:?}", reg_id)))),
327        };
328
329        Ok(())
330    }
331}
332
333// This is only for setting execution modes, the actual execution shall live within
334// BlockingEventLoop trait impl.
335impl<
336    R: Register + Debug + Eq + StdHash,
337    M: SupportMachine + CoreMachine<REG = R>,
338    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
339> SingleThreadResume for GdbStubHandler<M, A>
340{
341    fn resume(&mut self, signal: Option<Signal>) -> Result<(), Self::Error> {
342        if signal.is_some() {
343            return Err(Error::External("no support for continuing with signal".to_string()));
344        }
345        self.exec_mode = ExecMode::Continue;
346        Ok(())
347    }
348
349    fn support_single_step(&mut self) -> Option<SingleThreadSingleStepOps<'_, Self>> {
350        Some(self)
351    }
352
353    fn support_range_step(&mut self) -> Option<SingleThreadRangeSteppingOps<'_, Self>> {
354        Some(self)
355    }
356}
357
358impl<
359    R: Register + Debug + Eq + StdHash,
360    M: SupportMachine + CoreMachine<REG = R>,
361    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
362> SingleThreadRangeStepping for GdbStubHandler<M, A>
363{
364    fn resume_range_step(
365        &mut self,
366        start: <Self::Arch as Arch>::Usize,
367        end: <Self::Arch as Arch>::Usize,
368    ) -> Result<(), Self::Error> {
369        self.exec_mode = ExecMode::RangeStep(start, end);
370        Ok(())
371    }
372}
373
374impl<
375    R: Register + Debug + Eq + StdHash,
376    M: SupportMachine + CoreMachine<REG = R>,
377    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
378> SingleThreadSingleStep for GdbStubHandler<M, A>
379{
380    fn step(&mut self, signal: Option<Signal>) -> Result<(), Self::Error> {
381        if signal.is_some() {
382            return Err(Error::External("no support for stepping with signal".to_string()));
383        }
384        self.exec_mode = ExecMode::Step;
385        Ok(())
386    }
387}
388
389impl<
390    R: Register + Debug + Eq + StdHash,
391    M: SupportMachine + CoreMachine<REG = R>,
392    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
393> Breakpoints for GdbStubHandler<M, A>
394{
395    fn support_sw_breakpoint(&mut self) -> Option<SwBreakpointOps<'_, Self>> {
396        Some(self)
397    }
398
399    fn support_hw_watchpoint(&mut self) -> Option<HwWatchpointOps<'_, Self>> {
400        Some(self)
401    }
402}
403
404impl<
405    R: Register + Debug + Eq + StdHash,
406    M: SupportMachine + CoreMachine<REG = R>,
407    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
408> SwBreakpoint for GdbStubHandler<M, A>
409{
410    fn add_sw_breakpoint(
411        &mut self,
412        addr: <Self::Arch as Arch>::Usize,
413        _kind: <Self::Arch as Arch>::BreakpointKind,
414    ) -> TargetResult<bool, Self> {
415        self.breakpoints.push(addr);
416        Ok(true)
417    }
418
419    fn remove_sw_breakpoint(
420        &mut self,
421        addr: <Self::Arch as Arch>::Usize,
422        _kind: <Self::Arch as Arch>::BreakpointKind,
423    ) -> TargetResult<bool, Self> {
424        match self.breakpoints.iter().position(|x| *x == addr) {
425            None => return Ok(false),
426            Some(pos) => self.breakpoints.remove(pos),
427        };
428
429        Ok(true)
430    }
431}
432
433impl<
434    R: Register + Debug + Eq + StdHash,
435    M: SupportMachine + CoreMachine<REG = R>,
436    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
437> HwWatchpoint for GdbStubHandler<M, A>
438{
439    fn add_hw_watchpoint(
440        &mut self,
441        addr: <Self::Arch as Arch>::Usize,
442        _len: <Self::Arch as Arch>::Usize,
443        kind: WatchKind,
444    ) -> TargetResult<bool, Self> {
445        self.watchpoints.push((addr, kind));
446        Ok(true)
447    }
448
449    fn remove_hw_watchpoint(
450        &mut self,
451        addr: <Self::Arch as Arch>::Usize,
452        _len: <Self::Arch as Arch>::Usize,
453        kind: WatchKind,
454    ) -> TargetResult<bool, Self> {
455        match self.watchpoints.iter().position(|(a, k)| *a == addr && *k == kind) {
456            None => return Ok(false),
457            Some(pos) => self.breakpoints.remove(pos),
458        };
459
460        Ok(true)
461    }
462}
463
464impl<
465    R: Register + Debug + Eq + StdHash,
466    M: SupportMachine + CoreMachine<REG = R>,
467    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
468> CatchSyscalls for GdbStubHandler<M, A>
469{
470    fn enable_catch_syscalls(
471        &mut self,
472        filter: Option<SyscallNumbers<'_, <Self::Arch as Arch>::Usize>>,
473    ) -> TargetResult<(), Self> {
474        self.catch_syscalls = match filter {
475            Some(numbers) => FilteredSyscalls::Filter(numbers.collect()),
476            None => FilteredSyscalls::All,
477        };
478        Ok(())
479    }
480
481    fn disable_catch_syscalls(&mut self) -> TargetResult<(), Self> {
482        self.catch_syscalls = FilteredSyscalls::None;
483        Ok(())
484    }
485}
486
487#[derive(Default)]
488pub struct GdbStubHandlerEventLoop<M, A> {
489    _machine: PhantomData<M>,
490    _arch: PhantomData<A>,
491}
492
493impl<
494    R: Register + Debug + Eq + StdHash,
495    M: SupportMachine + CoreMachine<REG = R>,
496    A: Arch<Usize = R, Registers = RiscvCoreRegs<R>, RegId = RiscvRegId<R>>,
497> BlockingEventLoop for GdbStubHandlerEventLoop<M, A>
498{
499    type Target = GdbStubHandler<M, A>;
500    type Connection = Box<dyn ConnectionExt<Error = std::io::Error>>;
501    type StopReason = SingleThreadStopReason<A::Usize>;
502
503    fn on_interrupt(
504        _target: &mut Self::Target,
505    ) -> Result<Option<SingleThreadStopReason<A::Usize>>, <GdbStubHandler<M, A> as Target>::Error> {
506        Ok(Some(SingleThreadStopReason::Signal(Signal::SIGINT)))
507    }
508
509    #[allow(clippy::type_complexity)]
510    fn wait_for_stop_reason(
511        target: &mut Self::Target,
512        conn: &mut Self::Connection,
513    ) -> Result<
514        Event<SingleThreadStopReason<A::Usize>>,
515        WaitForStopReasonError<<Self::Target as Target>::Error, <Self::Connection as Connection>::Error>,
516    > {
517        let poll_incoming_data = || conn.peek().map(|b| b.is_some()).unwrap_or(true);
518
519        Ok(match target.execute(poll_incoming_data) {
520            VmEvent::IncomingData => {
521                let byte = conn.read().map_err(WaitForStopReasonError::Connection)?;
522                Event::IncomingData(byte)
523            }
524            VmEvent::DoneStep => Event::TargetStopped(SingleThreadStopReason::DoneStep),
525            VmEvent::Exited(code) => Event::TargetStopped(SingleThreadStopReason::Exited(code)),
526            VmEvent::Break => Event::TargetStopped(SingleThreadStopReason::SwBreak(())),
527            VmEvent::WatchRead(addr) => {
528                Event::TargetStopped(SingleThreadStopReason::Watch { tid: (), kind: WatchKind::Read, addr })
529            }
530            VmEvent::WatchWrite(addr) => {
531                Event::TargetStopped(SingleThreadStopReason::Watch { tid: (), kind: WatchKind::Write, addr })
532            }
533            VmEvent::CatchSyscall(number) => Event::TargetStopped(SingleThreadStopReason::CatchSyscall {
534                tid: None,
535                number,
536                position: CatchSyscallPosition::Entry,
537            }),
538            VmEvent::Error(e) => return Err(WaitForStopReasonError::Target(e)),
539        })
540    }
541}
542
543impl<R: Register, M: SupportMachine + CoreMachine<REG = R>, A> Memory for GdbStubHandler<M, A> {
544    type REG = R;
545
546    fn new() -> Self {
547        todo!()
548    }
549
550    fn new_with_memory(_: usize) -> Self {
551        todo!()
552    }
553
554    fn memory_size(&self) -> usize {
555        self.machine.memory().memory_size()
556    }
557
558    fn load_bytes(&mut self, addr: u64, size: u64) -> Result<bytes::Bytes, ckb_vm::Error> {
559        self.machine.memory_mut().load_bytes(addr, size)
560    }
561
562    fn lr(&self) -> &<Self as Memory>::REG {
563        self.machine.memory().lr()
564    }
565
566    fn set_lr(&mut self, addr: &<Self as Memory>::REG) {
567        self.machine.memory_mut().set_lr(addr)
568    }
569
570    fn init_pages(
571        &mut self,
572        addr: u64,
573        size: u64,
574        flags: u8,
575        source: Option<Bytes>,
576        offset_from_addr: u64,
577    ) -> Result<(), Error> {
578        self.machine.memory_mut().init_pages(addr, size, flags, source, offset_from_addr)
579    }
580
581    fn fetch_flag(&mut self, page: u64) -> Result<u8, Error> {
582        self.machine.memory_mut().fetch_flag(page)
583    }
584
585    fn set_flag(&mut self, page: u64, flag: u8) -> Result<(), Error> {
586        self.machine.memory_mut().set_flag(page, flag)
587    }
588
589    fn clear_flag(&mut self, page: u64, flag: u8) -> Result<(), Error> {
590        self.machine.memory_mut().clear_flag(page, flag)
591    }
592
593    fn store_byte(&mut self, addr: u64, size: u64, value: u8) -> Result<(), Error> {
594        self.machine.memory_mut().store_byte(addr, size, value)
595    }
596
597    fn store_bytes(&mut self, addr: u64, value: &[u8]) -> Result<(), Error> {
598        self.machine.memory_mut().store_bytes(addr, value)
599    }
600
601    fn execute_load16(&mut self, addr: u64) -> Result<u16, Error> {
602        self.machine.memory_mut().execute_load16(addr)
603    }
604
605    fn execute_load32(&mut self, addr: u64) -> Result<u32, Error> {
606        self.machine.memory_mut().execute_load32(addr)
607    }
608
609    fn load8(&mut self, addr: &Self::REG) -> Result<Self::REG, Error> {
610        let result = self.machine.memory_mut().load8(addr)?;
611        self.memory_reads.push(addr.clone());
612        Ok(result)
613    }
614
615    fn load16(&mut self, addr: &Self::REG) -> Result<Self::REG, Error> {
616        let result = self.machine.memory_mut().load16(addr)?;
617        self.memory_reads.push(addr.clone());
618        Ok(result)
619    }
620
621    fn load32(&mut self, addr: &Self::REG) -> Result<Self::REG, Error> {
622        let result = self.machine.memory_mut().load32(addr)?;
623        self.memory_reads.push(addr.clone());
624        Ok(result)
625    }
626
627    fn load64(&mut self, addr: &Self::REG) -> Result<Self::REG, Error> {
628        let result = self.machine.memory_mut().load64(addr)?;
629        self.memory_reads.push(addr.clone());
630        Ok(result)
631    }
632
633    fn store8(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
634        self.machine.memory_mut().store8(addr, value)?;
635        self.memory_writes.push(addr.clone());
636        Ok(())
637    }
638
639    fn store16(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
640        self.machine.memory_mut().store16(addr, value)?;
641        self.memory_writes.push(addr.clone());
642        Ok(())
643    }
644
645    fn store32(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
646        self.machine.memory_mut().store32(addr, value)?;
647        self.memory_writes.push(addr.clone());
648        Ok(())
649    }
650
651    fn store64(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
652        self.machine.memory_mut().store64(addr, value)?;
653        self.memory_writes.push(addr.clone());
654        Ok(())
655    }
656}
657
658impl<R: Register, M: SupportMachine + CoreMachine<REG = R>, A> CoreMachine for GdbStubHandler<M, A> {
659    type REG = R;
660    type MEM = Self;
661
662    fn pc(&self) -> &Self::REG {
663        self.machine.pc()
664    }
665
666    fn update_pc(&mut self, pc: Self::REG) {
667        self.machine.update_pc(pc)
668    }
669
670    fn commit_pc(&mut self) {
671        self.machine.commit_pc()
672    }
673
674    fn memory(&self) -> &Self::MEM {
675        self
676    }
677
678    fn memory_mut(&mut self) -> &mut Self::MEM {
679        self
680    }
681
682    fn registers(&self) -> &[Self::REG] {
683        self.machine.registers()
684    }
685
686    fn set_register(&mut self, idx: usize, value: Self::REG) {
687        self.machine.set_register(idx, value)
688    }
689
690    fn version(&self) -> u32 {
691        self.machine.version()
692    }
693
694    fn isa(&self) -> u8 {
695        self.machine.isa()
696    }
697}
698
699impl<R: Register, M: SupportMachine + CoreMachine<REG = R>, A> Machine for GdbStubHandler<M, A> {
700    fn ecall(&mut self) -> Result<(), Error> {
701        self.machine.ecall()
702    }
703
704    fn ebreak(&mut self) -> Result<(), Error> {
705        self.machine.ebreak()
706    }
707}