revm_bytecode/eof/
printer.rs

1#![cfg(feature = "std")]
2
3pub fn print(code: &[u8]) {
4    use crate::{opcode::*, utils::read_i16};
5    use 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[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            let immediate = &code[i + 1..i + 1 + opcode.immediate_size() as usize];
30            print!(" : 0x{:}", hex::encode(immediate));
31            if opcode.immediate_size() == 2 {
32                print!(" ({})", i16::from_be_bytes(immediate.try_into().unwrap()));
33            }
34        }
35        println!();
36
37        let mut rjumpv_additional_immediates = 0;
38        if op == RJUMPV {
39            let max_index = code[i + 1] as usize;
40            let len = max_index + 1;
41            // And max_index+1 is to get size of vtable as index starts from 0.
42            rjumpv_additional_immediates = len * 2;
43
44            // +1 is for max_index byte
45            if i + 1 + rjumpv_additional_immediates >= code.len() {
46                println!("Malformed code: immediate out of bounds");
47                break;
48            }
49
50            for vtablei in 0..len {
51                let offset = unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize;
52                println!("RJUMPV[{vtablei}]: 0x{offset:04X} ({offset})");
53            }
54        }
55
56        i += 1 + opcode.immediate_size() as usize + rjumpv_additional_immediates;
57    }
58}
59
60#[cfg(test)]
61mod test {
62    use primitives::hex;
63
64    #[test]
65    fn sanity_test() {
66        super::print(&hex!("6001e200ffff00"));
67    }
68}