mirror of
https://github.com/encounter/objdiff.git
synced 2026-03-30 11:32:16 -07:00
Improve automatic symbol pairing for functions with compiler-generated names (#303)
* Fix `__arraydtor$1234`s sometimes being swapped The list of symbols is not necessarily sorted by address, so if there are multiple `__arraydtor$1234` functions it's possible that they're in reverse order on the right, which would cause them to be paired up incorrectly. To fix this we sort by section index and symbol address after filtering down the list of symbols to ones that have matching names. * Support pairing up symbols for anonymous classes * Disallow exact-name pairups for compiler-generated symbols
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user