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 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 const DBG_FIRST_SPECIAL: u8 = 0x0a;
65 const DBG_LINE_BASE: i8 = -4;
67 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(®_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(®_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); local_var_map.insert(reg_num, new_var); }
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 { u8::read_from(context)? as u16
239 } else { 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 { u8::read_from(context)? as u32
248 } else if value_arg == 1 { u16::read_from(context)? as u32
250 } else if value_arg == 2 { U24::read_from(context)?.0
252 } else { 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 { u8::read_from(context)? as u64
266 } else if value_arg == 1 { u16::read_from(context)? as u64
268 } else if value_arg == 2 { U24::read_from(context)?.0 as u64
270 } else if value_arg == 3 { u32::read_from(context)? as u64
272 } else if value_arg == 4 { U40::read_from(context)?.0
274 } else if value_arg == 5 { U48::read_from(context)?.0
276 } else if value_arg == 6 { U56::read_from(context)?.0
278 } else { 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 { i8::read_from(context)? as i16
287 } else { 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 { i8::read_from(context)? as i32
296 } else if value_arg == 1 { i16::read_from(context)? as i32
298 } else if value_arg == 2 { I24::read_from(context)?.0
300 } else { 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 { i8::read_from(context)? as i64
309 } else if value_arg == 1 { i16::read_from(context)? as i64
311 } else if value_arg == 2 { I24::read_from(context)?.0 as i64
313 } else if value_arg == 3 { i32::read_from(context)? as i64
315 } else if value_arg == 4 { I40::read_from(context)?.0
317 } else if value_arg == 5 { I48::read_from(context)?.0
319 } else if value_arg == 6 { I56::read_from(context)?.0
321 } else { 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}