@@ -588,8 +588,8 @@ fn matching_symbols(
588
588
}
589
589
let symbol_match = SymbolMatch {
590
590
left : Some ( symbol_idx) ,
591
- right : find_symbol ( right, left, symbol , Some ( & right_used) ) ,
592
- prev : find_symbol ( prev, left, symbol , None ) ,
591
+ right : find_symbol ( right, left, symbol_idx , Some ( & right_used) ) ,
592
+ prev : find_symbol ( prev, left, symbol_idx , None ) ,
593
593
section_kind,
594
594
} ;
595
595
matches. push ( symbol_match) ;
@@ -613,7 +613,7 @@ fn matching_symbols(
613
613
matches. push ( SymbolMatch {
614
614
left : None ,
615
615
right : Some ( symbol_idx) ,
616
- prev : find_symbol ( prev, right, symbol , None ) ,
616
+ prev : find_symbol ( prev, right, symbol_idx , None ) ,
617
617
section_kind,
618
618
} ) ;
619
619
}
@@ -645,6 +645,13 @@ fn symbol_section<'obj>(obj: &'obj Object, symbol: &Symbol) -> Option<(&'obj str
645
645
}
646
646
}
647
647
648
+ fn symbol_section_name < ' obj > ( obj : & ' obj Object , symbol : & Symbol ) -> Option < & ' obj str > {
649
+ if let Some ( ( name, _kind) ) = symbol_section ( obj, symbol) {
650
+ return Some ( name) ;
651
+ }
652
+ None
653
+ }
654
+
648
655
fn symbol_section_kind ( obj : & Object , symbol : & Symbol ) -> SectionKind {
649
656
match symbol. section {
650
657
Some ( section_index) => obj. sections [ section_index] . kind ,
@@ -653,35 +660,81 @@ fn symbol_section_kind(obj: &Object, symbol: &Symbol) -> SectionKind {
653
660
}
654
661
}
655
662
663
+ /// Check if a symbol is a compiler-generated literal like @1234.
664
+ fn is_symbol_compiler_generated_literal ( symbol : & Symbol ) -> bool {
665
+ if !symbol. name . starts_with ( '@' ) {
666
+ return false ;
667
+ }
668
+ if !symbol. name [ 1 ..] . chars ( ) . all ( char:: is_numeric) {
669
+ // Exclude @stringBase0, @GUARD@, etc.
670
+ return false ;
671
+ }
672
+ return true ;
673
+ }
674
+
656
675
fn find_symbol (
657
676
obj : Option < & Object > ,
658
677
in_obj : & Object ,
659
- in_symbol : & Symbol ,
678
+ in_symbol_idx : usize ,
660
679
used : Option < & BTreeSet < usize > > ,
661
680
) -> Option < usize > {
681
+ let in_symbol = & in_obj. symbols [ in_symbol_idx] ;
662
682
let obj = obj?;
663
683
let ( section_name, section_kind) = symbol_section ( in_obj, in_symbol) ?;
664
- // Try to find an exact name match
665
- if let Some ( ( symbol_idx, _) ) = unmatched_symbols ( obj, used) . find ( |( _, symbol) | {
666
- symbol. name == in_symbol. name && symbol_section_kind ( obj, symbol) == section_kind
667
- } ) {
668
- return Some ( symbol_idx) ;
669
- }
684
+
670
685
// Match compiler-generated symbols against each other (e.g. @251 -> @60)
671
- // If they are at the same address in the same section
672
- if in_symbol . name . starts_with ( '@' )
686
+ // If they are in the same section and have the same value
687
+ if is_symbol_compiler_generated_literal ( in_symbol )
673
688
&& matches ! ( section_kind, SectionKind :: Data | SectionKind :: Bss )
674
- && let Some ( ( symbol_idx, _) ) = unmatched_symbols ( obj, used) . find ( |( _, symbol) | {
689
+ {
690
+ let mut closest_match_symbol_idx = None ;
691
+ let mut closest_match_percent = 0.0 ;
692
+ for ( symbol_idx, symbol) in unmatched_symbols ( obj, used) {
675
693
let Some ( section_index) = symbol. section else {
676
- return false ;
694
+ continue ;
677
695
} ;
678
- symbol. name . starts_with ( '@' )
679
- && symbol. address == in_symbol. address
680
- && obj. sections [ section_index] . name == section_name
681
- } )
682
- {
696
+ if obj. sections [ section_index] . name != section_name {
697
+ continue ;
698
+ }
699
+ if !is_symbol_compiler_generated_literal ( symbol) {
700
+ continue ;
701
+ }
702
+ match section_kind {
703
+ SectionKind :: Data => {
704
+ // For data, we try to pick the first symbol that matches 100%.
705
+ // If no symbol is a perfect match, pick whichever matches the closest.
706
+ if let Ok ( ( left_diff, _right_diff) ) =
707
+ diff_data_symbol ( in_obj, obj, in_symbol_idx, symbol_idx)
708
+ && let Some ( match_percent) = left_diff. match_percent
709
+ && match_percent > closest_match_percent
710
+ {
711
+ closest_match_symbol_idx = Some ( symbol_idx) ;
712
+ closest_match_percent = match_percent;
713
+ if match_percent == 100.0 {
714
+ break ;
715
+ }
716
+ }
717
+ }
718
+ SectionKind :: Bss => {
719
+ // For BSS, we simply pick the first symbol that has the exact matching size.
720
+ if in_symbol. size == symbol. size {
721
+ closest_match_symbol_idx = Some ( symbol_idx) ;
722
+ break ;
723
+ }
724
+ }
725
+ _ => unreachable ! ( ) ,
726
+ }
727
+ }
728
+ return closest_match_symbol_idx;
729
+ }
730
+
731
+ // Try to find an exact name match
732
+ if let Some ( ( symbol_idx, _) ) = unmatched_symbols ( obj, used) . find ( |( _, symbol) | {
733
+ symbol. name == in_symbol. name && symbol_section_kind ( obj, symbol) == section_kind
734
+ } ) {
683
735
return Some ( symbol_idx) ;
684
736
}
737
+
685
738
// Match Metrowerks symbol$1234 against symbol$2345
686
739
if let Some ( ( prefix, suffix) ) = in_symbol. name . split_once ( '$' ) {
687
740
if !suffix. chars ( ) . all ( char:: is_numeric) {
@@ -692,13 +745,15 @@ fn find_symbol(
692
745
prefix == p
693
746
&& s. chars ( ) . all ( char:: is_numeric)
694
747
&& symbol_section_kind ( obj, symbol) == section_kind
748
+ && symbol_section_name ( obj, symbol) == Some ( section_name)
695
749
} else {
696
750
false
697
751
}
698
752
} ) {
699
753
return Some ( symbol_idx) ;
700
754
}
701
755
}
756
+
702
757
None
703
758
}
704
759
0 commit comments