mips: Ignore .NON_MATCHING functions from INLINE_ASM macros

This commit is contained in:
Luke Street 2025-03-11 21:39:17 -06:00
parent fa26200ed7
commit 42d4c38079
12 changed files with 539 additions and 46 deletions

View File

@ -232,6 +232,7 @@ fn report_object(
if symbol.section != Some(section_idx) if symbol.section != Some(section_idx)
|| symbol.size == 0 || symbol.size == 0
|| symbol.flags.contains(SymbolFlag::Hidden) || symbol.flags.contains(SymbolFlag::Hidden)
|| symbol.flags.contains(SymbolFlag::Ignored)
{ {
continue; continue;
} }

View File

@ -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 core::ops::Range;
use anyhow::{Result, bail}; use anyhow::{Result, bail};
@ -15,7 +19,7 @@ use crate::{
diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart}, diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart},
obj::{ obj::{
InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags, InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags,
ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction, ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolFlagSet,
}, },
}; };
@ -26,6 +30,7 @@ pub struct ArchMips {
pub isa_extension: Option<IsaExtension>, pub isa_extension: Option<IsaExtension>,
pub ri_gp_value: i32, pub ri_gp_value: i32,
pub paired_relocations: Vec<BTreeMap<u64, i64>>, pub paired_relocations: Vec<BTreeMap<u64, i64>>,
pub ignored_symbols: BTreeSet<usize>,
} }
const EF_MIPS_ABI: u32 = 0x0000F000; const EF_MIPS_ABI: u32 = 0x0000F000;
@ -118,7 +123,25 @@ impl ArchMips {
paired_relocations[section_index] = addends; 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 { fn instruction_flags(&self, diff_config: &DiffObjConfig) -> rabbitizer::InstructionFlags {
@ -294,6 +317,14 @@ impl Arch for ArchMips {
_ => 1, _ => 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( fn push_args(

View File

@ -139,27 +139,13 @@ pub fn diff_data_section(
) -> Result<(SectionDiff, SectionDiff)> { ) -> Result<(SectionDiff, SectionDiff)> {
let left_section = &left_obj.sections[left_section_idx]; let left_section = &left_obj.sections[left_section_idx];
let right_section = &right_obj.sections[right_section_idx]; let right_section = &right_obj.sections[right_section_idx];
let left_max = left_obj let left_max = symbols_matching_section(&left_obj.symbols, left_section_idx)
.symbols .filter_map(|(_, s)| s.address.checked_sub(left_section.address).map(|a| a + s.size))
.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)
})
.max() .max()
.unwrap_or(0) .unwrap_or(0)
.min(left_section.size); .min(left_section.size);
let right_max = right_obj let right_max = symbols_matching_section(&right_obj.symbols, right_section_idx)
.symbols .filter_map(|(_, s)| s.address.checked_sub(right_section.address).map(|a| a + s.size))
.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)
})
.max() .max()
.unwrap_or(0) .unwrap_or(0)
.min(right_section.size); .min(right_section.size);
@ -412,21 +398,13 @@ pub fn diff_generic_section(
left_section_idx: usize, left_section_idx: usize,
_right_section_idx: usize, _right_section_idx: usize,
) -> Result<(SectionDiff, SectionDiff)> { ) -> Result<(SectionDiff, SectionDiff)> {
let match_percent = if left_obj let match_percent = if symbols_matching_section(&left_obj.symbols, left_section_idx)
.symbols
.iter()
.enumerate()
.filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section)
.map(|(i, _)| &left_diff.symbols[i]) .map(|(i, _)| &left_diff.symbols[i])
.all(|d| d.match_percent == Some(100.0)) .all(|d| d.match_percent == Some(100.0))
{ {
100.0 // Avoid fp precision issues 100.0 // Avoid fp precision issues
} else { } else {
let (matched, total) = left_obj let (matched, total) = symbols_matching_section(&left_obj.symbols, left_section_idx)
.symbols
.iter()
.enumerate()
.filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section)
.map(|(i, s)| (s, &left_diff.symbols[i])) .map(|(i, s)| (s, &left_diff.symbols[i]))
.fold((0.0, 0.0), |(matched, total), (s, d)| { .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) (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, right_section_idx: usize,
) -> Result<(SectionDiff, SectionDiff)> { ) -> Result<(SectionDiff, SectionDiff)> {
let left_section = &left_obj.sections[left_section_idx]; let left_section = &left_obj.sections[left_section_idx];
let left_sizes = left_obj let left_sizes = symbols_matching_section(&left_obj.symbols, left_section_idx)
.symbols
.iter()
.enumerate()
.filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section)
.filter_map(|(_, s)| s.address.checked_sub(left_section.address).map(|a| (a, s.size))) .filter_map(|(_, s)| s.address.checked_sub(left_section.address).map(|a| (a, s.size)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let right_section = &right_obj.sections[right_section_idx]; let right_section = &right_obj.sections[right_section_idx];
let right_sizes = right_obj let right_sizes = symbols_matching_section(&right_obj.symbols, right_section_idx)
.symbols
.iter()
.enumerate()
.filter(|(_, s)| s.section == Some(right_section_idx) && s.kind != SymbolKind::Section)
.filter_map(|(_, s)| s.address.checked_sub(right_section.address).map(|a| (a, s.size))) .filter_map(|(_, s)| s.address.checked_sub(right_section.address).map(|a| (a, s.size)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let ops = capture_diff_slices(Algorithm::Patience, &left_sizes, &right_sizes); 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![] }, SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
)) ))
} }
fn symbols_matching_section(
symbols: &[Symbol],
section_idx: usize,
) -> impl Iterator<Item = (usize, &Symbol)> + '_ {
symbols.iter().enumerate().filter(move |(_, s)| {
s.section == Some(section_idx)
&& s.kind != SymbolKind::Section
&& s.size > 0
&& !s.flags.contains(SymbolFlag::Ignored)
})
}

