Skip to content

Commit e1ccee1

Browse files
committed
Improve data section diffing more
This re-implements the older algorithm used for data and BSS section match percentages. We perform both and choose the highest match percent between the two options. Resolves #84, #85
1 parent 952b6a6 commit e1ccee1

File tree

3 files changed

+75
-14
lines changed

3 files changed

+75
-14
lines changed

objdiff-core/src/diff/data.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub fn diff_data_section(
5454
let right_data = &right.data[..right_max as usize];
5555
let ops =
5656
capture_diff_slices_deadline(Algorithm::Patience, left_data, right_data, Some(deadline));
57+
let match_percent = get_diff_ratio(&ops, left_data.len(), right_data.len()) * 100.0;
5758

5859
let mut left_diff = Vec::<ObjDataDiff>::new();
5960
let mut right_diff = Vec::<ObjDataDiff>::new();
@@ -127,6 +128,13 @@ pub fn diff_data_section(
127128
diff_generic_section(left, right, left_section_diff, right_section_diff)?;
128129
left_section_diff.data_diff = left_diff;
129130
right_section_diff.data_diff = right_diff;
131+
// Use the highest match percent between two options:
132+
// - Left symbols matching right symbols by name
133+
// - Diff of the data itself
134+
if left_section_diff.match_percent.unwrap_or(-1.0) < match_percent {
135+
left_section_diff.match_percent = Some(match_percent);
136+
right_section_diff.match_percent = Some(match_percent);
137+
}
130138
Ok((left_section_diff, right_section_diff))
131139
}
132140

@@ -191,3 +199,35 @@ pub fn diff_generic_section(
191199
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
192200
))
193201
}
202+
203+
/// Compare the addresses and sizes of each symbol in the BSS sections.
204+
pub fn diff_bss_section(
205+
left: &ObjSection,
206+
right: &ObjSection,
207+
left_diff: &ObjSectionDiff,
208+
right_diff: &ObjSectionDiff,
209+
) -> Result<(ObjSectionDiff, ObjSectionDiff)> {
210+
let deadline = Instant::now() + Duration::from_secs(5);
211+
let left_sizes = left.symbols.iter().map(|s| (s.section_address, s.size)).collect::<Vec<_>>();
212+
let right_sizes = right.symbols.iter().map(|s| (s.section_address, s.size)).collect::<Vec<_>>();
213+
let ops = capture_diff_slices_deadline(
214+
Algorithm::Patience,
215+
&left_sizes,
216+
&right_sizes,
217+
Some(deadline),
218+
);
219+
let mut match_percent = get_diff_ratio(&ops, left_sizes.len(), right_sizes.len()) * 100.0;
220+
221+
// Use the highest match percent between two options:
222+
// - Left symbols matching right symbols by name
223+
// - Diff of the addresses and sizes of each symbol
224+
let (generic_diff, _) = diff_generic_section(left, right, left_diff, right_diff)?;
225+
if generic_diff.match_percent.unwrap_or(-1.0) > match_percent {
226+
match_percent = generic_diff.match_percent.unwrap();
227+
}
228+
229+
Ok((
230+
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
231+
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
232+
))
233+
}

