rtvm_interpreter/opcode/
eof_printer.rs

1#[cfg(feature = "std")]
2pub fn print_eof_code(code: &[u8]) {
3    use super::*;
4    use crate::instructions::utility::read_i16;
5    use rtvm_primitives::hex;
6
7    // We can check validity and jump destinations in one pass.
8    let mut i = 0;
9    while i < code.len() {
10        let op = code[i];
11        let opcode = &OPCODE_INFO_JUMPTABLE[op as usize];
12
13        let Some(opcode) = opcode else {
14            println!("Unknown opcode: 0x{:02X}", op);
15            i += 1;
16            continue;
17        };
18
19        if opcode.immediate_size != 0 {
20            // check if the opcode immediate are within the bounds of the code
21            if i + opcode.immediate_size as usize >= code.len() {
22                println!("Malformed code: immediate out of bounds");
23                break;
24            }
25        }
26
27        print!("{}", opcode.name);
28        if opcode.immediate_size != 0 {
29            print!(
30                " : 0x{:}",
31                hex::encode(&code[i + 1..i + 1 + opcode.immediate_size as usize])
32            );
33        }
34
35        let mut rjumpv_additional_immediates = 0;
36        if op == RJUMPV {
37            let max_index = code[i + 1] as usize;
38            let len = max_index + 1;
39            // and max_index+1 is to get size of vtable as index starts from 0.
40            rjumpv_additional_immediates = len * 2;
41
42            // +1 is for max_index byte
43            if i + 1 + rjumpv_additional_immediates >= code.len() {
44                println!("Malformed code: immediate out of bounds");
45                break;
46            }
47
48            for vtablei in 0..len {
49                let offset = unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize;
50                println!("RJUMPV[{vtablei}]: 0x{offset:04X}({offset})");
51            }
52        }
53
54        i += 1 + opcode.immediate_size as usize + rjumpv_additional_immediates;
55    }
56}
57
58#[cfg(test)]
59mod test {
60    use super::*;
61    use rtvm_primitives::hex;
62
63    #[test]
64    fn sanity_test() {
65        print_eof_code(&hex!("6001e200ffff00"));
66    }
67}