(
left_obj: &Object,
right_obj: &Object,
left_symbol_idx: usize,
right_symbol_idx: usize,
l: Option<InstructionRef>,
r: Option<InstructionRef>,
left_row: &InstructionDiffRo
| 417 | } |
| 418 | |
| 419 | fn diff_instruction( |
| 420 | left_obj: &Object, |
| 421 | right_obj: &Object, |
| 422 | left_symbol_idx: usize, |
| 423 | right_symbol_idx: usize, |
| 424 | l: Option<InstructionRef>, |
| 425 | r: Option<InstructionRef>, |
| 426 | left_row: &InstructionDiffRow, |
| 427 | right_row: &InstructionDiffRow, |
| 428 | diff_config: &DiffObjConfig, |
| 429 | state: &mut InstructionDiffState, |
| 430 | ) -> Result<InstructionDiffResult> { |
| 431 | let (l, r) = match (l, r) { |
| 432 | (Some(l), Some(r)) => (l, r), |
| 433 | (Some(_), None) => { |
| 434 | state.diff_score += PENALTY_INSERT_DELETE; |
| 435 | return Ok(InstructionDiffResult::new(InstructionDiffKind::Delete)); |
| 436 | } |
| 437 | (None, Some(_)) => { |
| 438 | state.diff_score += PENALTY_INSERT_DELETE; |
| 439 | return Ok(InstructionDiffResult::new(InstructionDiffKind::Insert)); |
| 440 | } |
| 441 | (None, None) => return Ok(InstructionDiffResult::new(InstructionDiffKind::None)), |
| 442 | }; |
| 443 | |
| 444 | // If opcodes don't match, replace |
| 445 | if l.opcode != r.opcode { |
| 446 | state.diff_score += PENALTY_REPLACE; |
| 447 | return Ok(InstructionDiffResult::new(InstructionDiffKind::Replace)); |
| 448 | } |
| 449 | |
| 450 | let left_resolved = left_obj |
| 451 | .resolve_instruction_ref(left_symbol_idx, l) |
| 452 | .context("Failed to resolve left instruction")?; |
| 453 | let right_resolved = right_obj |
| 454 | .resolve_instruction_ref(right_symbol_idx, r) |
| 455 | .context("Failed to resolve right instruction")?; |
| 456 | |
| 457 | if left_resolved.code != right_resolved.code |
| 458 | || !reloc_eq(left_obj, right_obj, left_resolved, right_resolved, diff_config) |
| 459 | { |
| 460 | // If either the raw code bytes or relocations don't match, process instructions and compare args |
| 461 | let left_ins = left_obj.arch.process_instruction(left_resolved, diff_config)?; |
| 462 | let right_ins = right_obj.arch.process_instruction(right_resolved, diff_config)?; |
| 463 | if left_ins.args.len() != right_ins.args.len() { |
| 464 | state.diff_score += PENALTY_REPLACE; |
| 465 | return Ok(InstructionDiffResult::new(InstructionDiffKind::Replace)); |
| 466 | } |
| 467 | let mut result = InstructionDiffResult::new(InstructionDiffKind::None); |
| 468 | if left_ins.mnemonic != right_ins.mnemonic { |
| 469 | state.diff_score += PENALTY_REG_DIFF; |
| 470 | result.kind = InstructionDiffKind::OpMismatch; |
| 471 | } |
| 472 | for (a, b) in left_ins.args.iter().zip(right_ins.args.iter()) { |
| 473 | if arg_eq( |
| 474 | left_obj, |
| 475 | right_obj, |
| 476 | left_row, |
no test coverage detected