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#[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
333impl<
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}