xabc_lib/
literal.rs

1use std::collections::HashMap;
2
3use scroll::Pread;
4
5use crate::{method, region::Region, string::ABCString, uint32_t};
6
7// https://gitee.com/openharmony/arkcompiler_runtime_core/blob/master/libpandafile/literal_data_accessor.h#L32
8#[allow(non_camel_case_types)]
9pub enum LiteralTag {
10    TAG_VALUE = 0x00,
11    BOOL = 0x01,
12    // int_8 and tagvalue have the same range for data representation.
13    // INTEGER_8 = TAGVALUE,
14    INTEGER = 0x02,
15    FLOAT = 0x03,
16    DOUBLE = 0x04,
17    STRING = 0x05,
18    METHOD = 0x06,
19    GENERATORMETHOD = 0x07,
20    ACCESSOR = 0x08,
21    METHODAFFILIATE = 0x09,
22    ARRAY_U1 = 0x0a,
23    ARRAY_U8 = 0x0b,
24    ARRAY_I8 = 0x0c,
25    ARRAY_U16 = 0x0d,
26    ARRAY_I16 = 0x0e,
27    ARRAY_U32 = 0x0f,
28    ARRAY_I32 = 0x10,
29    ARRAY_U64 = 0x11,
30    ARRAY_I64 = 0x12,
31    ARRAY_F32 = 0x13,
32    ARRAY_F64 = 0x14,
33    ARRAY_STRING = 0x15,
34    ASYNC_GENERATOR_METHOD = 0x16,
35    LITERAL_BUFFER_INDEX = 0x17,
36    LITERAL_ARRAY = 0x18,
37    BUILTIN_TYPE_INDEX = 0x19,
38    GETTER = 0x1a,
39    SETTER = 0x1b,
40    NULL_VALUE = 0xff,
41    UNKNOWN = 0xee,
42}
43
44impl LiteralTag {
45    pub fn from_u8(value: u8) -> Self {
46        match value {
47            0x00 => LiteralTag::TAG_VALUE,
48            0x01 => LiteralTag::BOOL,
49            0x02 => LiteralTag::INTEGER,
50            0x03 => LiteralTag::FLOAT,
51            0x04 => LiteralTag::DOUBLE,
52            0x05 => LiteralTag::STRING,
53            0x06 => LiteralTag::METHOD,
54            0x07 => LiteralTag::GENERATORMETHOD,
55            0x08 => LiteralTag::ACCESSOR,
56            0x09 => LiteralTag::METHODAFFILIATE,
57            0x0a => LiteralTag::ARRAY_U1,
58            0x0b => LiteralTag::ARRAY_U8,
59            0x0c => LiteralTag::ARRAY_I8,
60            0x0d => LiteralTag::ARRAY_U16,
61            0x0e => LiteralTag::ARRAY_I16,
62            0x0f => LiteralTag::ARRAY_U32,
63            0x10 => LiteralTag::ARRAY_I32,
64            0x11 => LiteralTag::ARRAY_U64,
65            0x12 => LiteralTag::ARRAY_I64,
66            0x13 => LiteralTag::ARRAY_F32,
67            0x14 => LiteralTag::ARRAY_F64,
68            0x15 => LiteralTag::ARRAY_STRING,
69            0x16 => LiteralTag::ASYNC_GENERATOR_METHOD,
70            0x17 => LiteralTag::LITERAL_BUFFER_INDEX,
71            0x18 => LiteralTag::LITERAL_ARRAY,
72            0x19 => LiteralTag::BUILTIN_TYPE_INDEX,
73            0x1a => LiteralTag::GETTER,
74            0x1b => LiteralTag::SETTER,
75            0xff => LiteralTag::NULL_VALUE,
76            _ => LiteralTag::UNKNOWN,
77        }
78    }
79}
80
81// https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-bytecode-file-format-V5#literalarray
82fn parse_literal_array(source: &[u8], offset: usize, region: &Region) -> String {
83    let num_literals = source.pread_with::<uint32_t>(offset, scroll::LE).unwrap();
84
85    let mut off = offset;
86    off += 4;
87
88    let mut result = String::new();
89    let mut counter = 0;
90    loop {
91        if counter >= num_literals {
92            break;
93        }
94
95        counter += 1;
96
97        let tag_value = source.pread::<u8>(off).unwrap();
98        off += 1;
99        match LiteralTag::from_u8(tag_value) {
100            LiteralTag::TAG_VALUE => {
101                tracing::debug!("TaggleValue: Match");
102                off += 1;
103            }
104            LiteralTag::BOOL => {
105                let data = source.pread::<u8>(off).unwrap();
106                off += 1;
107                let s = format!("bool: {}, ", data);
108                result += &s;
109            }
110            LiteralTag::INTEGER => {
111                let data = source.pread::<u32>(off).unwrap();
112                let s = format!("i32: 0x{:X}, ", data);
113                result += &s;
114                off += 4;
115            }
116            LiteralTag::FLOAT => {
117                let data = source.pread_with::<u32>(off, scroll::BE).unwrap();
118                let s = format!("f32: {}, ", f32::from_bits(data));
119                result += &s;
120                off += 4;
121            }
122            LiteralTag::DOUBLE => {
123                let data = source.pread_with::<u64>(off, scroll::BE).unwrap();
124                let s = format!("f64: {}, ", f64::from_bits(data));
125                result += &s;
126
127                off += 8;
128            }
129            LiteralTag::STRING => {
130                let string_off = source.pread::<u32>(off).unwrap();
131                let str = source.pread::<ABCString>(string_off as usize).unwrap();
132                let s = format!("str: \"{}\", ", str.str());
133                result += &s;
134
135                off += 4;
136            }
137            LiteralTag::METHOD => {
138                let method_off = source.pread::<uint32_t>(off).unwrap();
139                let method = method::get_method_sign(source, method_off as usize, region);
140                let s = format!("Method: {}, ", method);
141                result += &s;
142
143                off += 4;
144            }
145            LiteralTag::GENERATORMETHOD => {
146                let _off = source.pread::<uint32_t>(off).unwrap();
147                let s = format!("GeneratorMethod: {}, ", _off);
148                result += &s;
149                off += 4;
150            }
151            LiteralTag::ACCESSOR => {
152                let data = source.pread::<u8>(off).unwrap();
153                let s = format!("Accessor: {}, ", data);
154                result += &s;
155                off += 1;
156            }
157            LiteralTag::METHODAFFILIATE => {
158                let data = source.pread::<u16>(off).unwrap();
159                let s = format!("MethodAffiliate: {}, ", data);
160                result += &s;
161                off += 2;
162            }
163            LiteralTag::ARRAY_U1 => {
164                tracing::debug!("ArrayU1: Match");
165                off += 4;
166            }
167            LiteralTag::ARRAY_U8 => {
168                tracing::debug!("ArrayU8: Match");
169                off += 4;
170            }
171            LiteralTag::ARRAY_I8 => {
172                tracing::debug!("ArrayI8: Match");
173                off += 4;
174            }
175            LiteralTag::ARRAY_U16 => {
176                tracing::debug!("ArrayU16: Match");
177                off += 4;
178            }
179            LiteralTag::ARRAY_I16 => {
180                tracing::debug!("ArrayI16: Match");
181                off += 4;
182            }
183            LiteralTag::ARRAY_U32 => {
184                tracing::debug!("ArrayU32: Match");
185                off += 4;
186            }
187            LiteralTag::ARRAY_I32 => {
188                tracing::debug!("ArrayI32: Match");
189                off += 4;
190            }
191            LiteralTag::ARRAY_U64 => {
192                tracing::debug!("ArrayU64: Match");
193                off += 4;
194            }
195            LiteralTag::ARRAY_I64 => {
196                tracing::debug!("Match ArrayI64");
197                off += 4;
198            }
199            LiteralTag::ARRAY_F32 => {
200                tracing::debug!("Match ArrayF32");
201                off += 4;
202            }
203            LiteralTag::ARRAY_F64 => {
204                tracing::debug!("ArrayF64: {}", tag_value);
205                off += 8;
206            }
207            LiteralTag::ARRAY_STRING => {
208                // TODO: 一个字符串数组
209                tracing::debug!("ArrayString: {}", tag_value);
210                off += 4;
211            }
212            LiteralTag::ASYNC_GENERATOR_METHOD => {
213                tracing::debug!("ArrayGeneratorMethod: {}", tag_value);
214                off += 4;
215            }
216            LiteralTag::LITERAL_BUFFER_INDEX => {
217                tracing::debug!("LiteralBufferIndex: {}", tag_value);
218                off += 4;
219            }
220            LiteralTag::LITERAL_ARRAY => {
221                tracing::debug!("LiteralArr: {}", tag_value);
222                off += 4;
223            }
224            LiteralTag::BUILTIN_TYPE_INDEX => {
225                tracing::debug!("BuiltinTypeIndex: {}", tag_value);
226                off += 1;
227            }
228            LiteralTag::GETTER => {
229                let data = source.pread::<uint32_t>(off).unwrap();
230                let s = format!("Getter: 0x{:X}, ", data);
231                result += &s;
232                off += 4;
233            }
234            LiteralTag::SETTER => {
235                tracing::debug!("Setter: {}", tag_value);
236                off += 4;
237            }
238            LiteralTag::NULL_VALUE => {
239                tracing::debug!("NullValue: {}", tag_value);
240                off += 1;
241            }
242            LiteralTag::UNKNOWN => {
243                tracing::warn!("未知的Tag: 0x{:X}", tag_value);
244                break;
245            }
246        }
247    }
248
249    result
250}
251
252pub fn parse_literal_array_index(
253    source: &[u8],
254    offset: uint32_t,
255    num_literals: uint32_t,
256    regions: &[Region],
257) -> HashMap<usize, String> {
258    let mut off = offset as usize;
259    let mut literal_array_map: HashMap<usize, String> = HashMap::new();
260
261    for _ in 0..num_literals {
262        let array_off = source.pread::<uint32_t>(off).unwrap();
263        off += 4;
264
265        let mut region: Option<&Region> = None;
266        for item in regions.iter() {
267            if item.is_here(array_off as usize) {
268                region = Some(item);
269                break;
270            }
271        }
272
273        if region.is_none() {
274            tracing::warn!("region not found");
275            continue;
276        }
277
278        let region = region.unwrap();
279        let literal = parse_literal_array(source, array_off as usize, region);
280        literal_array_map.insert(array_off as usize, literal);
281    }
282
283    literal_array_map
284}