@@ -40,6 +40,7 @@ fn map_section_kind(section: &object::Section) -> SectionKind {
4040/// e.g. symbol$1234 and symbol$2345 will both be replaced with symbol$0000 internally.
4141fn get_normalized_symbol_name ( name : & str ) -> Option < String > {
4242 const DUMMY_UNIQUE_ID : & str = "0000" ;
43+ const DUMMY_UNIQUE_MSVC_ID : & str = "00000000" ;
4344 if let Some ( ( prefix, suffix) ) = name. split_once ( "@class$" )
4445 && let Some ( idx) = suffix. chars ( ) . position ( |c| !c. is_numeric ( ) )
4546 && idx > 0
@@ -59,6 +60,26 @@ fn get_normalized_symbol_name(name: &str) -> Option<String> {
5960 {
6061 // Match GCC symbol.1234 against symbol.2345
6162 Some ( format ! ( "{prefix}.{DUMMY_UNIQUE_ID}" ) )
63+ } else if name. starts_with ( '?' ) {
64+ // Match MSVC anonymous class symbol names, ignoring the unique ID.
65+ // e.g. ?CheckContextOr@?A0x24773155@@YA_NPBVDataArray@@@Z
66+ // and: ?CheckContextOr@?A0xddf6240c@@YA_NPBVDataArray@@@Z
67+ let mut name_str = String :: from ( name) ;
68+ let anon_indices: Vec < usize > = name_str. match_indices ( "?A0x" ) . map ( |( idx, _) | idx) . collect ( ) ;
69+ if !anon_indices. is_empty ( ) {
70+ for idx in anon_indices {
71+ // the str sequence we're looking for is: ?A0xXXXXXXXX@@
72+ if u32:: from_str_radix ( & name_str[ idx + 4 ..idx + 12 ] , 16 ) . is_ok ( )
73+ && & name_str[ idx + 12 ..idx + 14 ] == "@@"
74+ {
75+ // if the two above checks passed, we're good to replace the hash
76+ name_str. replace_range ( idx + 4 ..idx + 12 , DUMMY_UNIQUE_MSVC_ID ) ;
77+ }
78+ }
79+ Some ( name_str)
80+ } else {
81+ None
82+ }
6283 } else {
6384 None
6485 }
0 commit comments