objdiff-core/src/diff/mod.rs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::{
66
diff::{
77
code::{diff_code, no_diff_code, process_code_symbol},
88
data::{
9-
diff_bss_symbol, diff_data_section, diff_data_symbol, diff_generic_section,
10-
no_diff_symbol,
9+
diff_bss_section, diff_bss_symbol, diff_data_section, diff_data_symbol,
10+
diff_generic_section, no_diff_symbol,
1111
},
1212
},
1313
obj::{ObjInfo, ObjIns, ObjSection, ObjSectionKind, ObjSymbol, SymbolRef},
@@ -483,7 +483,7 @@ pub fn diff_objs(
483483
let left_section = &left_obj.sections[left_section_idx];
484484
let right_section = &right_obj.sections[right_section_idx];
485485
match section_kind {
486-
ObjSectionKind::Code | ObjSectionKind::Bss => {
486+
ObjSectionKind::Code => {
487487
let left_section_diff = left_out.section_diff(left_section_idx);
488488
let right_section_diff = right_out.section_diff(right_section_idx);
489489
let (left_diff, right_diff) = diff_generic_section(
@@ -507,6 +507,18 @@ pub fn diff_objs(
507507
left_out.section_diff_mut(left_section_idx).merge(left_diff);
508508
right_out.section_diff_mut(right_section_idx).merge(right_diff);
509509
}
510+
ObjSectionKind::Bss => {
511+
let left_section_diff = left_out.section_diff(left_section_idx);
512+
let right_section_diff = right_out.section_diff(right_section_idx);
513+
let (left_diff, right_diff) = diff_bss_section(
514+
left_section,
515+
right_section,
516+
left_section_diff,
517+
right_section_diff,
518+
)?;
519+
left_out.section_diff_mut(left_section_idx).merge(left_diff);
520+
right_out.section_diff_mut(right_section_idx).merge(right_diff);
521+
}
510522
}
511523
}
512524
}
@@ -546,8 +558,8 @@ fn matching_symbols(
546558
for (symbol_idx, symbol) in section.symbols.iter().enumerate() {
547559
let symbol_match = SymbolMatch {
548560
left: Some(SymbolRef { section_idx, symbol_idx }),
549-
right: find_symbol(right, symbol, section),
550-
prev: find_symbol(prev, symbol, section),
561+
right: find_symbol(right, symbol, section, Some(&right_used)),
562+
prev: find_symbol(prev, symbol, section, None),
551563
section_kind: section.kind,
552564
};
553565
matches.push(symbol_match);
@@ -579,7 +591,7 @@ fn matching_symbols(
579591
matches.push(SymbolMatch {
580592
left: None,
581593
right: Some(symbol_ref),
582-
prev: find_symbol(prev, symbol, section),
594+
prev: find_symbol(prev, symbol, section, None),
583595
section_kind: section.kind,
584596
});
585597
}
@@ -604,6 +616,7 @@ fn find_symbol(
604616
obj: Option<&ObjInfo>,
605617
in_symbol: &ObjSymbol,
606618
in_section: &ObjSection,
619+
used: Option<&HashSet<SymbolRef>>,
607620
) -> Option<SymbolRef> {
608621
let obj = obj?;
609622
// Try to find an exact name match
@@ -641,13 +654,21 @@ fn find_symbol(
641654
if section.kind != in_section.kind {
642655
continue;
643656
}
644-
if let Some(symbol_idx) = section.symbols.iter().position(|symbol| {
645-
if let Some((p, s)) = symbol.name.split_once('$') {
646-
prefix == p && s.chars().all(char::is_numeric)
647-
} else {
648-
false
649-
}
650-
}) {
657+
if let Some((symbol_idx, _)) =
658+
section.symbols.iter().enumerate().find(|&(symbol_idx, symbol)| {
659+
if used
660+
.map(|u| u.contains(&SymbolRef { section_idx, symbol_idx }))
661+
.unwrap_or(false)
662+
{
663+
return false;
664+
}
665+
if let Some((p, s)) = symbol.name.split_once('$') {
666+
prefix == p && s.chars().all(char::is_numeric)
667+
} else {
668+
false
669+
}
670+
})
671+
{
651672
return Some(SymbolRef { section_idx, symbol_idx });
652673
}
653674
}

objdiff-core/src/obj/read.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ fn symbols_by_section(
149149
}
150150
}
151151
}
152-
result.sort_by_key(|v| v.address);
152+
result.sort_by(|a, b| a.address.cmp(&b.address).then(a.size.cmp(&b.size)));
153153
let mut iter = result.iter_mut().peekable();
154154
while let Some(symbol) = iter.next() {
155155
if symbol.size == 0 {

0 commit comments

Comments
 (0)