diff --git a/objdiff-core/src/diff/code.rs b/objdiff-core/src/diff/code.rs index 6dc48d7..3d3273a 100644 --- a/objdiff-core/src/diff/code.rs +++ b/objdiff-core/src/diff/code.rs @@ -299,15 +299,10 @@ fn compare_ins( ) -> Result { let mut result = InsDiffResult::default(); if let (Some(left_ins), Some(right_ins)) = (&left.ins, &right.ins) { - if left_ins.args.len() != right_ins.args.len() - || left_ins.op != right_ins.op - // Check if any PlainText segments differ (punctuation and spacing) - // This indicates a more significant difference than a simple arg mismatch - || !left_ins.args.iter().zip(&right_ins.args).all(|(a, b)| match (a, b) { - (ObjInsArg::PlainText(l), ObjInsArg::PlainText(r)) => l == r, - _ => true, - }) - { + // Count only non-PlainText args + let left_args_count = left_ins.iter_args().count(); + let right_args_count = right_ins.iter_args().count(); + if left_args_count != right_args_count || left_ins.op != right_ins.op { // Totally different op result.kind = ObjInsDiffKind::Replace; state.diff_count += 1; @@ -318,7 +313,7 @@ fn compare_ins( result.kind = ObjInsDiffKind::OpMismatch; state.diff_count += 1; } - for (a, b) in left_ins.args.iter().zip(&right_ins.args) { + for (a, b) in left_ins.iter_args().zip(right_ins.iter_args()) { if arg_eq(config, left_obj, right_obj, a, b, left, right) { result.left_args_diff.push(None); result.right_args_diff.push(None); diff --git a/objdiff-core/src/diff/display.rs b/objdiff-core/src/diff/display.rs index bc0d080..45fdca8 100644 --- a/objdiff-core/src/diff/display.rs +++ b/objdiff-core/src/diff/display.rs @@ -58,20 +58,23 @@ pub fn display_diff( cb(DiffText::Spacing(4))?; } cb(DiffText::Opcode(&ins.mnemonic, ins.op))?; + let mut arg_diff_idx = 0; // non-PlainText index for (i, arg) in ins.args.iter().enumerate() { if i == 0 { cb(DiffText::Spacing(1))?; } - let diff = ins_diff.arg_diff.get(i).and_then(|o| o.as_ref()); + let diff = ins_diff.arg_diff.get(arg_diff_idx).and_then(|o| o.as_ref()); match arg { ObjInsArg::PlainText(s) => { cb(DiffText::Basic(s))?; } ObjInsArg::Arg(v) => { cb(DiffText::Argument(v, diff))?; + arg_diff_idx += 1; } ObjInsArg::Reloc => { display_reloc_name(ins.reloc.as_ref().unwrap(), &mut cb, diff)?; + arg_diff_idx += 1; } ObjInsArg::BranchDest(dest) => { if let Some(dest) = dest.checked_sub(base_addr) { @@ -79,6 +82,7 @@ pub fn display_diff( } else { cb(DiffText::Basic(""))?; } + arg_diff_idx += 1; } } } diff --git a/objdiff-core/src/diff/mod.rs b/objdiff-core/src/diff/mod.rs index 6443caa..5a17e90 100644 --- a/objdiff-core/src/diff/mod.rs +++ b/objdiff-core/src/diff/mod.rs @@ -245,7 +245,7 @@ pub struct ObjInsDiff { pub branch_from: Option, /// Branches to instruction pub branch_to: Option, - /// Arg diffs + /// Arg diffs (only contains non-PlainText args) pub arg_diff: Vec>, } diff --git a/objdiff-core/src/obj/mod.rs b/objdiff-core/src/obj/mod.rs index 48ce9b5..50e135a 100644 --- a/objdiff-core/src/obj/mod.rs +++ b/objdiff-core/src/obj/mod.rs @@ -85,6 +85,9 @@ pub enum ObjInsArg { } impl ObjInsArg { + #[inline] + pub fn is_plain_text(&self) -> bool { matches!(self, ObjInsArg::PlainText(_)) } + pub fn loose_eq(&self, other: &ObjInsArg) -> bool { match (self, other) { (ObjInsArg::Arg(a), ObjInsArg::Arg(b)) => a.loose_eq(b), @@ -112,6 +115,14 @@ pub struct ObjIns { pub orig: Option, } +impl ObjIns { + /// Iterate over non-PlainText arguments. + #[inline] + pub fn iter_args(&self) -> impl DoubleEndedIterator { + self.args.iter().filter(|a| !a.is_plain_text()) + } +} + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)] pub enum ObjSymbolKind { #[default]