revm_bytecode/eof/
printer.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#![cfg(feature = "std")]

pub fn print(code: &[u8]) {
    use crate::{opcode::*, utils::read_i16};
    use primitives::hex;

    // We can check validity and jump destinations in one pass.
    let mut i = 0;
    while i < code.len() {
        let op = code[i];
        let opcode = &OPCODE_INFO[op as usize];

        let Some(opcode) = opcode else {
            println!("Unknown opcode: 0x{:02X}", op);
            i += 1;
            continue;
        };

        if opcode.immediate_size() != 0 {
            // check if the opcode immediate are within the bounds of the code
            if i + opcode.immediate_size() as usize >= code.len() {
                println!("Malformed code: immediate out of bounds");
                break;
            }
        }

        print!("{}", opcode.name());
        if opcode.immediate_size() != 0 {
            let immediate = &code[i + 1..i + 1 + opcode.immediate_size() as usize];
            print!(" : 0x{:}", hex::encode(immediate));
            if opcode.immediate_size() == 2 {
                print!(" ({})", i16::from_be_bytes(immediate.try_into().unwrap()));
            }
        }
        println!();

        let mut rjumpv_additional_immediates = 0;
        if op == RJUMPV {
            let max_index = code[i + 1] as usize;
            let len = max_index + 1;
            // and max_index+1 is to get size of vtable as index starts from 0.
            rjumpv_additional_immediates = len * 2;

            // +1 is for max_index byte
            if i + 1 + rjumpv_additional_immediates >= code.len() {
                println!("Malformed code: immediate out of bounds");
                break;
            }

            for vtablei in 0..len {
                let offset = unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize;
                println!("RJUMPV[{vtablei}]: 0x{offset:04X} ({offset})");
            }
        }

        i += 1 + opcode.immediate_size() as usize + rjumpv_additional_immediates;
    }
}

#[cfg(test)]
mod test {
    use primitives::hex;

    #[test]
    fn sanity_test() {
        super::print(&hex!("6001e200ffff00"));
    }
}