revm_bytecode/eof/
printer.rs

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