xabc_lib/
code.rs

1use getset::Getters;
2use scroll::{ctx, Uleb128};
3
4use crate::error;
5
6// TODO: 解析 `TryBlock`
7#[allow(dead_code)]
8#[derive(Debug, Getters, Default)]
9#[get = "pub"]
10struct TryBlock {
11    /// TryBlock的第一条指令距离其所在Code的instructions的起始位置的偏移量。
12    start_pc: u64,
13    /// TryBlock的大小,以字节为单位。
14    length: u64,
15    /// 与TryBlock关联的CatchBlock的数量,值为1。
16    num_catches: u64,
17    /// 与TryBlock关联的CatchBlock的数组,数组中有且仅有一个可以捕获所有类型的异常的CatchBlock。
18    catch_blocks: Vec<(CatchBlock, usize)>,
19}
20
21impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for TryBlock {
22    type Error = error::Error;
23    fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
24        let off = &mut 0;
25        let start_pc = Uleb128::read(source, off).unwrap();
26        let length = Uleb128::read(source, off).unwrap();
27        let num_catches = Uleb128::read(source, off).unwrap();
28
29        let catch_blocks = (0..num_catches)
30            .map(|_| CatchBlock::try_from_ctx(source, scroll::Endian::Little))
31            .collect::<Result<Vec<_>, _>>()?;
32
33        Ok((
34            TryBlock {
35                start_pc,
36                length,
37                num_catches,
38                catch_blocks,
39            },
40            source.len(),
41        ))
42    }
43}
44
45// TODO: 解析 `CatchBlock`
46#[allow(dead_code)]
47#[derive(Debug, Getters, Default)]
48#[get = "pub"]
49struct CatchBlock {
50    /// 值是0,表示此CatchBlock块捕获了所有类型的异常。
51    type_idx: u64,
52    /// 异常处理逻辑的第一条指令的程序计数器。
53    handler_pc: u64,
54    /// 此CatchBlock的大小,以字节为单位。
55    catch_type: u64,
56}
57
58impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for CatchBlock {
59    type Error = error::Error;
60    fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
61        let off = &mut 0;
62        let type_idx = Uleb128::read(source, off).unwrap();
63        let handler_pc = Uleb128::read(source, off).unwrap();
64        let catch_type = Uleb128::read(source, off).unwrap();
65
66        Ok((
67            CatchBlock {
68                type_idx,
69                handler_pc,
70                catch_type,
71            },
72            source.len(),
73        ))
74    }
75}
76
77#[derive(Debug, Getters, Default)]
78#[get = "pub"]
79pub struct Code {
80    /// 寄存器的数量,存放入参和默认参数的寄存器不计算在内。
81    num_regs: u64,
82    /// 入参和默认参数的总数量。
83    num_args: u64,
84    /// 所有指令的总大小,以字节为单位。
85    code_size: u64,
86    /// try_blocks数组的长度,即TryBlock的数量。
87    tries_size: u64,
88    /// 所有指令的数组。
89    instructions: Vec<u8>,
90    /// 一个数组,数组中每一个元素都是TryBlock类型。
91    try_blocks: Vec<(TryBlock, usize)>,
92}
93
94impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Code {
95    type Error = error::Error;
96    fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
97        let off = &mut 0;
98
99        let num_regs = Uleb128::read(source, off).unwrap();
100        let num_args = Uleb128::read(source, off).unwrap();
101        let code_size = Uleb128::read(source, off).unwrap();
102        let tries_size = Uleb128::read(source, off).unwrap();
103
104        tracing::debug!(
105            "num_regs: {}, num_args: {}, code_size: {}, tries_size: {}",
106            num_regs,
107            num_args,
108            code_size,
109            tries_size
110        );
111
112        let instructions = source[*off..*off + code_size as usize].to_vec();
113        *off += code_size as usize;
114
115        let try_blocks = (0..tries_size)
116            .map(|_| TryBlock::try_from_ctx(source, scroll::Endian::Little))
117            .collect::<Result<Vec<_>, _>>()?;
118
119        Ok((
120            Code {
121                num_regs,
122                num_args,
123                code_size,
124                tries_size,
125                instructions,
126                try_blocks,
127            },
128            source.len(),
129        ))
130    }
131}