ckb_debugger/
machine_assign.rs

1use ckb_script::{CoreMachine as CkbScriptCoreMachineType, DataLocation, ROOT_VM_ID, RunMode, Scheduler, VmArgs};
2use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider};
3use ckb_vm::cost_model::estimate_cycles;
4use ckb_vm::decoder::Decoder;
5use ckb_vm::instructions::execute;
6use ckb_vm::registers::A7;
7use ckb_vm::{Bytes, CoreMachine, Error, Machine, SupportMachine, Syscalls};
8
9pub struct MachineAssign<DL>
10where
11    DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
12{
13    pub id: u64,
14    pub scheduler: Scheduler<DL>,
15    pub expand_cycles: u64,
16    pub expand_syscalls: Vec<Box<(dyn Syscalls<CkbScriptCoreMachineType>)>>,
17}
18
19impl<DL> CoreMachine for MachineAssign<DL>
20where
21    DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
22{
23    type REG = u64;
24    type MEM = <CkbScriptCoreMachineType as CoreMachine>::MEM;
25
26    fn pc(&self) -> &Self::REG {
27        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
28        dm.pc()
29    }
30
31    fn update_pc(&mut self, pc: Self::REG) {
32        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
33        dm.update_pc(pc)
34    }
35
36    fn commit_pc(&mut self) {
37        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
38        dm.commit_pc()
39    }
40
41    fn memory(&self) -> &Self::MEM {
42        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
43        dm.memory()
44    }
45
46    fn memory_mut(&mut self) -> &mut Self::MEM {
47        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
48        dm.memory_mut()
49    }
50
51    fn registers(&self) -> &[Self::REG] {
52        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
53        dm.registers()
54    }
55
56    fn set_register(&mut self, idx: usize, value: Self::REG) {
57        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
58        dm.set_register(idx, value)
59    }
60
61    fn version(&self) -> u32 {
62        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
63        dm.version()
64    }
65
66    fn isa(&self) -> u8 {
67        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
68        dm.isa()
69    }
70}
71impl<DL> SupportMachine for MachineAssign<DL>
72where
73    DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
74{
75    fn cycles(&self) -> u64 {
76        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
77        dm.cycles()
78    }
79
80    fn set_cycles(&mut self, cycles: u64) {
81        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
82        dm.set_cycles(cycles)
83    }
84
85    fn max_cycles(&self) -> u64 {
86        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
87        dm.max_cycles()
88    }
89
90    fn set_max_cycles(&mut self, cycles: u64) {
91        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
92        dm.set_max_cycles(cycles);
93    }
94
95    fn running(&self) -> bool {
96        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
97        dm.running()
98    }
99
100    fn set_running(&mut self, running: bool) {
101        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
102        dm.set_running(running)
103    }
104
105    fn reset(&mut self, max_cycles: u64) {
106        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
107        dm.reset(max_cycles)
108    }
109
110    fn reset_signal(&mut self) -> bool {
111        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
112        dm.reset_signal()
113    }
114
115    fn code(&self) -> &Bytes {
116        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
117        dm.code()
118    }
119}
120
121impl<DL> Machine for MachineAssign<DL>
122where
123    DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
124{
125    fn ecall(&mut self) -> Result<(), Error> {
126        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
127        for i in 0..self.expand_syscalls.len() {
128            if self.expand_syscalls[i].ecall(dm.inner_mut())? {
129                return Ok(());
130            }
131        }
132        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
133        let result = dm.ecall();
134        let cycles = dm.cycles();
135        let sid = dm.registers()[A7];
136        if result == Err(Error::Yield) {
137            let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
138            dm.set_cycles(0);
139            self.scheduler.iteration_cycles =
140                self.scheduler.iteration_cycles.checked_add(cycles).ok_or(Error::CyclesExceeded)?;
141            self.scheduler.iterate_process_results(self.id, Err(Error::Yield))?;
142            self.consume_cycles(self.scheduler.iteration_cycles)?;
143
144            let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
145            let next_pc = dm.inner_mut().pc() + 4;
146
147            self.wait()?;
148
149            let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
150            dm.inner_mut().update_pc(next_pc);
151            return Ok(());
152        }
153        if sid == 93 {
154            let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
155            dm.set_cycles(0);
156            self.scheduler.iteration_cycles =
157                self.scheduler.iteration_cycles.checked_add(cycles).ok_or(Error::CyclesExceeded)?;
158            self.consume_cycles(self.scheduler.iteration_cycles)?;
159            return Ok(());
160        }
161        result
162    }
163
164    fn ebreak(&mut self) -> Result<(), Error> {
165        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
166        dm.ebreak()
167    }
168}
169
170impl<DL> std::fmt::Display for MachineAssign<DL>
171where
172    DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
173{
174    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
175        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
176        dm.fmt(f)
177    }
178}
179
180impl<DL> MachineAssign<DL>
181where
182    DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
183{
184    pub fn new(id: u64, args: &[Bytes], scheduler: Scheduler<DL>) -> Result<Self, Error> {
185        let mut r = Self { id, scheduler, expand_cycles: u64::MAX, expand_syscalls: vec![] };
186        if r.scheduler.states.is_empty() {
187            let location = DataLocation {
188                data_piece_id: r.scheduler.sg_data.sg_info.program_data_piece_id.clone(),
189                offset: 0,
190                length: u64::MAX,
191            };
192            assert_eq!(r.scheduler.boot_vm(&location, VmArgs::Vector(args.to_vec()))?, ROOT_VM_ID);
193        }
194        Ok(r)
195    }
196
197    pub fn consume_cycles(&mut self, cycles: u64) -> Result<(), Error> {
198        self.scheduler.consume_cycles(cycles)?;
199        self.scheduler.iteration_cycles = 0;
200        self.expand_cycles = self.expand_cycles.checked_sub(cycles).ok_or(Error::CyclesExceeded)?;
201        Ok(())
202    }
203
204    pub fn exit_code(&self) -> i8 {
205        let root_vm = &self.scheduler.instantiated[&ROOT_VM_ID];
206        root_vm.1.machine.exit_code()
207    }
208
209    pub fn step(&mut self, decoder: &mut Decoder) -> Result<(), Error> {
210        let instruction = {
211            let pc = *self.pc();
212            let memory = self.memory_mut();
213            decoder.decode(memory, pc)?
214        };
215        let cycles = estimate_cycles(instruction);
216        self.add_cycles(cycles)?;
217        execute(instruction, self)
218    }
219
220    pub fn wait(&mut self) -> Result<(), Error> {
221        loop {
222            let im = self.scheduler.iterate_prepare_machine()?;
223            let id = im.0;
224            let vm = im.1;
225            vm.set_max_cycles(self.expand_cycles);
226            if self.id == id {
227                vm.machine.set_running(true);
228                break;
229            }
230            let result = vm.run();
231            let cycles = vm.machine.cycles();
232            vm.machine.set_cycles(0);
233            self.scheduler.iteration_cycles =
234                self.scheduler.iteration_cycles.checked_add(cycles).ok_or(Error::CyclesExceeded)?;
235            self.scheduler.iterate_process_results(id, result)?;
236            self.consume_cycles(self.scheduler.iteration_cycles)?;
237        }
238        Ok(())
239    }
240
241    pub fn done(&mut self) -> Result<(), Error> {
242        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
243        let dmexit = dm.exit_code();
244        self.scheduler.iterate_process_results(self.id, Ok(dmexit))?;
245        self.scheduler.run(RunMode::LimitCycles(self.expand_cycles))?;
246        return Ok(());
247    }
248}