View File

@ -580,7 +580,11 @@ fn symbol_matches_filter(
if symbol.section.is_none() && !symbol.flags.contains(SymbolFlag::Common) { if symbol.section.is_none() && !symbol.flags.contains(SymbolFlag::Common) {
return false; 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; return false;
} }
match filter { match filter {

View File

@ -371,7 +371,10 @@ fn generate_mapping_symbols(
}; };
let base_section_kind = symbol_section_kind(base_obj, &base_obj.symbols[base_symbol_ref]); 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() { 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; continue;
} }
match base_section_kind { match base_section_kind {
@ -526,6 +529,9 @@ fn matching_symbols(
)?; )?;
} }
for (symbol_idx, symbol) in left.symbols.iter().enumerate() { 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); let section_kind = symbol_section_kind(left, symbol);
if section_kind == SectionKind::Unknown { if section_kind == SectionKind::Unknown {
continue; continue;
@ -547,6 +553,9 @@ fn matching_symbols(
} }
if let Some(right) = right { if let Some(right) = right {
for (symbol_idx, symbol) in right.symbols.iter().enumerate() { 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); let section_kind = symbol_section_kind(right, symbol);
if section_kind == SectionKind::Unknown { if section_kind == SectionKind::Unknown {
continue; continue;
@ -572,9 +581,10 @@ fn unmatched_symbols<'obj, 'used>(
where where
'obj: 'used, 'obj: 'used,
{ {
obj.symbols.iter().enumerate().filter(move |&(symbol_idx, _)| { obj.symbols.iter().enumerate().filter(move |&(symbol_idx, symbol)| {
// Skip symbols that have already been matched !symbol.flags.contains(SymbolFlag::Ignored)
!used.is_some_and(|u| u.contains(&symbol_idx)) // Skip symbols that have already been matched
&& !used.is_some_and(|u| u.contains(&symbol_idx))
}) })
} }

View File

@ -42,6 +42,8 @@ flags! {
HasExtra, HasExtra,
/// Symbol size was missing and was inferred /// Symbol size was missing and was inferred
SizeInferred, SizeInferred,
/// Symbol should be ignored by any diffing
Ignored,
} }
} }

View File

@ -37,3 +37,11 @@ fn cross_endian_diff() {
assert_eq!(left_diff.instruction_rows[2].kind, diff::InstructionDiffKind::None); assert_eq!(left_diff.instruction_rows[2].kind, diff::InstructionDiffKind::None);
assert_eq!(right_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);
}

Binary file not shown.

View File

@ -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,
},
]

View File

@ -50,6 +50,7 @@ Object {
{}, {},
{}, {},
], ],
ignored_symbols: {},
}, },
endianness: Little, endianness: Little,
symbols: [ symbols: [

View File

@ -320,6 +320,7 @@ impl From<obj::SymbolFlagSet> for SymbolFlags {
obj::SymbolFlag::Hidden => SymbolFlags::HIDDEN, obj::SymbolFlag::Hidden => SymbolFlags::HIDDEN,
obj::SymbolFlag::HasExtra => SymbolFlags::HAS_EXTRA, obj::SymbolFlag::HasExtra => SymbolFlags::HAS_EXTRA,
obj::SymbolFlag::SizeInferred => SymbolFlags::SIZE_INFERRED, obj::SymbolFlag::SizeInferred => SymbolFlags::SIZE_INFERRED,
obj::SymbolFlag::Ignored => SymbolFlags::IGNORED,
}; };
} }
out out

View File

@ -89,6 +89,7 @@ interface display {
hidden, hidden,
has-extra, has-extra,
size-inferred, size-inferred,
ignored,
} }
record symbol-display { record symbol-display {