diff --git a/objdiff-core/src/diff/data.rs b/objdiff-core/src/diff/data.rs index 73b9175..5eeed55 100644 --- a/objdiff-core/src/diff/data.rs +++ b/objdiff-core/src/diff/data.rs @@ -36,12 +36,25 @@ pub fn diff_bss_symbol( } pub fn symbol_name_matches(left_name: &str, right_name: &str) -> bool { - // Match Metrowerks symbol$1234 against symbol$2345 - // and GCC symbol.1234 against symbol.2345 - if let Some((prefix, suffix)) = left_name.split_once(['$', '.']) { - if !suffix.chars().all(char::is_numeric) { - return false; + if let Some((left_prefix, left_suffix)) = left_name.split_once("@class$") + && let Some((right_prefix, right_suffix)) = right_name.split_once("@class$") + { + // Match Metrowerks anonymous class symbol names, ignoring the unique ID. + // e.g. __dt__Q29dCamera_c23@class$3665d_camera_cppFv + if left_prefix == right_prefix + && let Some(left_idx) = left_suffix.chars().position(|c| !c.is_numeric()) + && let Some(right_idx) = right_suffix.chars().position(|c| !c.is_numeric()) + { + // e.g. d_camera_cppFv (after the unique ID) + left_suffix[left_idx..] == right_suffix[right_idx..] + } else { + false } + } else if let Some((prefix, suffix)) = left_name.split_once(['$', '.']) + && suffix.chars().all(char::is_numeric) + { + // Match Metrowerks symbol$1234 against symbol$2345 + // and GCC symbol.1234 against symbol.2345 right_name .split_once(['$', '.']) .is_some_and(|(p, s)| p == prefix && s.chars().all(char::is_numeric)) diff --git a/objdiff-core/src/diff/mod.rs b/objdiff-core/src/diff/mod.rs index efbe2c2..c8c9c31 100644 --- a/objdiff-core/src/diff/mod.rs +++ b/objdiff-core/src/diff/mod.rs @@ -7,6 +7,7 @@ use alloc::{ use core::{num::NonZeroU32, ops::Range}; use anyhow::Result; +use itertools::Itertools; use crate::{ diff::{ @@ -759,18 +760,16 @@ fn find_symbol( return closest_match_symbol_idx; } - // Try to find an exact name match - if let Some((symbol_idx, _)) = unmatched_symbols(obj, used).find(|(_, symbol)| { - symbol.name == in_symbol.name && symbol_section_kind(obj, symbol) == section_kind - }) { - return Some(symbol_idx); - } - - if let Some((symbol_idx, _)) = unmatched_symbols(obj, used).find(|&(_, symbol)| { - symbol_name_matches(&in_symbol.name, &symbol.name) - && symbol_section_kind(obj, symbol) == section_kind - && symbol_section(obj, symbol).is_some_and(|(name, _)| name == section_name) - }) { + // Try to find a symbol with a matching name + if let Some((symbol_idx, _)) = unmatched_symbols(obj, used) + .filter(|&(_, symbol)| { + symbol_name_matches(&in_symbol.name, &symbol.name) + && symbol_section_kind(obj, symbol) == section_kind + && symbol_section(obj, symbol).is_some_and(|(name, _)| name == section_name) + }) + .sorted_unstable_by_key(|&(_, symbol)| (symbol.section, symbol.address)) + .next() + { return Some(symbol_idx); }