Skip to content

Commit 8e4615e

Browse files
committed
Do two separate passes when pairing up literals
1 parent 81163a6 commit 8e4615e

File tree

1 file changed

+63
-43
lines changed

1 file changed

+63
-43
lines changed

objdiff-core/src/diff/mod.rs

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -575,47 +575,57 @@ fn matching_symbols(
575575
&mut matches,
576576
)?;
577577
}
578-
for (symbol_idx, symbol) in left.symbols.iter().enumerate() {
579-
if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) {
580-
continue;
581-
}
582-
let section_kind = symbol_section_kind(left, symbol);
583-
if section_kind == SectionKind::Unknown {
584-
continue;
585-
}
586-
if left_used.contains(&symbol_idx) {
587-
continue;
588-
}
589-
let symbol_match = SymbolMatch {
590-
left: Some(symbol_idx),
591-
right: find_symbol(right, left, symbol_idx, Some(&right_used)),
592-
prev: find_symbol(prev, left, symbol_idx, None),
593-
section_kind,
594-
};
595-
matches.push(symbol_match);
596-
if let Some(right) = symbol_match.right {
597-
right_used.insert(right);
578+
// Do two passes for nameless literals. The first only pairs up perfect matches to ensure
579+
// those are correct first, while the second pass catches near matches.
580+
for fuzzy_literals in [false, true] {
581+
for (symbol_idx, symbol) in left.symbols.iter().enumerate() {
582+
if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) {
583+
continue;
584+
}
585+
let section_kind = symbol_section_kind(left, symbol);
586+
if section_kind == SectionKind::Unknown {
587+
continue;
588+
}
589+
if left_used.contains(&symbol_idx) {
590+
continue;
591+
}
592+
let symbol_match = SymbolMatch {
593+
left: Some(symbol_idx),
594+
right: find_symbol(right, left, symbol_idx, Some(&right_used), fuzzy_literals),
595+
prev: find_symbol(prev, left, symbol_idx, None, fuzzy_literals),
596+
section_kind,
597+
};
598+
matches.push(symbol_match);
599+
left_used.insert(symbol_idx);
600+
if let Some(right) = symbol_match.right {
601+
right_used.insert(right);
602+
}
598603
}
599604
}
600605
}
601606
if let Some(right) = right {
602-
for (symbol_idx, symbol) in right.symbols.iter().enumerate() {
603-
if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) {
604-
continue;
605-
}
606-
let section_kind = symbol_section_kind(right, symbol);
607-
if section_kind == SectionKind::Unknown {
608-
continue;
609-
}
610-
if right_used.contains(&symbol_idx) {
611-
continue;
607+
// Do two passes for nameless literals. The first only pairs up perfect matches to ensure
608+
// those are correct first, while the second pass catches near matches.
609+
for fuzzy_literals in [false, true] {
610+
for (symbol_idx, symbol) in right.symbols.iter().enumerate() {
611+
if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) {
612+
continue;
613+
}
614+
let section_kind = symbol_section_kind(right, symbol);
615+
if section_kind == SectionKind::Unknown {
616+
continue;
617+
}
618+
if right_used.contains(&symbol_idx) {
619+
continue;
620+
}
621+
matches.push(SymbolMatch {
622+
left: None,
623+
right: Some(symbol_idx),
624+
prev: find_symbol(prev, right, symbol_idx, None, fuzzy_literals),
625+
section_kind,
626+
});
627+
right_used.insert(symbol_idx);
612628
}
613-
matches.push(SymbolMatch {
614-
left: None,
615-
right: Some(symbol_idx),
616-
prev: find_symbol(prev, right, symbol_idx, None),
617-
section_kind,
618-
});
619629
}
620630
}
621631
Ok(matches)
@@ -677,6 +687,7 @@ fn find_symbol(
677687
in_obj: &Object,
678688
in_symbol_idx: usize,
679689
used: Option<&BTreeSet<usize>>,
690+
fuzzy_literals: bool,
680691
) -> Option<usize> {
681692
let in_symbol = &in_obj.symbols[in_symbol_idx];
682693
let obj = obj?;
@@ -687,7 +698,8 @@ fn find_symbol(
687698
if is_symbol_compiler_generated_literal(in_symbol)
688699
&& matches!(section_kind, SectionKind::Data | SectionKind::Bss)
689700
{
690-
let mut matching_symbol_idx = None;
701+
let mut closest_match_symbol_idx = None;
702+
let mut closest_match_percent = 0.0;
691703
for (symbol_idx, symbol) in unmatched_symbols(obj, used) {
692704
let Some(section_index) = symbol.section else {
693705
continue;
@@ -700,27 +712,35 @@ fn find_symbol(
700712
}
701713
match section_kind {
702714
SectionKind::Data => {
703-
// For data, pick the first symbol that has the exact matching bytes and relocations.
715+
// For data, pick the first symbol with exactly matching bytes and relocations.
716+
// If no symbols match exactly, and `fuzzy_literals` is true, pick the closest
717+
// plausible match instead.
704718
if let Ok((left_diff, _right_diff)) =
705719
diff_data_symbol(in_obj, obj, in_symbol_idx, symbol_idx)
706720
&& let Some(match_percent) = left_diff.match_percent
707-
&& match_percent == 100.0
721+
&& (match_percent == 100.0
722+
|| (fuzzy_literals
723+
&& match_percent >= 50.0
724+
&& match_percent > closest_match_percent))
708725
{
709-
matching_symbol_idx = Some(symbol_idx);
710-
break;
726+
closest_match_symbol_idx = Some(symbol_idx);
727+
closest_match_percent = match_percent;
728+
if match_percent == 100.0 {
729+
break;
730+
}
711731
}
712732
}
713733
SectionKind::Bss => {
714734
// For BSS, pick the first symbol that has the exact matching size.
715735
if in_symbol.size == symbol.size {
716-
matching_symbol_idx = Some(symbol_idx);
736+
closest_match_symbol_idx = Some(symbol_idx);
717737
break;
718738
}
719739
}
720740
_ => unreachable!(),
721741
}
722742
}
723-
return matching_symbol_idx;
743+
return closest_match_symbol_idx;
724744
}
725745

726746
// Try to find an exact name match

0 commit comments

Comments
 (0)