integrate properly debug info serialization

This commit is contained in:
Jean-Marie Mineau 2025-01-14 11:25:07 +01:00
parent 652bab50f7
commit 5899c8d160
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2

View file

@ -436,6 +436,25 @@ impl DexWriter {
let mut max_addr = 0; let mut max_addr = 0;
let mut label_min_max_addrs: HashMap<String, (usize, usize)> = HashMap::new(); let mut label_min_max_addrs: HashMap<String, (usize, usize)> = HashMap::new();
let parameter_names = if let Some(parameter_names) = code.parameter_names {
let mut parameter_names_idxs = vec![];
for name in &parameter_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 { for ins in &code.insns {
match ins { match ins {
Instruction::Label { name } => { Instruction::Label { name } => {
@ -701,6 +720,91 @@ impl DexWriter {
encoded_handlers.list.push(catches); encoded_handlers.list.push(catches);
} }
Instruction::Label { .. } => (), 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 let ins = ins
.get_raw_ins(GetRawInsParam { .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 { if addr % 2 != 0 {
// make sure the payload section is 4 bytes aligned // make sure the payload section is 4 bytes aligned
let nop = (Instruction::Nop {}).get_raw_ins(GetRawInsParam::default())?; 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; 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::<DbgBytecode>::deserialize(&mut cursor, DbgBytecode::EndSequence)?,
};
if let Some(parameter_names) = code.parameter_names {
for name in &parameter_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() { let handlers = if encoded_handlers.list.is_empty() {
None None
} else { } else {