Skip to content

Commit dabfa4b

Browse files
authored
GCC: Fix "Instruction count mismatch" when combining text sections (#397)
1 parent ae39329 commit dabfa4b

3 files changed

Lines changed: 25 additions & 19 deletions

File tree

‎objdiff-core/src/arch/ppc/mod.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,10 @@ impl Arch for ArchPpc {
364364
bytes: &[u8],
365365
) -> Option<DataType> {
366366
if reloc.is_some_and(|r| {
367-
r.symbol.name.starts_with("@stringBase")
368-
|| r.symbol.name.starts_with("@wstringBase")
367+
r.symbol.name.starts_with("@stringBase") // MWCC
368+
|| r.symbol.name.starts_with("@wstringBase") // MWCC
369369
|| r.symbol.name.starts_with("$SG")
370-
|| r.symbol.demangled_name == Some("`string'".to_string())
370+
|| r.symbol.name.starts_with("??_C") // MSVC
371371
}) {
372372
// Compiler-generated symbol name for a string or a pool of strings.
373373
return Some(DataType::String);

‎objdiff-core/src/diff/mod.rs‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{
1818
},
1919
obj::{
2020
InstructionRef, Object, Relocation, ResolvedRelocation, SectionKind, Symbol, SymbolFlag,
21-
SymbolKind,
21+
SymbolKind, read::get_section_base_name,
2222
},
2323
};
2424

@@ -810,10 +810,8 @@ where
810810

811811
fn symbol_section<'obj>(obj: &'obj Object, symbol: &Symbol) -> Option<(&'obj str, SectionKind)> {
812812
if let Some(section) = symbol.section.and_then(|section_idx| obj.sections.get(section_idx)) {
813-
// Match x86 .rdata$r against .rdata$rs
814-
let section_name =
815-
section.name.split_once('$').map_or(section.name.as_str(), |(prefix, _)| prefix);
816-
Some((section_name, section.kind))
813+
let section_base_name = get_section_base_name(section);
814+
Some((section_base_name, section.kind))
817815
} else if symbol.flags.contains(SymbolFlag::Common) {
818816
Some((".comm", SectionKind::Common))
819817
} else {

‎objdiff-core/src/obj/read.rs‎

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,17 @@ fn get_normalized_symbol_name(name: &str) -> Option<String> {
8989
}
9090
}
9191

92-
/// Check if a symbol's name is entirely compiler-generated, such as @1234 or _$E1234.
92+
/// Check if a symbol's name is entirely compiler-generated (e.g. for a literal).
9393
/// This enables pairing these symbols up by their value instead of their name.
9494
fn is_symbol_name_compiler_generated(name: &str) -> bool {
9595
if name.starts_with('@') && name[1..].chars().all(char::is_numeric) {
96-
// Exclude @stringBase0, @GUARD@, etc.
96+
// Match Metrowerks @1234 against @2345
9797
return true;
98-
} else if (name.starts_with("_$E") || name.starts_with("$LC"))
99-
&& name[3..].chars().all(char::is_numeric)
100-
{
98+
} else if name.starts_with("_$E") && name[3..].chars().all(char::is_numeric) {
99+
// Match MSVC _$E1234 against _$E2345
100+
return true;
101+
} else if name.starts_with("$LC") && name[3..].chars().all(char::is_numeric) {
102+
// Match GCC $LC1234 against $LC2345
101103
return true;
102104
}
103105
false
@@ -926,6 +928,17 @@ fn parse_line_info_coff(
926928
Ok(())
927929
}
928930

931+
pub fn get_section_base_name(section: &Section) -> &str {
932+
// Match MSVC x86 .rdata$r against .rdata$rs
933+
// Match GCC i._ZN14class_00acb578C1Ev against i [combined]
934+
section
935+
.name
936+
.get(1..)
937+
.and_then(|s| s.rfind(['$', '.']))
938+
.and_then(|i| section.name.get(..i + 1))
939+
.unwrap_or(&section.name)
940+
}
941+
929942
fn combine_sections(
930943
sections: &mut [Section],
931944
symbols: &mut [Symbol],
@@ -934,12 +947,7 @@ fn combine_sections(
934947
let mut data_sections = BTreeMap::<String, Vec<usize>>::new();
935948
let mut text_sections = BTreeMap::<String, Vec<usize>>::new();
936949
for (i, section) in sections.iter().enumerate() {
937-
let base_name = section
938-
.name
939-
.get(1..)
940-
.and_then(|s| s.rfind(['$', '.']))
941-
.and_then(|i| section.name.get(..i + 1))
942-
.unwrap_or(&section.name);
950+
let base_name = get_section_base_name(section);
943951
match section.kind {
944952
SectionKind::Data | SectionKind::Bss => {
945953
data_sections.entry(base_name.to_string()).or_default().push(i);

0 commit comments

Comments
 (0)