ckb_debugger/
syscall_file_stream.rs

1use ckb_vm::{
2    Error, Memory, Register, SupportMachine, Syscalls,
3    registers::{A0, A1, A7},
4};
5
6#[derive(Clone)]
7pub struct FileStream {
8    content: Vec<u8>,
9    offset: usize,
10}
11
12impl Default for FileStream {
13    fn default() -> Self {
14        Self { content: Default::default(), offset: 0 }
15    }
16}
17
18impl FileStream {
19    pub fn new(file_name: &str) -> Self {
20        let content = crate::arch::file_read(file_name).unwrap();
21        FileStream { content, offset: 0 }
22    }
23
24    // Mimic: ssize_t read(int fd, void *buf, size_t count);
25    fn read(&mut self, buf: &mut [u8]) -> isize {
26        if self.offset >= self.content.len() {
27            return -1;
28        }
29        let remaining_size = self.content.len() - self.offset;
30        let read_size = std::cmp::min(buf.len(), remaining_size);
31        buf[0..read_size].copy_from_slice(&self.content[self.offset..self.offset + read_size]);
32
33        self.offset += read_size;
34        read_size as isize
35    }
36}
37
38impl<Mac: SupportMachine> Syscalls<Mac> for FileStream {
39    fn initialize(&mut self, _machine: &mut Mac) -> Result<(), Error> {
40        Ok(())
41    }
42
43    fn ecall(&mut self, machine: &mut Mac) -> Result<bool, Error> {
44        let id = machine.registers()[A7].to_u64();
45        if id != 9000 {
46            return Ok(false);
47        }
48        let arg_buf = machine.registers()[A0].to_u64();
49        let arg_count = machine.registers()[A1].to_u64();
50        let mut buf = vec![0u8; arg_count as usize];
51        let read_size = self.read(&mut buf);
52        if read_size > 0 {
53            machine.memory_mut().store_bytes(arg_buf, &buf[0..read_size as usize])?;
54            machine.set_register(A0, Mac::REG::from_u64(read_size as u64));
55        } else {
56            machine.set_register(A0, Mac::REG::from_i64(-1));
57        }
58        return Ok(true);
59    }
60}