ckb-debugger 1.1.1

Standalone debugger for Nervos CKB
Documentation
use ckb_vm::{
    Error, Memory, Register, SupportMachine, Syscalls,
    registers::{A0, A1, A7},
};

#[derive(Clone)]
pub struct FileStream {
    content: Vec<u8>,
    offset: usize,
}

impl Default for FileStream {
    fn default() -> Self {
        Self { content: Default::default(), offset: 0 }
    }
}

impl FileStream {
    pub fn new(file_name: &str) -> Self {
        let content = crate::arch::file_read(file_name).unwrap();
        FileStream { content, offset: 0 }
    }

    // Mimic: ssize_t read(int fd, void *buf, size_t count);
    fn read(&mut self, buf: &mut [u8]) -> isize {
        if self.offset >= self.content.len() {
            return -1;
        }
        let remaining_size = self.content.len() - self.offset;
        let read_size = std::cmp::min(buf.len(), remaining_size);
        buf[0..read_size].copy_from_slice(&self.content[self.offset..self.offset + read_size]);

        self.offset += read_size;
        read_size as isize
    }
}

impl<Mac: SupportMachine> Syscalls<Mac> for FileStream {
    fn initialize(&mut self, _machine: &mut Mac) -> Result<(), Error> {
        Ok(())
    }

    fn ecall(&mut self, machine: &mut Mac) -> Result<bool, Error> {
        let id = machine.registers()[A7].to_u64();
        if id != 9000 {
            return Ok(false);
        }
        let arg_buf = machine.registers()[A0].to_u64();
        let arg_count = machine.registers()[A1].to_u64();
        let mut buf = vec![0u8; arg_count as usize];
        let read_size = self.read(&mut buf);
        if read_size > 0 {
            machine.memory_mut().store_bytes(arg_buf, &buf[0..read_size as usize])?;
            machine.set_register(A0, Mac::REG::from_u64(read_size as u64));
        } else {
            machine.set_register(A0, Mac::REG::from_i64(-1));
        }
        return Ok(true);
    }
}