From 5899c8d1604110ef2ded40db072ee42681d0ee0f Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Tue, 14 Jan 2025 11:25:07 +0100 Subject: [PATCH] integrate properly debug info serialization --- androscalpel/src/dex_writer.rs | 147 ++++++++++++++++++++++++++------- 1 file changed, 116 insertions(+), 31 deletions(-) diff --git a/androscalpel/src/dex_writer.rs b/androscalpel/src/dex_writer.rs index d44b479..41aea38 100644 --- a/androscalpel/src/dex_writer.rs +++ b/androscalpel/src/dex_writer.rs @@ -436,6 +436,25 @@ impl DexWriter { let mut max_addr = 0; let mut label_min_max_addrs: HashMap = HashMap::new(); + let parameter_names = if let Some(parameter_names) = code.parameter_names { + let mut parameter_names_idxs = vec![]; + for name in ¶meter_names { + if let Some(name) = name { + parameter_names_idxs.push(Uleb128p1(*self.strings.get(name).ok_or(anyhow!( + "String {} (name of param of {}) not found", + name.__str__(), + method_id.__repr__() + ))? as u32)); + } else { + parameter_names_idxs.push(NO_INDEX); + } + } + parameter_names_idxs + } else { + vec![NO_INDEX; method_id.proto.parameters.len()] + }; + let mut debug_builder = DebugInfoBuilder::new(parameter_names); + for ins in &code.insns { match ins { Instruction::Label { name } => { @@ -701,6 +720,91 @@ impl DexWriter { encoded_handlers.list.push(catches); } Instruction::Label { .. } => (), + Instruction::DebugLocal { + reg, + name, + type_, + signature, + } => { + debug_builder + .add_info(&DebugInfo::DefLocal { + addr: addr as u32, + reg: *reg, + val: DebugRegState { + type_idx: type_ + .map(|ty| { + self.type_ids.get(&ty).ok_or(anyhow!( + "Could not found type {} of local variable {} in debug info of {} \ + in the dex builder", + ty.__repr__(), + name.unwrap_or(String::new()), + method_id.__repr__() + )) + }) + .transpose()? + .map(|idx| *idx as u32), + name_idx: name + .map(|name| { + self.strings.get(&name.into()).ok_or(anyhow!( + "Could not found string '{}' (name of local variable in debug info of {}) \ + in the dex builder", + name, + method_id.__repr__() + )) + }) + .transpose()? + .map(|idx| *idx as u32), + sig_idx: signature + .map(|sig| { + self.strings.get(&sig.into()).ok_or(anyhow!( + "Could not found string '{}' (signature of local variable {} in debug info of {}) \ + in the dex builder", + sig, + name.unwrap_or(String::new()), + method_id.__repr__() + )) + }) + .transpose()? + .map(|idx| *idx as u32), + in_scope: true, + }, + }) + .context("Failled to serialize DebugLocal information")?; + } + Instruction::DebugEndLocal { reg } => debug_builder + .add_info(&DebugInfo::EndLocal { + addr: addr as u32, + reg: *reg, + }) + .context("Failled to serialize DebugEndLocal information")?, + Instruction::DebugEndPrologue {} => debug_builder + .add_info(&DebugInfo::PrologueEnd { addr: addr as u32 }) + .context("Failled to serialize DebugEndPrologue information")?, + Instruction::DebugBeginEpilogue {} => debug_builder + .add_info(&DebugInfo::EpilogueBegin { addr: addr as u32 }) + .context("Failled to serialize DebugBeginEpilogue information")?, + Instruction::DebugSourceFile { file } => debug_builder + .add_info(&DebugInfo::SetSourceFile { + addr: addr as u32, + source_file_idx: file + .map(|file| { + self.strings.get(&file.into()).ok_or(anyhow!( + "Could not found string '{}' (name of the source file of part of {}) \ + in the dex builder", + file, + method_id.__repr__() + )) + }) + .transpose()? + .map(|idx| *idx as u32), + }) + .context("Failled to serialize DebugSourceFile information")?, + Instruction::DebugLine { number } => debug_builder + .add_info(&DebugInfo::SetLineNumber { + addr: addr as u32, + line_num: *number as u32, + }) + .context("Failled to serialize DebugLine information")?, _ => { let ins = ins .get_raw_ins(GetRawInsParam { @@ -724,6 +828,18 @@ impl DexWriter { } } } + + let debug_info_off = if let Some(debug_info) = debug_builder.build() { + let debug_info_off = self + .section_manager + .get_aligned_size(Section::DebugInfoItem); + self.section_manager + .add_elt(Section::DebugInfoItem, Some(debug_info.size())); + self.debug_info_items.push(debug_info); + debug_info_off + 1 + } else { + 0 + }; if addr % 2 != 0 { // make sure the payload section is 4 bytes aligned let nop = (Instruction::Nop {}).get_raw_ins(GetRawInsParam::default())?; @@ -736,37 +852,6 @@ impl DexWriter { try_.handler_off += encoded_handlers.size_field().size() as u16; } - let debug_info_off = if code.debug_info.1.is_empty() && code.parameter_names.is_none() { - 0 - } else { - let debug_info_off = self - .section_manager - .get_aligned_size(Section::DebugInfoItem); - let mut cursor = Cursor::new(code.debug_info.1); - let mut item = DebugInfoItem { - line_start: Uleb128(code.debug_info.0), - parameter_names: vec![], - bytecode: Vec::::deserialize(&mut cursor, DbgBytecode::EndSequence)?, - }; - if let Some(parameter_names) = code.parameter_names { - for name in ¶meter_names { - if let Some(name) = name { - item.parameter_names - .push(Uleb128p1(*self.strings.get(name).ok_or(anyhow!( - "String {} (name of param of {}) not found", - name.__str__(), - method_id.__repr__() - ))? as u32)); - } else { - item.parameter_names.push(NO_INDEX); - } - } - } - self.section_manager - .add_elt(Section::DebugInfoItem, Some(item.size())); - self.debug_info_items.push(item); - debug_info_off + 1 - }; let handlers = if encoded_handlers.list.is_empty() { None } else {