diff --git a/objdiff-core/src/arch/ppc/mod.rs b/objdiff-core/src/arch/ppc/mod.rs index e60731e4..9421ecf7 100644 --- a/objdiff-core/src/arch/ppc/mod.rs +++ b/objdiff-core/src/arch/ppc/mod.rs @@ -364,10 +364,10 @@ impl Arch for ArchPpc { bytes: &[u8], ) -> Option { if reloc.is_some_and(|r| { - r.symbol.name.starts_with("@stringBase") - || r.symbol.name.starts_with("@wstringBase") + r.symbol.name.starts_with("@stringBase") // MWCC + || r.symbol.name.starts_with("@wstringBase") // MWCC || r.symbol.name.starts_with("$SG") - || r.symbol.demangled_name == Some("`string'".to_string()) + || r.symbol.name.starts_with("??_C") // MSVC }) { // Compiler-generated symbol name for a string or a pool of strings. return Some(DataType::String); diff --git a/objdiff-core/src/diff/mod.rs b/objdiff-core/src/diff/mod.rs index 1e683db7..f82242df 100644 --- a/objdiff-core/src/diff/mod.rs +++ b/objdiff-core/src/diff/mod.rs @@ -18,7 +18,7 @@ use crate::{ }, obj::{ InstructionRef, Object, Relocation, ResolvedRelocation, SectionKind, Symbol, SymbolFlag, - SymbolKind, + SymbolKind, read::get_section_base_name, }, }; @@ -810,10 +810,8 @@ where fn symbol_section<'obj>(obj: &'obj Object, symbol: &Symbol) -> Option<(&'obj str, SectionKind)> { if let Some(section) = symbol.section.and_then(|section_idx| obj.sections.get(section_idx)) { - // Match x86 .rdata$r against .rdata$rs - let section_name = - section.name.split_once('$').map_or(section.name.as_str(), |(prefix, _)| prefix); - Some((section_name, section.kind)) + let section_base_name = get_section_base_name(section); + Some((section_base_name, section.kind)) } else if symbol.flags.contains(SymbolFlag::Common) { Some((".comm", SectionKind::Common)) } else { diff --git a/objdiff-core/src/obj/read.rs b/objdiff-core/src/obj/read.rs index 51a536ce..49ec2c3d 100644 --- a/objdiff-core/src/obj/read.rs +++ b/objdiff-core/src/obj/read.rs @@ -89,15 +89,17 @@ fn get_normalized_symbol_name(name: &str) -> Option { } } -/// Check if a symbol's name is entirely compiler-generated, such as @1234 or _$E1234. +/// Check if a symbol's name is entirely compiler-generated (e.g. for a literal). /// This enables pairing these symbols up by their value instead of their name. fn is_symbol_name_compiler_generated(name: &str) -> bool { if name.starts_with('@') && name[1..].chars().all(char::is_numeric) { - // Exclude @stringBase0, @GUARD@, etc. + // Match Metrowerks @1234 against @2345 return true; - } else if (name.starts_with("_$E") || name.starts_with("$LC")) - && name[3..].chars().all(char::is_numeric) - { + } else if name.starts_with("_$E") && name[3..].chars().all(char::is_numeric) { + // Match MSVC _$E1234 against _$E2345 + return true; + } else if name.starts_with("$LC") && name[3..].chars().all(char::is_numeric) { + // Match GCC $LC1234 against $LC2345 return true; } false @@ -926,6 +928,17 @@ fn parse_line_info_coff( Ok(()) } +pub fn get_section_base_name(section: &Section) -> &str { + // Match MSVC x86 .rdata$r against .rdata$rs + // Match GCC i._ZN14class_00acb578C1Ev against i [combined] + section + .name + .get(1..) + .and_then(|s| s.rfind(['$', '.'])) + .and_then(|i| section.name.get(..i + 1)) + .unwrap_or(§ion.name) +} + fn combine_sections( sections: &mut [Section], symbols: &mut [Symbol], @@ -934,12 +947,7 @@ fn combine_sections( let mut data_sections = BTreeMap::>::new(); let mut text_sections = BTreeMap::>::new(); for (i, section) in sections.iter().enumerate() { - let base_name = section - .name - .get(1..) - .and_then(|s| s.rfind(['$', '.'])) - .and_then(|i| section.name.get(..i + 1)) - .unwrap_or(§ion.name); + let base_name = get_section_base_name(section); match section.kind { SectionKind::Data | SectionKind::Bss => { data_sections.entry(base_name.to_string()).or_default().push(i);