Skip to content

Commit 22a24f3

Browse files
committed
Diff data symbols & improve symbol match logic
1 parent 854dc9e commit 22a24f3

File tree

9 files changed

+190
-50
lines changed

9 files changed

+190
-50
lines changed

objdiff-core/src/arch/mips.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Cow;
22

3-
use anyhow::{bail, Result};
3+
use anyhow::{anyhow, bail, Result};
44
use object::{elf, Endian, Endianness, File, Object, Relocation, RelocationFlags};
55
use rabbitizer::{config, Abi, InstrCategory, Instruction, OperandType};
66

@@ -35,6 +35,7 @@ impl ObjArch for ObjArchMips {
3535
config: &DiffObjConfig,
3636
) -> Result<ProcessCodeResult> {
3737
let (section, symbol) = obj.section_symbol(symbol_ref);
38+
let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?;
3839
let code = &section.data
3940
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
4041

objdiff-core/src/arch/ppc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Cow;
22

3-
use anyhow::{bail, Result};
3+
use anyhow::{anyhow, bail, Result};
44
use object::{elf, File, Relocation, RelocationFlags};
55
use ppc750cl::{Argument, InsIter, GPR};
66

@@ -36,6 +36,7 @@ impl ObjArch for ObjArchPpc {
3636
config: &DiffObjConfig,
3737
) -> Result<ProcessCodeResult> {
3838
let (section, symbol) = obj.section_symbol(symbol_ref);
39+
let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?;
3940
let code = &section.data
4041
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
4142

objdiff-core/src/arch/x86.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ impl ObjArch for ObjArchX86 {
3333
config: &DiffObjConfig,
3434
) -> Result<ProcessCodeResult> {
3535
let (section, symbol) = obj.section_symbol(symbol_ref);
36+
let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?;
3637
let code = &section.data
3738
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
3839

objdiff-core/src/diff/code.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub fn no_diff_code(
2828
diff.push(ObjInsDiff { ins: Some(i), kind: ObjInsDiffKind::None, ..Default::default() });
2929
}
3030
resolve_branches(&mut diff);
31-
Ok(ObjSymbolDiff { diff_symbol: None, instructions: diff, match_percent: None })
31+
Ok(ObjSymbolDiff { symbol_ref, diff_symbol: None, instructions: diff, match_percent: None })
3232
}
3333

3434
pub fn diff_code(
@@ -66,11 +66,13 @@ pub fn diff_code(
6666

6767
Ok((
6868
ObjSymbolDiff {
69+
symbol_ref: left_symbol_ref,
6970
diff_symbol: Some(right_symbol_ref),
7071
instructions: left_diff,
7172
match_percent: Some(percent),
7273
},
7374
ObjSymbolDiff {
75+
symbol_ref: right_symbol_ref,
7476
diff_symbol: Some(left_symbol_ref),
7577
instructions: right_diff,
7678
match_percent: Some(percent),

objdiff-core/src/diff/data.rs

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use std::{
33
time::{Duration, Instant},
44
};
55

6-
use anyhow::Result;
7-
use similar::{capture_diff_slices_deadline, Algorithm};
6+
use anyhow::{anyhow, Result};
7+
use similar::{capture_diff_slices_deadline, get_diff_ratio, Algorithm};
88

99
use crate::{
1010
diff::{ObjDataDiff, ObjDataDiffKind, ObjSectionDiff, ObjSymbolDiff},
@@ -22,20 +22,22 @@ pub fn diff_bss_symbol(
2222
let percent = if left_symbol.size == right_symbol.size { 100.0 } else { 50.0 };
2323
Ok((
2424
ObjSymbolDiff {
25+
symbol_ref: left_symbol_ref,
2526
diff_symbol: Some(right_symbol_ref),
2627
instructions: vec![],
2728
match_percent: Some(percent),
2829
},
2930
ObjSymbolDiff {
31+
symbol_ref: right_symbol_ref,
3032
diff_symbol: Some(left_symbol_ref),
3133
instructions: vec![],
3234
match_percent: Some(percent),
3335
},
3436
))
3537
}
3638

37-
pub fn no_diff_bss_symbol(_obj: &ObjInfo, _symbol_ref: SymbolRef) -> ObjSymbolDiff {
38-
ObjSymbolDiff { diff_symbol: None, instructions: vec![], match_percent: Some(0.0) }
39+
pub fn no_diff_symbol(_obj: &ObjInfo, symbol_ref: SymbolRef) -> ObjSymbolDiff {
40+
ObjSymbolDiff { symbol_ref, diff_symbol: None, instructions: vec![], match_percent: None }
3941
}
4042

4143
pub fn diff_data(
@@ -45,6 +47,7 @@ pub fn diff_data(
4547
let deadline = Instant::now() + Duration::from_secs(5);
4648
let ops =
4749
capture_diff_slices_deadline(Algorithm::Patience, &left.data, &right.data, Some(deadline));
50+
let match_percent = get_diff_ratio(&ops, left.data.len(), right.data.len()) * 100.0;
4851

4952
let mut left_diff = Vec::<ObjDataDiff>::new();
5053
let mut right_diff = Vec::<ObjDataDiff>::new();
@@ -118,14 +121,50 @@ pub fn diff_data(
118121
ObjSectionDiff {
119122
symbols: vec![],
120123
data_diff: left_diff,
121-
// TODO
122-
match_percent: None,
124+
match_percent: Some(match_percent),
123125
},
124126
ObjSectionDiff {
125127
symbols: vec![],
126128
data_diff: right_diff,
127-
// TODO
128-
match_percent: None,
129+
match_percent: Some(match_percent),
130+
},
131+
))
132+
}
133+
134+
pub fn diff_data_symbol(
135+
left_obj: &ObjInfo,
136+
right_obj: &ObjInfo,
137+
left_symbol_ref: SymbolRef,
138+
right_symbol_ref: SymbolRef,
139+
) -> Result<(ObjSymbolDiff, ObjSymbolDiff)> {
140+
let (left_section, left_symbol) = left_obj.section_symbol(left_symbol_ref);
141+
let (right_section, right_symbol) = right_obj.section_symbol(right_symbol_ref);
142+
143+
let left_section = left_section.ok_or_else(|| anyhow!("Data symbol section not found"))?;
144+
let right_section = right_section.ok_or_else(|| anyhow!("Data symbol section not found"))?;
145+
146+
let left_data = &left_section.data[left_symbol.section_address as usize
147+
..(left_symbol.section_address + left_symbol.size) as usize];
148+
let right_data = &right_section.data[right_symbol.section_address as usize
149+
..(right_symbol.section_address + right_symbol.size) as usize];
150+
151+
let deadline = Instant::now() + Duration::from_secs(5);
152+
let ops =
153+
capture_diff_slices_deadline(Algorithm::Patience, left_data, right_data, Some(deadline));
154+
let match_percent = get_diff_ratio(&ops, left_data.len(), right_data.len()) * 100.0;
155+
156+
Ok((
157+
ObjSymbolDiff {
158+
symbol_ref: left_symbol_ref,
159+
diff_symbol: Some(right_symbol_ref),
160+
instructions: vec![],
161+
match_percent: Some(match_percent),
162+
},
163+
ObjSymbolDiff {
164+
symbol_ref: right_symbol_ref,
165+
diff_symbol: Some(left_symbol_ref),
166+
instructions: vec![],
167+
match_percent: Some(match_percent),
129168
},
130169
))
131170
}

objdiff-core/src/diff/mod.rs

Lines changed: 97 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
mod code;
2-
mod data;
3-
pub mod display;
4-
51
use std::collections::HashSet;
62

73
use anyhow::Result;
84

95
use crate::{
106
diff::{
117
code::{diff_code, no_diff_code},
12-
data::{diff_bss_symbol, diff_data, no_diff_bss_symbol},
8+
data::{diff_bss_symbol, diff_data, diff_data_symbol, no_diff_symbol},
139
},
14-
obj::{ObjInfo, ObjIns, ObjSectionKind, SymbolRef},
10+
obj::{ObjInfo, ObjIns, ObjSection, ObjSectionKind, ObjSymbol, SymbolRef},
1511
};
1612

13+
mod code;
14+
mod data;
15+
pub mod display;
16+
1717
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
1818
pub enum X86Formatter {
1919
#[default]
@@ -62,6 +62,7 @@ impl ObjSectionDiff {
6262

6363
#[derive(Debug, Clone, Default)]
6464
pub struct ObjSymbolDiff {
65+
pub symbol_ref: SymbolRef,
6566
pub diff_symbol: Option<SymbolRef>,
6667
pub instructions: Vec<ObjInsDiff>,
6768
pub match_percent: Option<f32>,
@@ -142,10 +143,11 @@ impl ObjDiff {
142143
sections: Vec::with_capacity(obj.sections.len()),
143144
common: Vec::with_capacity(obj.common.len()),
144145
};
145-
for section in &obj.sections {
146+
for (section_idx, section) in obj.sections.iter().enumerate() {
146147
let mut symbols = Vec::with_capacity(section.symbols.len());
147-
for _ in &section.symbols {
148+
for (symbol_idx, _) in section.symbols.iter().enumerate() {
148149
symbols.push(ObjSymbolDiff {
150+
symbol_ref: SymbolRef { section_idx, symbol_idx },
149151
diff_symbol: None,
150152
instructions: vec![],
151153
match_percent: None,
@@ -162,8 +164,9 @@ impl ObjDiff {
162164
match_percent: None,
163165
});
164166
}
165-
for _ in &obj.common {
167+
for (symbol_idx, _) in obj.common.iter().enumerate() {
166168
result.common.push(ObjSymbolDiff {
169+
symbol_ref: SymbolRef { section_idx: obj.sections.len(), symbol_idx },
167170
diff_symbol: None,
168171
instructions: vec![],
169172
match_percent: None,
@@ -184,12 +187,20 @@ impl ObjDiff {
184187

185188
#[inline]
186189
pub fn symbol_diff(&self, symbol_ref: SymbolRef) -> &ObjSymbolDiff {
187-
&self.section_diff(symbol_ref.section_idx).symbols[symbol_ref.symbol_idx]
190+
if symbol_ref.section_idx == self.sections.len() {
191+
&self.common[symbol_ref.symbol_idx]
192+
} else {
193+
&self.section_diff(symbol_ref.section_idx).symbols[symbol_ref.symbol_idx]
194+
}
188195
}
189196

190197
#[inline]
191198
pub fn symbol_diff_mut(&mut self, symbol_ref: SymbolRef) -> &mut ObjSymbolDiff {
192-
&mut self.section_diff_mut(symbol_ref.section_idx).symbols[symbol_ref.symbol_idx]
199+
if symbol_ref.section_idx == self.sections.len() {
200+
&mut self.common[symbol_ref.symbol_idx]
201+
} else {
202+
&mut self.section_diff_mut(symbol_ref.section_idx).symbols[symbol_ref.symbol_idx]
203+
}
193204
}
194205
}
195206

@@ -247,7 +258,14 @@ pub fn diff_objs(
247258
}
248259
}
249260
ObjSectionKind::Data => {
250-
// TODO diff data symbol
261+
let (left_diff, right_diff) = diff_data_symbol(
262+
left_obj,
263+
right_obj,
264+
left_symbol_ref,
265+
right_symbol_ref,
266+
)?;
267+
*left_out.symbol_diff_mut(left_symbol_ref) = left_diff;
268+
*right_out.symbol_diff_mut(right_symbol_ref) = right_diff;
251269
}
252270
ObjSectionKind::Bss => {
253271
let (left_diff, right_diff) = diff_bss_symbol(
@@ -268,10 +286,9 @@ pub fn diff_objs(
268286
*left_out.symbol_diff_mut(left_symbol_ref) =
269287
no_diff_code(left_obj, left_symbol_ref, config)?;
270288
}
271-
ObjSectionKind::Data => {}
272-
ObjSectionKind::Bss => {
289+
ObjSectionKind::Data | ObjSectionKind::Bss => {
273290
*left_out.symbol_diff_mut(left_symbol_ref) =
274-
no_diff_bss_symbol(left_obj, left_symbol_ref);
291+
no_diff_symbol(left_obj, left_symbol_ref);
275292
}
276293
}
277294
}
@@ -282,10 +299,9 @@ pub fn diff_objs(
282299
*right_out.symbol_diff_mut(right_symbol_ref) =
283300
no_diff_code(right_obj, right_symbol_ref, config)?;
284301
}
285-
ObjSectionKind::Data => {}
286-
ObjSectionKind::Bss => {
302+
ObjSectionKind::Data | ObjSectionKind::Bss => {
287303
*right_out.symbol_diff_mut(right_symbol_ref) =
288-
no_diff_bss_symbol(right_obj, right_symbol_ref);
304+
no_diff_symbol(right_obj, right_symbol_ref);
289305
}
290306
}
291307
}
@@ -357,8 +373,8 @@ fn matching_symbols(
357373
for (symbol_idx, symbol) in section.symbols.iter().enumerate() {
358374
let symbol_match = SymbolMatch {
359375
left: Some(SymbolRef { section_idx, symbol_idx }),
360-
right: find_symbol(right, &symbol.name, section.kind),
361-
prev: find_symbol(prev, &symbol.name, section.kind),
376+
right: find_symbol(right, symbol, section),
377+
prev: find_symbol(prev, symbol, section),
362378
section_kind: section.kind,
363379
};
364380
matches.push(symbol_match);
@@ -367,6 +383,18 @@ fn matching_symbols(
367383
}
368384
}
369385
}
386+
for (symbol_idx, symbol) in left.common.iter().enumerate() {
387+
let symbol_match = SymbolMatch {
388+
left: Some(SymbolRef { section_idx: left.sections.len(), symbol_idx }),
389+
right: find_common_symbol(right, symbol),
390+
prev: find_common_symbol(prev, symbol),
391+
section_kind: ObjSectionKind::Bss,
392+
};
393+
matches.push(symbol_match);
394+
if let Some(right) = symbol_match.right {
395+
right_used.insert(right);
396+
}
397+
}
370398
}
371399
if let Some(right) = right {
372400
for (section_idx, section) in right.sections.iter().enumerate() {
@@ -378,29 +406,68 @@ fn matching_symbols(
378406
matches.push(SymbolMatch {
379407
left: None,
380408
right: Some(symbol_ref),
381-
prev: find_symbol(prev, &symbol.name, section.kind),
409+
prev: find_symbol(prev, symbol, section),
382410
section_kind: section.kind,
383411
});
384412
}
385413
}
414+
for (symbol_idx, symbol) in right.common.iter().enumerate() {
415+
let symbol_ref = SymbolRef { section_idx: right.sections.len(), symbol_idx };
416+
if right_used.contains(&symbol_ref) {
417+
continue;
418+
}
419+
matches.push(SymbolMatch {
420+
left: None,
421+
right: Some(symbol_ref),
422+
prev: find_common_symbol(prev, symbol),
423+
section_kind: ObjSectionKind::Bss,
424+
});
425+
}
386426
}
387427
Ok(matches)
388428
}
389429

390430
fn find_symbol(
391431
obj: Option<&ObjInfo>,
392-
name: &str,
393-
section_kind: ObjSectionKind,
432+
in_symbol: &ObjSymbol,
433+
in_section: &ObjSection,
394434
) -> Option<SymbolRef> {
395-
for (section_idx, section) in obj?.sections.iter().enumerate() {
396-
if section.kind != section_kind {
435+
let obj = obj?;
436+
// Try to find an exact name match
437+
for (section_idx, section) in obj.sections.iter().enumerate() {
438+
if section.kind != in_section.kind {
397439
continue;
398440
}
399-
let symbol_idx = match section.symbols.iter().position(|symbol| symbol.name == name) {
400-
Some(symbol_idx) => symbol_idx,
401-
None => continue,
402-
};
403-
return Some(SymbolRef { section_idx, symbol_idx });
441+
if let Some(symbol_idx) =
442+
section.symbols.iter().position(|symbol| symbol.name == in_symbol.name)
443+
{
444+
return Some(SymbolRef { section_idx, symbol_idx });
445+
}
446+
}
447+
// Match compiler-generated symbols against each other (e.g. @251 -> @60)
448+
// If they are at the same address in the same section
449+
if in_symbol.name.starts_with('@')
450+
&& matches!(in_section.kind, ObjSectionKind::Data | ObjSectionKind::Bss)
451+
{
452+
if let Some((section_idx, section)) =
453+
obj.sections.iter().enumerate().find(|(_, s)| s.name == in_section.name)
454+
{
455+
if let Some(symbol_idx) = section.symbols.iter().position(|symbol| {
456+
symbol.address == in_symbol.address && symbol.name.starts_with('@')
457+
}) {
458+
return Some(SymbolRef { section_idx, symbol_idx });
459+
}
460+
}
461+
}
462+
None
463+
}
464+
465+
fn find_common_symbol(obj: Option<&ObjInfo>, in_symbol: &ObjSymbol) -> Option<SymbolRef> {
466+
let obj = obj?;
467+
for (symbol_idx, symbol) in obj.common.iter().enumerate() {
468+
if symbol.name == in_symbol.name {
469+
return Some(SymbolRef { section_idx: obj.sections.len(), symbol_idx });
470+
}
404471
}
405472
None
406473
}

0 commit comments

Comments
 (0)