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            dm.set_cycles(0);
138            self.scheduler.iterate_process_results(self.id, Err(Error::Yield))?;
139            self.consume_cycles(cycles)?;
140            self.wait()?;
141            if sid == 2043 {
142                // Special handling for ExecV2.
143                let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
144                dm.set_running(true)
145            }
146            return Ok(());
147        }
148        if sid == 93 {
149            dm.set_cycles(0);
150            self.consume_cycles(cycles)?;
151            return Ok(());
152        }
153        result
154    }
155
156    fn ebreak(&mut self) -> Result<(), Error> {
157        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
158        dm.ebreak()
159    }
160}
161
162impl<DL> std::fmt::Display for MachineAssign<DL>
163where
164    DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
165{
166    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
167        let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
168        dm.fmt(f)
169    }
170}
171
172impl<DL> MachineAssign<DL>
173where
174    DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
175{
176    pub fn new(id: u64, args: &[Bytes], scheduler: Scheduler<DL>) -> Result<Self, Error> {
177        let mut r = Self { id, scheduler, expand_cycles: u64::MAX, expand_syscalls: vec![] };
178        if r.scheduler.states.is_empty() {
179            let location = DataLocation {
180                data_piece_id: r.scheduler.sg_data.sg_info.program_data_piece_id.clone(),
181                offset: 0,
182                length: u64::MAX,
183            };
184            assert_eq!(r.scheduler.boot_vm(&location, VmArgs::Vector(args.to_vec()))?, ROOT_VM_ID);
185        }
186        Ok(r)
187    }
188
189    pub fn consume_cycles(&mut self, cycles: u64) -> Result<(), Error> {
190        self.scheduler.consume_cycles(cycles)?;
191        self.expand_cycles = self.expand_cycles.checked_sub(cycles).ok_or(Error::CyclesExceeded)?;
192        Ok(())
193    }
194
195    pub fn exit_code(&self) -> i8 {
196        let root_vm = &self.scheduler.instantiated[&ROOT_VM_ID];
197        root_vm.1.machine.exit_code()
198    }
199
200    pub fn step(&mut self, decoder: &mut Decoder) -> Result<(), Error> {
201        let instruction = {
202            let pc = *self.pc();
203            let memory = self.memory_mut();
204            decoder.decode(memory, pc)?
205        };
206        let cycles = estimate_cycles(instruction);
207        self.add_cycles(cycles)?;
208        execute(instruction, self)
209    }
210
211    pub fn wait(&mut self) -> Result<(), Error> {
212        loop {
213            let im = self.scheduler.iterate_prepare_machine()?;
214            let id = im.0;
215            let vm = im.1;
216            if self.id == id {
217                break;
218            }
219            let result = vm.run();
220            let cycles = vm.machine.cycles();
221            vm.machine.set_cycles(0);
222            self.scheduler.iterate_process_results(id, result)?;
223            self.consume_cycles(cycles)?;
224        }
225        Ok(())
226    }
227
228    pub fn done(&mut self) -> Result<(), Error> {
229        let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
230        let dmexit = dm.exit_code();
231        self.scheduler.iterate_process_results(self.id, Ok(dmexit))?;
232        self.scheduler.run(RunMode::LimitCycles(self.expand_cycles))?;
233        return Ok(());
234    }
235}