Skip to content

Commit e3fff7b

Browse files
committed
Improve data section diff logic
More accurate in more cases Fixes #81
1 parent 75b0e7d commit e3fff7b

File tree

2 files changed

+52
-54
lines changed

2 files changed

+52
-54
lines changed

objdiff-core/src/diff/data.rs

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,6 @@ use crate::{
1111
obj::{ObjInfo, ObjSection, SymbolRef},
1212
};
1313

14-
/// Compare the addresses and sizes of each symbol in the BSS sections.
15-
pub fn diff_bss_section(
16-
left: &ObjSection,
17-
right: &ObjSection,
18-
) -> Result<(ObjSectionDiff, ObjSectionDiff)> {
19-
let deadline = Instant::now() + Duration::from_secs(5);
20-
let left_sizes = left.symbols.iter().map(|s| (s.section_address, s.size)).collect::<Vec<_>>();
21-
let right_sizes = right.symbols.iter().map(|s| (s.section_address, s.size)).collect::<Vec<_>>();
22-
let ops = capture_diff_slices_deadline(
23-
Algorithm::Patience,
24-
&left_sizes,
25-
&right_sizes,
26-
Some(deadline),
27-
);
28-
let match_percent = get_diff_ratio(&ops, left_sizes.len(), right_sizes.len()) * 100.0;
29-
Ok((
30-
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
31-
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
32-
))
33-
}
34-
3514
pub fn diff_bss_symbol(
3615
left_obj: &ObjInfo,
3716
right_obj: &ObjInfo,
@@ -65,6 +44,8 @@ pub fn no_diff_symbol(_obj: &ObjInfo, symbol_ref: SymbolRef) -> ObjSymbolDiff {
6544
pub fn diff_data_section(
6645
left: &ObjSection,
6746
right: &ObjSection,
47+
left_section_diff: &ObjSectionDiff,
48+
right_section_diff: &ObjSectionDiff,
6849
) -> Result<(ObjSectionDiff, ObjSectionDiff)> {
6950
let deadline = Instant::now() + Duration::from_secs(5);
7051
let left_max = left.symbols.iter().map(|s| s.section_address + s.size).max().unwrap_or(0);
@@ -73,7 +54,6 @@ pub fn diff_data_section(
7354
let right_data = &right.data[..right_max as usize];
7455
let ops =
7556
capture_diff_slices_deadline(Algorithm::Patience, left_data, right_data, Some(deadline));
76-
let match_percent = get_diff_ratio(&ops, left_data.len(), right_data.len()) * 100.0;
7757

7858
let mut left_diff = Vec::<ObjDataDiff>::new();
7959
let mut right_diff = Vec::<ObjDataDiff>::new();
@@ -143,18 +123,11 @@ pub fn diff_data_section(
143123
}
144124
}
145125

146-
Ok((
147-
ObjSectionDiff {
148-
symbols: vec![],
149-
data_diff: left_diff,
150-
match_percent: Some(match_percent),
151-
},
152-
ObjSectionDiff {
153-
symbols: vec![],
154-
data_diff: right_diff,
155-
match_percent: Some(match_percent),
156-
},
157-
))
126+
let (mut left_section_diff, mut right_section_diff) =
127+
diff_generic_section(left, right, left_section_diff, right_section_diff)?;
128+
left_section_diff.data_diff = left_diff;
129+
right_section_diff.data_diff = right_diff;
130+
Ok((left_section_diff, right_section_diff))
158131
}
159132

160133
pub fn diff_data_symbol(
@@ -195,21 +168,24 @@ pub fn diff_data_symbol(
195168
))
196169
}
197170

198-
/// Compare the text sections of two object files.
199-
/// This essentially adds up the match percentage of each symbol in the text section.
200-
pub fn diff_text_section(
171+
/// Compares a section of two object files.
172+
/// This essentially adds up the match percentage of each symbol in the section.
173+
pub fn diff_generic_section(
201174
left: &ObjSection,
202175
_right: &ObjSection,
203176
left_diff: &ObjSectionDiff,
204177
_right_diff: &ObjSectionDiff,
205178
) -> Result<(ObjSectionDiff, ObjSectionDiff)> {
206-
let match_percent = left
207-
.symbols
208-
.iter()
209-
.zip(left_diff.symbols.iter())
210-
.map(|(s, d)| d.match_percent.unwrap_or(0.0) * s.size as f32)
211-
.sum::<f32>()
212-
/ left.size as f32;
179+
let match_percent = if left_diff.symbols.iter().all(|d| d.match_percent == Some(100.0)) {
180+
100.0 // Avoid fp precision issues
181+
} else {
182+
left.symbols
183+
.iter()
184+
.zip(left_diff.symbols.iter())
185+
.map(|(s, d)| d.match_percent.unwrap_or(0.0) * s.size as f32)
186+
.sum::<f32>()
187+
/ left.size as f32
188+
};
213189
Ok((
214190
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
215191
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },

objdiff-core/src/diff/mod.rs

Lines changed: 32 additions & 10 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_section, diff_bss_symbol, diff_data_section, diff_data_symbol,
10-
diff_text_section, no_diff_symbol,
9+
diff_bss_symbol, diff_data_section, diff_data_symbol, diff_generic_section,
10+
no_diff_symbol,
1111
},
1212
},
1313
obj::{ObjInfo, ObjIns, ObjSection, ObjSectionKind, ObjSymbol, SymbolRef},
@@ -483,10 +483,10 @@ 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 => {
486+
ObjSectionKind::Code | ObjSectionKind::Bss => {
487487
let left_section_diff = left_out.section_diff(left_section_idx);
488488
let right_section_diff = right_out.section_diff(right_section_idx);
489-
let (left_diff, right_diff) = diff_text_section(
489+
let (left_diff, right_diff) = diff_generic_section(
490490
left_section,
491491
right_section,
492492
left_section_diff,
@@ -496,12 +496,14 @@ pub fn diff_objs(
496496
right_out.section_diff_mut(right_section_idx).merge(right_diff);
497497
}
498498
ObjSectionKind::Data => {
499-
let (left_diff, right_diff) = diff_data_section(left_section, right_section)?;
500-
left_out.section_diff_mut(left_section_idx).merge(left_diff);
501-
right_out.section_diff_mut(right_section_idx).merge(right_diff);
502-
}
503-
ObjSectionKind::Bss => {
504-
let (left_diff, right_diff) = diff_bss_section(left_section, right_section)?;
499+
let left_section_diff = left_out.section_diff(left_section_idx);
500+
let right_section_diff = right_out.section_diff(right_section_idx);
501+
let (left_diff, right_diff) = diff_data_section(
502+
left_section,
503+
right_section,
504+
left_section_diff,
505+
right_section_diff,
506+
)?;
505507
left_out.section_diff_mut(left_section_idx).merge(left_diff);
506508
right_out.section_diff_mut(right_section_idx).merge(right_diff);
507509
}
@@ -630,6 +632,26 @@ fn find_symbol(
630632
}
631633
}
632634
}
635+
// Match Metrowerks symbol$1234 against symbol$2345
636+
if let Some((prefix, suffix)) = in_symbol.name.split_once('$') {
637+
if !suffix.chars().all(char::is_numeric) {
638+
return None;
639+
}
640+
for (section_idx, section) in obj.sections.iter().enumerate() {
641+
if section.kind != in_section.kind {
642+
continue;
643+
}
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+
}) {
651+
return Some(SymbolRef { section_idx, symbol_idx });
652+
}
653+
}
654+
}
633655
None
634656
}
635657

0 commit comments

Comments
 (0)