ckb_debugger/
machine_assign.rs1use 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}