xabc_lib/
method.rs

1use getset::Getters;
2use scroll::Uleb128;
3use tracing::debug;
4
5use crate::error;
6use crate::region::Region;
7use crate::string::ABCString;
8use crate::uint16_t;
9use crate::uint32_t;
10use crate::uint8_t;
11
12use scroll::ctx;
13use scroll::Pread;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16enum MethodAccessFlags {
17    Public = 0x0001,
18    Private = 0x0002,
19    Protected = 0x0004,
20    Static = 0x0008,
21    Final = 0x0010,
22    Synchronized = 0x0020,
23    Bridge = 0x0040,
24    Varargs = 0x0080,
25    Native = 0x0100,
26    Abstract = 0x0400,
27    Strict = 0x0800,
28    Synthetic = 0x1000,
29}
30
31impl MethodAccessFlags {
32    pub fn parse(value: u64) -> Vec<String> {
33        let mut access_flags: Vec<String> = Vec::new();
34
35        let flags = [
36            MethodAccessFlags::Public,
37            MethodAccessFlags::Private,
38            MethodAccessFlags::Protected,
39            MethodAccessFlags::Static,
40            MethodAccessFlags::Final,
41            MethodAccessFlags::Synchronized,
42            MethodAccessFlags::Bridge,
43            MethodAccessFlags::Varargs,
44            MethodAccessFlags::Native,
45            MethodAccessFlags::Abstract,
46            MethodAccessFlags::Strict,
47            MethodAccessFlags::Synthetic,
48        ]
49        .to_vec();
50
51        for flag in flags {
52            let x = flag as u64;
53            if value & x != 0 {
54                access_flags.push(format!("{:?}", flag));
55            }
56        }
57
58        access_flags
59    }
60}
61
62#[derive(Debug, Getters, Default)]
63#[get = "pub"]
64pub struct MethodData {
65    /// 指向方法的 Code 对象的偏移量。
66    code_off: uint32_t,
67    source_lang: uint8_t,
68    runtime_annotation_off: uint32_t,
69    runtime_param_annotation_off: uint32_t,
70    debug_info_off: uint32_t,
71    annotation_off: uint32_t,
72    param_annotation_off: uint32_t,
73    type_annotation_off: uint32_t,
74    runtime_type_annotation_off: uint32_t,
75}
76
77#[derive(Debug, Getters, Default)]
78#[get = "pub"]
79pub struct Method {
80    /// 类的索引
81    class_idx: uint16_t,
82    proto_idx: uint16_t,
83    /// 名字的偏移量,指向一个 String
84    name_off: uint32_t,
85
86    /// 它的值必须是 AccessFlag 的组合。
87    access_flags: Vec<String>,
88    // method_data: Vec,
89    size: usize,
90    method_data: MethodData,
91}
92
93impl Method {}
94
95// TODO: 方法签名还不完整
96pub fn get_method_sign(source: &[u8], offset: usize, region: &Region) -> String {
97    let mut name = String::new();
98    let mut off = offset;
99    let class_idx = source.pread::<uint16_t>(off).unwrap();
100    off += 2;
101    let class_name = region.get_class_name(class_idx as usize).to_string();
102    name += &class_name;
103    name += "->";
104
105    // TODO: 获取方法签名,获取参数
106    let _proto_idx = source.pread::<uint16_t>(off).unwrap();
107    off += 2;
108
109    let name_idx = source.pread::<uint32_t>(off).unwrap();
110    let method_name = source
111        .pread::<ABCString>(name_idx as usize)
112        .unwrap()
113        .to_string();
114
115    name += &method_name;
116
117    name
118}
119
120impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Method {
121    type Error = error::Error;
122    fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
123        let class_idx = source.pread::<uint16_t>(0).unwrap();
124        let proto_idx = source.pread::<uint16_t>(2).unwrap();
125        let name_off = source.pread::<uint32_t>(4).unwrap();
126
127        let off = &mut 8;
128        let access_flags = Uleb128::read(source, off).unwrap();
129        let access_flags = MethodAccessFlags::parse(access_flags);
130
131        // 解析 method_data
132
133        let mut method_data = MethodData::default();
134        // NOTE: 数据保存
135        'l: loop {
136            let tag_value = source.pread::<u8>(*off).unwrap();
137            *off += 1;
138
139            match tag_value {
140                0x00 => {
141                    tracing::debug!("NOTHING");
142                    break 'l;
143                }
144                0x01 => {
145                    let code_off = source.pread::<uint32_t>(*off).unwrap();
146                    *off += 4;
147                    method_data.code_off = code_off;
148                    debug!("CODE {:?}", code_off);
149                }
150                0x02 => {
151                    let data = source.pread::<u8>(*off).unwrap();
152                    *off += 1;
153                    method_data.source_lang = data;
154                    debug!("SOURCE_LANG {:?}", data);
155                }
156                0x03 => {
157                    let data = source.pread::<uint32_t>(*off).unwrap();
158                    *off += 4;
159                    method_data.runtime_annotation_off = data;
160                    debug!("RUNTIME_ANNOTATION {:?}", data);
161                }
162                0x04 => {
163                    let data = source.pread::<uint32_t>(*off).unwrap();
164                    *off += 4;
165                    method_data.runtime_param_annotation_off = data;
166                    debug!("RUNTIME_PARAM_ANNOTATION {:?}", data);
167                }
168                0x05 => {
169                    let data = source.pread::<uint32_t>(*off).unwrap();
170                    *off += 4;
171                    method_data.debug_info_off = data;
172                    debug!("DEBUG_INFO {:?}", data);
173                }
174                0x06 => {
175                    let data = source.pread::<uint32_t>(*off).unwrap();
176                    *off += 4;
177                    method_data.annotation_off = data;
178                    debug!("ANNOTATION {:?}", data);
179                }
180                0x07 => {
181                    let data = source.pread::<uint32_t>(*off).unwrap();
182                    *off += 4;
183                    method_data.param_annotation_off = data;
184                    debug!("PARAM_ANNOTATION {:?}", data);
185                }
186                0x08 => {
187                    let data = source.pread::<uint32_t>(*off).unwrap();
188                    *off += 4;
189                    method_data.type_annotation_off = data;
190                    debug!("TYPE_ANNOTATION {:?}", data);
191                }
192                0x09 => {
193                    let data = source.pread::<uint32_t>(*off).unwrap();
194                    *off += 4;
195                    method_data.runtime_type_annotation_off = data;
196                    debug!("RUNTIME_TYPE_ANNOTATION {:?}", data);
197                }
198                _ => {
199                    // FIXME: 这种情况是不可能出现,一定有问题。
200                    tracing::error!("Method Data: UNKNOWN 0x{:02X}", tag_value);
201                }
202            }
203        }
204
205        let size = *off;
206
207        Ok((
208            Method {
209                class_idx,
210                proto_idx,
211                name_off,
212                access_flags,
213                method_data,
214                size,
215            },
216            source.len(),
217        ))
218    }
219}