From 42d4c380796b46ed52396e94cb43e98651754368 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 11 Mar 2025 21:39:17 -0600 Subject: [PATCH] mips: Ignore `.NON_MATCHING` functions from `INLINE_ASM` macros --- objdiff-cli/src/cmd/report.rs | 1 + objdiff-core/src/arch/mips.rs | 37 +- objdiff-core/src/diff/data.rs | 58 +-- objdiff-core/src/diff/display.rs | 6 +- objdiff-core/src/diff/mod.rs | 18 +- objdiff-core/src/obj/mod.rs | 2 + objdiff-core/tests/arch_mips.rs | 8 + objdiff-core/tests/data/mips/vw_main.c.o | Bin 0 -> 3700 bytes .../arch_mips__filter_non_matching.snap | 452 ++++++++++++++++++ .../tests/snapshots/arch_mips__read_mips.snap | 1 + objdiff-wasm/src/api.rs | 1 + objdiff-wasm/wit/objdiff.wit | 1 + 12 files changed, 539 insertions(+), 46 deletions(-) create mode 100644 objdiff-core/tests/data/mips/vw_main.c.o create mode 100644 objdiff-core/tests/snapshots/arch_mips__filter_non_matching.snap 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 0000000000000000000000000000000000000000..a0684dfb908ef95bb0cfb1e61fd336ef38ddc702 GIT binary patch literal 3700 zcmcImUu;`f8UOiSw{?mkx2ZQgFyK3TofRV23#PbIgq%7~QmO4i+f5xWiT@?NT522H z=^tsRVeL>SS#?23D{o#>NCr`yZh-QzY1JOK?hy$dka)<`C=wFzFbT0C@An=1x;Gw( z@xYOezw`UP?|lExch2?I^odEA%LRM5;K4%#EP4T#0mPL;1fK^Pj`5)V){}rf24uqq z-fnr2+;DROa~m-9a1iOR83cDFHw;c6QX76Hhc|#U^*RQ*w;^Ud*wOtEo7$MHgE$tJ zHAu@y)oV!CFJrO}T%(_tHaz$t=Z-FWZM~~V-FN}1+t-l3v5fR>9oN>Wzr7DHt#i+| zt-r!<-I%}W!B*Xa?9DiuYoQwKurR63zgB=_pmRLkzy) z-GI(1*bG9`e|nJh%4%x;st-~>v-x99f9(c7NqrqGn%&WotRXq~j{*s=ua{*R)&OhfFuhqR+uZP*E5ln83 zU}__VY4+}F-AB2f@&M&=$`h22QJ$pS?kTwshUy=KJ!>5Dv0iqb6WBw%Qhx#NL*TiU zp>39_<0mgb`@+LxI^5*T9uM?Q?r+eZio0_!)~^FEa{?h_z||g{j)h|HBb4|v+Jo=L z+Jk?J4I3Zuo+f=J`)}BohlZpvY&?MJzXx5db(fjkp-gw}CpHZW|K!!9zH8W6p#P4( z=!#5qg|-Ke@eE(QV=BMLVx62T@kZ0j5oL{pU|Azj*<-1*8UH;e+UxLE_&A)5c z{?C%%ZvX!ojSo_`P+Wp*9~bUV)z`^zM}2sJwb|yg zWyc#LcG~+kvDDAtl=#k)+C%JR`>@rA%YFF!efT-rC^P?`kc$0VlsobBUeR!L@3Ldl2xoJJXIBO zs#L1vtzxED7^TLUf>VF0gOmz|T{u&!S~aUwe8?FuE-V&M$<#8%QJneSQl?TkT`JXL zuwy=YBy}{t+x&!8DdcJ=Gqs9!xu>Uci=KM=)a=Rev#IIhr=~iaR0O9B^W(*Qx>zeM z^)?(mlKxf#)$^yTR#8Z+Cv!JqM%k3Q(XGO?(*>*d#?QSgX+qAQjg}O8pwp+KH%BabayJB@?_#+df^T)P^sW0*{{I#FMcV1& z8KHD?UFc)L??`3e4yoAn@J`6S5upKKOei1Kve2(~?u_WaNvz^!4-4j}N#QW5n;(dC zLW974q12sYqC#b8UjTwa`8P5t^k641jbGDc!H)n31yr+LRkl16=){+3k?xR zt5+`6GFj4Er9;o#t4d)pS}R#!ENR^6$>TF;qM58UznEE2{KaTF zUqO_&B$}zQgR)DtLX{pq^N{Z%!|J`3Nv 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 {