java_asm/impls/dex/r/
raw.rs

1use crate::dex::{CodeItem, DSleb128, DUByte, DUInt, DULeb128, DULeb128P1, DebugInfoItem, DexFile, EncodedCatchHandler, EncodedValue, EncodedValueType, Header, InsnContainer, LocalVar, StringData};
2use crate::err::AsmResultOkExt;
3use crate::impls::jvms::r::*;
4use crate::{mutf8_to_string, AsmErr, AsmResult};
5use std::collections::HashMap;
6
7impl ReadFrom for CodeItem {
8    fn read_from(context: &mut ReadContext) -> AsmResult<Self> {
9        context.align(4);
10        let registers_size = context.read()?;
11        let ins_size = context.read()?;
12        let outs_size = context.read()?;
13        let tries_size = context.read()?;
14        let debug_info_off = context.read()?;
15        let insn_container = context.read()?;
16        let tries;
17        let handlers;
18        if tries_size > 0 {
19            // padding to makes `tries` is 4-byte aligned
20            context.align(4);
21            tries = context.read_vec(tries_size)?;
22            handlers = context.read()?;
23        } else {
24            handlers = Default::default();
25            tries = Vec::new();
26        }
27        CodeItem {
28            registers_size, ins_size, outs_size, tries_size,
29            debug_info_off, insn_container, tries, handlers,
30        }.ok()
31    }
32}
33
34impl ReadFrom for InsnContainer {
35    fn read_from(context: &mut ReadContext) -> AsmResult<Self> {
36        let insns_size: DUInt = context.read()?;
37        let mut insns = Vec::new();
38        let len_of_insns = (insns_size * 2) as usize;
39        let mut cur = 0usize;
40        while cur < len_of_insns {
41            let start = context.index;
42            let insn = context.read()?;
43            insns.push(insn);
44            let end = context.index;
45            cur += end - start;
46        }
47        Ok(InsnContainer { insns_size, insns })
48    }
49}
50
51impl DebugInfoItem {
52    const DBG_END_SEQUENCE: u8 = 0x00;
53    const DBG_ADVANCE_PC: u8 = 0x01;
54    const DBG_ADVANCE_LINE: u8 = 0x02;
55    const DBG_START_LOCAL: u8 = 0x03;
56    const DBG_START_LOCAL_EXTENDED: u8 = 0x04;
57    const DBG_END_LOCAL: u8 = 0x05;
58    const DBG_RESTART_LOCAL: u8 = 0x06;
59    const DBG_SET_PROLOGUE_END: u8 = 0x07;
60    const DBG_SET_EPILOGUE_BEGIN: u8 = 0x08;
61    const DBG_SET_FILE: u8 = 0x09;
62
63    // the smallest special opcode
64    const DBG_FIRST_SPECIAL: u8 = 0x0a;
65    // the smallest line number increment
66    const DBG_LINE_BASE: i8 = -4;
67    // the number of line increments represented
68    const DBG_LINE_RANGE: u8 = 15;
69}
70
71impl ReadFrom for DebugInfoItem {
72    fn read_from(context: &mut ReadContext) -> AsmResult<Self> {
73        let line_start: DULeb128 = context.read()?;
74        let parameters_size: DULeb128 = context.read()?;
75        let parameter_names: Vec<DULeb128P1> = context.read_vec(parameters_size)?;
76        let mut records = Vec::new();
77        let mut local_vars: Vec<LocalVar> = Vec::new();
78        let mut local_var_map: HashMap<DULeb128, LocalVar> = HashMap::new();
79
80        let mut cur_line = line_start.value();
81        let mut cur_addr = 0;
82        let mut cur_source: DULeb128P1 = DULeb128P1::ZERO;
83        loop {
84            let opcode: u8 = context.read()?;
85            match opcode {
86                DebugInfoItem::DBG_END_SEQUENCE => break,
87
88                DebugInfoItem::DBG_ADVANCE_PC => {
89                    let addr_diff: DULeb128 = context.read()?;
90                    cur_addr += addr_diff.value();
91                }
92                DebugInfoItem::DBG_ADVANCE_LINE => {
93                    let line_diff: DSleb128 = context.read()?;
94                    cur_line = (cur_line as i32 + line_diff.value()) as u32;
95                }
96                DebugInfoItem::DBG_START_LOCAL => {
97                    let register: DULeb128 = context.read()?;
98                    let name_idx: DULeb128P1 = context.read()?;
99                    let type_idx: DULeb128P1 = context.read()?;
100                    let sig_idx = DULeb128P1::ZERO;
101                    let start_addr = Some(cur_addr);
102                    let end_addr = None;
103                    let local_var = LocalVar { register, name_idx, type_idx, sig_idx, start_addr, end_addr };
104                    local_var_map.insert(register, local_var);
105                }
106                DebugInfoItem::DBG_START_LOCAL_EXTENDED => {
107                    let register: DULeb128 = context.read()?;
108                    let name_idx: DULeb128P1 = context.read()?;
109                    let type_idx: DULeb128P1 = context.read()?;
110                    let sig_idx: DULeb128P1 = context.read()?;
111                    let start_addr = Some(cur_addr);
112                    let end_addr = None;
113                    let local_var = LocalVar { register, name_idx, type_idx, sig_idx, start_addr, end_addr };
114                    local_var_map.insert(register, local_var);
115                }
116                DebugInfoItem::DBG_END_LOCAL => {
117                    let reg_num: DULeb128 = context.read()?;
118                    if let Some(mut local_var) = local_var_map.remove(&reg_num) {
119                        local_var.end_addr = Some(cur_addr);
120                        local_vars.push(local_var);
121                    }
122                }
123                DebugInfoItem::DBG_RESTART_LOCAL => {
124                    let reg_num: DULeb128 = context.read()?;
125                    if let Some(mut old_var) = local_var_map.remove(&reg_num) {
126                        old_var.end_addr = Some(cur_addr);
127                        let mut new_var = old_var.clone();
128                        new_var.start_addr = Some(cur_addr);
129                        local_vars.push(old_var); // push old one
130                        local_var_map.insert(reg_num, new_var); // insert new one
131                    }
132                }
133                DebugInfoItem::DBG_SET_PROLOGUE_END | DebugInfoItem::DBG_SET_EPILOGUE_BEGIN => continue,
134                DebugInfoItem::DBG_SET_FILE => cur_source = context.read()?,
135                _ => {
136                    let adjusted_opcode = opcode - DebugInfoItem::DBG_FIRST_SPECIAL;
137                    let line_diff = DebugInfoItem::DBG_LINE_BASE as i16 + (adjusted_opcode % DebugInfoItem::DBG_LINE_RANGE) as i16;
138                    let addr_diff = adjusted_opcode / DebugInfoItem::DBG_LINE_RANGE;
139                    cur_line = (cur_line as i32 + line_diff as i32) as u32;
140                    cur_addr += addr_diff as u32;
141                    records.push((cur_addr, cur_line, cur_source));
142                }
143            }
144        }
145        
146        if !local_var_map.is_empty() {
147            local_vars.extend(local_var_map.into_values());
148        }
149
150        DebugInfoItem { line_start, parameter_names, records, local_vars }.ok()
151    }
152}
153
154impl ReadFrom for EncodedCatchHandler {
155    fn read_from(context: &mut ReadContext) -> AsmResult<Self> {
156        let size: DSleb128 = context.read()?;
157        let size_value = size.value();
158        let handler_size = size_value.abs() as usize;
159        let handlers = context.read_vec(handler_size)?;
160        let catch_all_addr = if size_value < 0 {
161            Some(context.read()?)
162        } else {
163            None
164        };
165        Ok(EncodedCatchHandler { size, handlers, catch_all_addr })
166    }
167}
168
169impl DexFile {
170    pub(crate) fn read_from(context: &mut ReadContext) -> AsmResult<Self> {
171        let header: Header = context.read()?;
172        let string_ids = context.read_vec(header.string_ids_size)?;
173        let type_ids = context.read_vec(header.type_ids_size)?;
174        let proto_ids = context.read_vec(header.proto_ids_size)?;
175        let field_ids = context.read_vec(header.field_ids_size)?;
176        let method_ids = context.read_vec(header.method_ids_size)?;
177        let class_defs = context.read_vec(header.class_defs_size)?;
178        DexFile {
179            header,
180            string_ids, type_ids, proto_ids, field_ids, method_ids,
181            class_defs,
182        }.ok()
183    }
184}
185
186impl ReadFrom for EncodedValue {
187    fn read_from(context: &mut ReadContext) -> AsmResult<Self> {
188        let header_byte: u8 = context.read()?;
189        let value_arg = header_byte & 0x1F;
190        let value_type = header_byte & 0xE0;
191        let encoded_value = match value_type {
192            EncodedValueType::VALUE_BYTE =>
193                EncodedValue::Byte(context.read()?),
194            EncodedValueType::VALUE_SHORT =>
195                EncodedValue::Short(read_i16(context, value_arg)?),
196            EncodedValueType::VALUE_CHAR =>
197                EncodedValue::Char(read_u16(context, value_arg)?),
198            EncodedValueType::VALUE_INT =>
199                EncodedValue::Int(read_i32(context, value_arg)?),
200            EncodedValueType::VALUE_LONG =>
201                EncodedValue::Long(read_i64(context, value_arg)?),
202            EncodedValueType::VALUE_FLOAT =>
203                EncodedValue::Float(read_f32(context, value_arg)?),
204            EncodedValueType::VALUE_DOUBLE =>
205                EncodedValue::Double(read_f64(context, value_arg)?),
206            EncodedValueType::VALUE_METHOD_TYPE =>
207                EncodedValue::MethodType(read_u32_based_size(context, value_arg)?),
208            EncodedValueType::VALUE_METHOD_HANDLE =>
209                EncodedValue::MethodHandle(read_u32_based_size(context, value_arg)?),
210            EncodedValueType::VALUE_STRING =>
211                EncodedValue::String(read_u32_based_size(context, value_arg)?),
212            EncodedValueType::VALUE_TYPE =>
213                EncodedValue::Type(read_u32_based_size(context, value_arg)?),
214            EncodedValueType::VALUE_FIELD =>
215                EncodedValue::Field(read_u32_based_size(context, value_arg)?),
216            EncodedValueType::VALUE_METHOD =>
217                EncodedValue::Method(read_u32_based_size(context, value_arg)?),
218            EncodedValueType::VALUE_ENUM =>
219                EncodedValue::Enum(read_u32_based_size(context, value_arg)?),
220            EncodedValueType::VALUE_ARRAY =>
221                EncodedValue::Array(context.read()?),
222            EncodedValueType::VALUE_ANNOTATION =>
223                EncodedValue::Annotation(context.read()?),
224            EncodedValueType::VALUE_NULL =>
225                EncodedValue::Null,
226            EncodedValueType::VALUE_BOOLEAN =>
227                EncodedValue::Boolean(value_arg != 0),
228            _ => return AsmErr::IllegalFormat(
229                format!("Unknown encoded value type: {:#X} at offset {:#X} of dex file.", value_type, context.index)
230            ).e(),
231        };
232        Ok(encoded_value)
233    }
234}
235
236fn read_u16(context: &mut ReadContext, value_arg: u8) -> AsmResult<u16> {
237    let value = if value_arg == 0 { // 1 byte
238        u8::read_from(context)? as u16
239    } else { // 2 bytes
240        u16::read_from(context)?
241    };
242    Ok(value)
243}
244
245fn read_u32(context: &mut ReadContext, value_arg: u8) -> AsmResult<u32> {
246    let value = if value_arg == 0 { // 1 byte
247        u8::read_from(context)? as u32
248    } else if value_arg == 1 { // 2 bytes
249        u16::read_from(context)? as u32
250    } else if value_arg == 2 { // 3 bytes
251        U24::read_from(context)?.0
252    } else { // 4 bytes
253        u32::read_from(context)?
254    };
255    Ok(value)
256}
257
258fn read_u32_based_size(context: &mut ReadContext, value_arg: u8) -> AsmResult<U32BasedSize> {
259    let value = U32BasedSize(read_u32(context, value_arg)?);
260    Ok(value)
261}
262
263fn read_u64(context: &mut ReadContext, value_arg: u8) -> AsmResult<u64> {
264    let value = if value_arg == 0 { // 1 byte
265        u8::read_from(context)? as u64
266    } else if value_arg == 1 { // 2 bytes
267        u16::read_from(context)? as u64
268    } else if value_arg == 2 { // 3 bytes
269        U24::read_from(context)?.0 as u64
270    } else if value_arg == 3 { // 4 bytes
271        u32::read_from(context)? as u64
272    } else if value_arg == 4 { // 5 bytes
273        U40::read_from(context)?.0
274    } else if value_arg == 5 { // 6 bytes
275        U48::read_from(context)?.0
276    } else if value_arg == 6 { // 7 bytes
277        U56::read_from(context)?.0
278    } else { // 8 bytes
279        u64::read_from(context)?
280    };
281    Ok(value)
282}
283
284fn read_i16(context: &mut ReadContext, value_arg: u8) -> AsmResult<i16> {
285    let value = if value_arg == 0 { // 1 byte
286        i8::read_from(context)? as i16
287    } else { // 2 bytes
288        i16::read_from(context)?
289    };
290    Ok(value)
291}
292
293fn read_i32(context: &mut ReadContext, value_arg: u8) -> AsmResult<i32> {
294    let value = if value_arg == 0 { // 1 byte
295        i8::read_from(context)? as i32
296    } else if value_arg == 1 { // 2 bytes
297        i16::read_from(context)? as i32
298    } else if value_arg == 2 { // 3 bytes
299        I24::read_from(context)?.0
300    } else { // 4 bytes
301        i32::read_from(context)?
302    };
303    Ok(value)
304}
305
306fn read_i64(context: &mut ReadContext, value_arg: u8) -> AsmResult<i64> {
307    let value = if value_arg == 0 { // 1 byte
308        i8::read_from(context)? as i64
309    } else if value_arg == 1 { // 2 bytes
310        i16::read_from(context)? as i64
311    } else if value_arg == 2 { // 3 bytes
312        I24::read_from(context)?.0 as i64
313    } else if value_arg == 3 { // 4 bytes
314        i32::read_from(context)? as i64
315    } else if value_arg == 4 { // 5 bytes
316        I40::read_from(context)?.0
317    } else if value_arg == 5 { // 6 bytes
318        I48::read_from(context)?.0
319    } else if value_arg == 6 { // 7 bytes
320        I56::read_from(context)?.0
321    } else { // 8 bytes
322        i64::read_from(context)?
323    };
324    Ok(value)
325}
326
327fn read_f32(context: &mut ReadContext, value_arg: u8) -> AsmResult<[DUByte; 4]> {
328    let mut res = [0u8; 4];
329    res[0] = context.read()?;
330    if value_arg > 0 {
331        res[1] = context.read()?;
332    }
333    if value_arg > 1 {
334        res[2] = context.read()?;
335    }
336    if value_arg > 2 {
337        res[3] = context.read()?;
338    }
339    Ok(res)
340}
341
342fn read_f64(context: &mut ReadContext, value_arg: u8) -> AsmResult<[DUByte; 8]> {
343    let mut res = [0u8; 8];
344    res[0] = context.read()?;
345    if value_arg > 0 {
346        res[1] = context.read()?;
347    }
348    if value_arg > 1 {
349        res[2] = context.read()?;
350    }
351    if value_arg > 2 {
352        res[3] = context.read()?;
353    }
354    if value_arg > 3 {
355        res[4] = context.read()?;
356    }
357    if value_arg > 4 {
358        res[5] = context.read()?;
359    }
360    if value_arg > 5 {
361        res[6] = context.read()?;
362    }
363    if value_arg > 6 {
364        res[7] = context.read()?;
365    }
366    Ok(res)
367}
368
369
370impl ReadFrom for StringData {
371    fn read_from(context: &mut ReadContext) -> AsmResult<Self> {
372        let utf16_size: DULeb128 = context.read()?;
373        let mut vec = Vec::new();
374        loop {
375            let current: u8 = context.read()?;
376            if current == 0 { break; }
377            vec.push(current);
378        }
379        let str_ref = mutf8_to_string(&vec)?;
380        Ok(StringData { utf16_size, str_ref })
381    }
382}