diff --git a/objdiff-cli/src/cmd/report.rs b/objdiff-cli/src/cmd/report.rs index be82667..c4541c7 100644 --- a/objdiff-cli/src/cmd/report.rs +++ b/objdiff-cli/src/cmd/report.rs @@ -232,6 +232,7 @@ fn report_object( if symbol.section != Some(section_idx) || symbol.size == 0 || symbol.flags.contains(SymbolFlag::Hidden) + || symbol.flags.contains(SymbolFlag::Ignored) { continue; } diff --git a/objdiff-core/src/arch/mips.rs b/objdiff-core/src/arch/mips.rs index fdf5914..73e7cc4 100644 --- a/objdiff-core/src/arch/mips.rs +++ b/objdiff-core/src/arch/mips.rs @@ -1,4 +1,8 @@ -use alloc::{collections::BTreeMap, string::ToString, vec::Vec}; +use alloc::{ + collections::{BTreeMap, BTreeSet}, + string::ToString, + vec::Vec, +}; use core::ops::Range; use anyhow::{Result, bail}; @@ -15,7 +19,7 @@ use crate::{ diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart}, obj::{ InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags, - ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction, + ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolFlagSet, }, }; @@ -26,6 +30,7 @@ pub struct ArchMips { pub isa_extension: Option, pub ri_gp_value: i32, pub paired_relocations: Vec>, + pub ignored_symbols: BTreeSet, } const EF_MIPS_ABI: u32 = 0x0000F000; @@ -118,7 +123,25 @@ impl ArchMips { paired_relocations[section_index] = addends; } - Ok(Self { endianness, abi, isa_extension, ri_gp_value, paired_relocations }) + let mut ignored_symbols = BTreeSet::new(); + for obj_symbol in object.symbols() { + let Ok(name) = obj_symbol.name() else { continue }; + if let Some(prefix) = name.strip_suffix(".NON_MATCHING") { + ignored_symbols.insert(obj_symbol.index().0); + if let Some(target_symbol) = object.symbol_by_name(prefix) { + ignored_symbols.insert(target_symbol.index().0); + } + } + } + + Ok(Self { + endianness, + abi, + isa_extension, + ri_gp_value, + paired_relocations, + ignored_symbols, + }) } fn instruction_flags(&self, diff_config: &DiffObjConfig) -> rabbitizer::InstructionFlags { @@ -294,6 +317,14 @@ impl Arch for ArchMips { _ => 1, } } + + fn extra_symbol_flags(&self, symbol: &object::Symbol) -> SymbolFlagSet { + let mut flags = SymbolFlagSet::default(); + if self.ignored_symbols.contains(&symbol.index().0) { + flags |= SymbolFlag::Ignored; + } + flags + } } fn push_args( diff --git a/objdiff-core/src/diff/data.rs b/objdiff-core/src/diff/data.rs index eb9e4c5..9cfa045 100644 --- a/objdiff-core/src/diff/data.rs +++ b/objdiff-core/src/diff/data.rs @@ -139,27 +139,13 @@ pub fn diff_data_section( ) -> Result<(SectionDiff, SectionDiff)> { let left_section = &left_obj.sections[left_section_idx]; let right_section = &right_obj.sections[right_section_idx]; - let left_max = left_obj - .symbols - .iter() - .filter_map(|s| { - if s.section != Some(left_section_idx) || s.kind == SymbolKind::Section { - return None; - } - s.address.checked_sub(left_section.address).map(|a| a + s.size) - }) + let left_max = symbols_matching_section(&left_obj.symbols, left_section_idx) + .filter_map(|(_, s)| s.address.checked_sub(left_section.address).map(|a| a + s.size)) .max() .unwrap_or(0) .min(left_section.size); - let right_max = right_obj - .symbols - .iter() - .filter_map(|s| { - if s.section != Some(right_section_idx) || s.kind == SymbolKind::Section { - return None; - } - s.address.checked_sub(right_section.address).map(|a| a + s.size) - }) + let right_max = symbols_matching_section(&right_obj.symbols, right_section_idx) + .filter_map(|(_, s)| s.address.checked_sub(right_section.address).map(|a| a + s.size)) .max() .unwrap_or(0) .min(right_section.size); @@ -412,21 +398,13 @@ pub fn diff_generic_section( left_section_idx: usize, _right_section_idx: usize, ) -> Result<(SectionDiff, SectionDiff)> { - let match_percent = if left_obj - .symbols - .iter() - .enumerate() - .filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section) + let match_percent = if symbols_matching_section(&left_obj.symbols, left_section_idx) .map(|(i, _)| &left_diff.symbols[i]) .all(|d| d.match_percent == Some(100.0)) { 100.0 // Avoid fp precision issues } else { - let (matched, total) = left_obj - .symbols - .iter() - .enumerate() - .filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section) + let (matched, total) = symbols_matching_section(&left_obj.symbols, left_section_idx) .map(|(i, s)| (s, &left_diff.symbols[i])) .fold((0.0, 0.0), |(matched, total), (s, d)| { (matched + d.match_percent.unwrap_or(0.0) * s.size as f32, total + s.size as f32) @@ -449,19 +427,11 @@ pub fn diff_bss_section( right_section_idx: usize, ) -> Result<(SectionDiff, SectionDiff)> { let left_section = &left_obj.sections[left_section_idx]; - let left_sizes = left_obj - .symbols - .iter() - .enumerate() - .filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section) + let left_sizes = symbols_matching_section(&left_obj.symbols, left_section_idx) .filter_map(|(_, s)| s.address.checked_sub(left_section.address).map(|a| (a, s.size))) .collect::>(); let right_section = &right_obj.sections[right_section_idx]; - let right_sizes = right_obj - .symbols - .iter() - .enumerate() - .filter(|(_, s)| s.section == Some(right_section_idx) && s.kind != SymbolKind::Section) + let right_sizes = symbols_matching_section(&right_obj.symbols, right_section_idx) .filter_map(|(_, s)| s.address.checked_sub(right_section.address).map(|a| (a, s.size))) .collect::>(); let ops = capture_diff_slices(Algorithm::Patience, &left_sizes, &right_sizes); @@ -487,3 +457,15 @@ pub fn diff_bss_section( SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] }, )) } + +fn symbols_matching_section( + symbols: &[Symbol], + section_idx: usize, +) -> impl Iterator + '_ { + symbols.iter().enumerate().filter(move |(_, s)| { + s.section == Some(section_idx) + && s.kind != SymbolKind::Section + && s.size > 0 + && !s.flags.contains(SymbolFlag::Ignored) + }) +} diff --git a/objdiff-core/src/diff/display.rs b/objdiff-core/src/diff/display.rs index a36c9aa..48a04a0 100644 --- a/objdiff-core/src/diff/display.rs +++ b/objdiff-core/src/diff/display.rs @@ -580,7 +580,11 @@ fn symbol_matches_filter( if symbol.section.is_none() && !symbol.flags.contains(SymbolFlag::Common) { return false; } - if !show_hidden_symbols && (symbol.size == 0 || symbol.flags.contains(SymbolFlag::Hidden)) { + if !show_hidden_symbols + && (symbol.size == 0 + || symbol.flags.contains(SymbolFlag::Hidden) + || symbol.flags.contains(SymbolFlag::Ignored)) + { return false; } match filter { diff --git a/objdiff-core/src/diff/mod.rs b/objdiff-core/src/diff/mod.rs index 272c63c..43f59d9 100644 --- a/objdiff-core/src/diff/mod.rs +++ b/objdiff-core/src/diff/mod.rs @@ -371,7 +371,10 @@ fn generate_mapping_symbols( }; let base_section_kind = symbol_section_kind(base_obj, &base_obj.symbols[base_symbol_ref]); for (target_symbol_index, target_symbol) in target_obj.symbols.iter().enumerate() { - if symbol_section_kind(target_obj, target_symbol) != base_section_kind { + if target_symbol.size == 0 + || target_symbol.flags.contains(SymbolFlag::Ignored) + || symbol_section_kind(target_obj, target_symbol) != base_section_kind + { continue; } match base_section_kind { @@ -526,6 +529,9 @@ fn matching_symbols( )?; } for (symbol_idx, symbol) in left.symbols.iter().enumerate() { + if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) { + continue; + } let section_kind = symbol_section_kind(left, symbol); if section_kind == SectionKind::Unknown { continue; @@ -547,6 +553,9 @@ fn matching_symbols( } if let Some(right) = right { for (symbol_idx, symbol) in right.symbols.iter().enumerate() { + if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) { + continue; + } let section_kind = symbol_section_kind(right, symbol); if section_kind == SectionKind::Unknown { continue; @@ -572,9 +581,10 @@ fn unmatched_symbols<'obj, 'used>( where 'obj: 'used, { - obj.symbols.iter().enumerate().filter(move |&(symbol_idx, _)| { - // Skip symbols that have already been matched - !used.is_some_and(|u| u.contains(&symbol_idx)) + obj.symbols.iter().enumerate().filter(move |&(symbol_idx, symbol)| { + !symbol.flags.contains(SymbolFlag::Ignored) + // Skip symbols that have already been matched + && !used.is_some_and(|u| u.contains(&symbol_idx)) }) } diff --git a/objdiff-core/src/obj/mod.rs b/objdiff-core/src/obj/mod.rs index 06459d6..f3f18a2 100644 --- a/objdiff-core/src/obj/mod.rs +++ b/objdiff-core/src/obj/mod.rs @@ -42,6 +42,8 @@ flags! { HasExtra, /// Symbol size was missing and was inferred SizeInferred, + /// Symbol should be ignored by any diffing + Ignored, } } diff --git a/objdiff-core/tests/arch_mips.rs b/objdiff-core/tests/arch_mips.rs index a4f2024..03fde07 100644 --- a/objdiff-core/tests/arch_mips.rs +++ b/objdiff-core/tests/arch_mips.rs @@ -37,3 +37,11 @@ fn cross_endian_diff() { assert_eq!(left_diff.instruction_rows[2].kind, diff::InstructionDiffKind::None); assert_eq!(right_diff.instruction_rows[2].kind, diff::InstructionDiffKind::None); } + +#[test] +#[cfg(feature = "mips")] +fn filter_non_matching() { + let diff_config = diff::DiffObjConfig::default(); + let obj = obj::read::parse(include_object!("data/mips/vw_main.c.o"), &diff_config).unwrap(); + insta::assert_debug_snapshot!(obj.symbols); +} \ No newline at end of file diff --git a/objdiff-core/tests/data/mips/vw_main.c.o b/objdiff-core/tests/data/mips/vw_main.c.o new file mode 100644 index 0000000..a0684df Binary files /dev/null and b/objdiff-core/tests/data/mips/vw_main.c.o differ diff --git a/objdiff-core/tests/snapshots/arch_mips__filter_non_matching.snap b/objdiff-core/tests/snapshots/arch_mips__filter_non_matching.snap new file mode 100644 index 0000000..99db1a2 --- /dev/null +++ b/objdiff-core/tests/snapshots/arch_mips__filter_non_matching.snap @@ -0,0 +1,452 @@ +--- +source: objdiff-core/tests/arch_mips.rs +expression: obj.symbols +--- +[ + Symbol { + name: "build/src/bodyprog/view/vw_main.i", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.text]", + demangled_name: None, + address: 0, + size: 0, + kind: Section, + section: Some( + 0, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.data]", + demangled_name: None, + address: 0, + size: 0, + kind: Section, + section: Some( + 2, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.bss]", + demangled_name: None, + address: 0, + size: 0, + kind: Section, + section: Some( + 3, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "gcc2_compiled.", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: Some( + 0, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "__gnu_compiled_c", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: Some( + 0, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: ".endfunc_80048AF4", + demangled_name: None, + address: 424, + size: 0, + kind: Unknown, + section: Some( + 0, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: ".endfunc_80048DA8", + demangled_name: None, + address: 1028, + size: 0, + kind: Unknown, + section: Some( + 0, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: ".endfunc_80048E3C", + demangled_name: None, + address: 1264, + size: 0, + kind: Unknown, + section: Some( + 0, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.reginfo]", + demangled_name: None, + address: 0, + size: 24, + kind: Section, + section: Some( + 4, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.MIPS.abiflags]", + demangled_name: None, + address: 0, + size: 24, + kind: Section, + section: Some( + 5, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.pdr]", + demangled_name: None, + address: 0, + size: 320, + kind: Section, + section: Some( + 6, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.gnu.attributes]", + demangled_name: None, + address: 0, + size: 16, + kind: Section, + section: Some( + 8, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwInitViewInfo", + demangled_name: None, + address: 0, + size: 88, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwViewPointInfo", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "GsInitCoordinate2", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwSetViewInfo", + demangled_name: None, + address: 784, + size: 96, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwGetViewCoord", + demangled_name: None, + address: 88, + size: 12, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwGetViewPosition", + demangled_name: None, + address: 100, + size: 40, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwGetViewAngle", + demangled_name: None, + address: 140, + size: 48, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "func_80048AF4", + demangled_name: None, + address: 188, + size: 236, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global | Ignored), + align: None, + virtual_address: None, + }, + Symbol { + name: "ratan2", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "SquareRoot0", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "func_80096C94", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwSetViewInfoDirectMatrix", + demangled_name: None, + address: 696, + size: 88, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "func_80048AF4.NON_MATCHING", + demangled_name: None, + address: 188, + size: 236, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global | Ignored), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwSetCoordRefAndEntou", + demangled_name: None, + address: 424, + size: 272, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "func_80096E78", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "shRsin", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "shRcos", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "vbSetRefView", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "vwMatrixToAngleYXZ", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Global), + align: None, + virtual_address: None, + }, + Symbol { + name: "func_80048DA8", + demangled_name: None, + address: 880, + size: 148, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global | Ignored), + align: None, + virtual_address: None, + }, + Symbol { + name: "func_80048DA8.NON_MATCHING", + demangled_name: None, + address: 880, + size: 148, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global | Ignored), + align: None, + virtual_address: None, + }, + Symbol { + name: "func_80048E3C", + demangled_name: None, + address: 1028, + size: 236, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global | Ignored), + align: None, + virtual_address: None, + }, + Symbol { + name: "func_80048E3C.NON_MATCHING", + demangled_name: None, + address: 1028, + size: 236, + kind: Function, + section: Some( + 0, + ), + flags: FlagSet(Global | Ignored), + align: None, + virtual_address: None, + }, +] diff --git a/objdiff-core/tests/snapshots/arch_mips__read_mips.snap b/objdiff-core/tests/snapshots/arch_mips__read_mips.snap index c50bac1..dd2b681 100644 --- a/objdiff-core/tests/snapshots/arch_mips__read_mips.snap +++ b/objdiff-core/tests/snapshots/arch_mips__read_mips.snap @@ -50,6 +50,7 @@ Object { {}, {}, ], + ignored_symbols: {}, }, endianness: Little, symbols: [ diff --git a/objdiff-wasm/src/api.rs b/objdiff-wasm/src/api.rs index 6b886e2..90ec812 100644 --- a/objdiff-wasm/src/api.rs +++ b/objdiff-wasm/src/api.rs @@ -320,6 +320,7 @@ impl From for SymbolFlags { obj::SymbolFlag::Hidden => SymbolFlags::HIDDEN, obj::SymbolFlag::HasExtra => SymbolFlags::HAS_EXTRA, obj::SymbolFlag::SizeInferred => SymbolFlags::SIZE_INFERRED, + obj::SymbolFlag::Ignored => SymbolFlags::IGNORED, }; } out diff --git a/objdiff-wasm/wit/objdiff.wit b/objdiff-wasm/wit/objdiff.wit index c9fed13..939e7ee 100644 --- a/objdiff-wasm/wit/objdiff.wit +++ b/objdiff-wasm/wit/objdiff.wit @@ -89,6 +89,7 @@ interface display { hidden, has-extra, size-inferred, + ignored, } record symbol-display {