@@ -305,7 +305,7 @@ public virtual AssemblyNameReference ImportReference (SR.AssemblyName name)
305
305
Mixin . CheckName ( name ) ;
306
306
307
307
AssemblyNameReference reference ;
308
- if ( TryGetAssemblyNameReference ( name , out reference ) )
308
+ if ( Mixin . TryGetAssemblyNameReference ( module , name , out reference ) )
309
309
return reference ;
310
310
311
311
reference = new AssemblyNameReference ( name . Name , name . Version )
@@ -320,23 +320,6 @@ public virtual AssemblyNameReference ImportReference (SR.AssemblyName name)
320
320
return reference ;
321
321
}
322
322
323
- bool TryGetAssemblyNameReference ( SR . AssemblyName name , out AssemblyNameReference assembly_reference )
324
- {
325
- var references = module . AssemblyReferences ;
326
-
327
- for ( int i = 0 ; i < references . Count ; i ++ ) {
328
- var reference = references [ i ] ;
329
- if ( name . FullName != reference . FullName ) // TODO compare field by field
330
- continue ;
331
-
332
- assembly_reference = reference ;
333
- return true ;
334
- }
335
-
336
- assembly_reference = null ;
337
- return false ;
338
- }
339
-
340
323
FieldReference ImportField ( SR . FieldInfo field , ImportGenericContext context )
341
324
{
342
325
var declaring_type = ImportType ( field . DeclaringType , context ) ;
@@ -756,57 +739,307 @@ public static void CheckModule (ModuleDefinition module)
756
739
757
740
public static bool TryGetAssemblyNameReference ( this ModuleDefinition module , AssemblyNameReference name_reference , out AssemblyNameReference assembly_reference )
758
741
{
759
- var references = module . AssemblyReferences ;
742
+ return TryGetAssemblyNameReference ( module , ( AssemblyWrapper ) name_reference , out assembly_reference ) ;
743
+ }
760
744
761
- for ( int i = 0 ; i < references . Count ; i ++ ) {
762
- var reference = references [ i ] ;
763
- if ( ! Equals ( name_reference , reference ) )
764
- continue ;
745
+ public static bool TryGetAssemblyNameReference ( this ModuleDefinition module , SR . AssemblyName name_reference , out AssemblyNameReference assembly_reference )
746
+ {
747
+ return TryGetAssemblyNameReference ( module , ( AssemblyWrapper ) name_reference , out assembly_reference ) ;
748
+ }
765
749
766
- assembly_reference = reference ;
750
+ static bool TryGetAssemblyNameReference ( this ModuleDefinition module , AssemblyWrapper name_reference , out AssemblyNameReference assembly_reference )
751
+ {
752
+ // Try to resolve the assembly using direct reference first
753
+ if ( module . TryGetDirectAssemblyNameReference ( name_reference , out assembly_reference ) ) {
767
754
return true ;
768
755
}
769
756
757
+ // If direct resolution fails, try to resolve using forwarded types
758
+ if ( module . TryGetForwardedAssemblyNameReference ( name_reference , out assembly_reference , new HashSet < string > ( ) ) ) {
759
+ return true ;
760
+ }
761
+
762
+ // As a fallback, if the assembly is still unresolved,
763
+ // check if it could be a system assembly like 'System.Private.CoreLib',
764
+ // which can be safely mapped to 'System.Runtime' in certain .NET platforms.
765
+ // This handles the internal details of .NET Core and .NET 5+,
766
+ // where 'System.Private.CoreLib' is the core library but it is not referenceable
767
+ // and 'System.Runtime' is the referenceable contract assembly.
768
+ if ( module . TryGetSystemAssemblyNameReference ( name_reference , out assembly_reference ) ) {
769
+ return true ;
770
+ }
771
+
772
+ // If resolution fails, set the output reference to null
770
773
assembly_reference = null ;
771
774
return false ;
772
775
}
773
776
774
- static bool Equals ( byte [ ] a , byte [ ] b )
777
+ static bool TryGetDirectAssemblyNameReference ( this ModuleDefinition module , AssemblyWrapper name_reference , out AssemblyNameReference assembly_reference )
775
778
{
776
- if ( ReferenceEquals ( a , b ) )
777
- return true ;
778
- if ( a == null )
779
- return false ;
780
- if ( a . Length != b . Length )
781
- return false ;
782
- for ( int i = 0 ; i < a . Length ; i ++ )
783
- if ( a [ i ] != b [ i ] )
784
- return false ;
785
- return true ;
779
+ // Check each assembly reference in the module for a match by full name
780
+ foreach ( var reference in module . AssemblyReferences ) {
781
+ if ( reference . FullName == name_reference . FullName ) {
782
+ assembly_reference = reference ;
783
+ return true ;
784
+ }
785
+ }
786
+
787
+ // If no direct reference is found, set the output reference to null
788
+ assembly_reference = null ;
789
+ return false ;
786
790
}
787
791
788
- static bool Equals < T > ( T a , T b ) where T : class , IEquatable < T >
792
+ static bool TryGetForwardedAssemblyNameReference (
793
+ this ModuleDefinition module ,
794
+ AssemblyWrapper name_reference ,
795
+ out AssemblyNameReference assembly_reference ,
796
+ HashSet < string > checked_assemblies )
789
797
{
790
- if ( ReferenceEquals ( a , b ) )
791
- return true ;
792
- if ( a == null )
793
- return false ;
794
- return a . Equals ( b ) ;
798
+ // Initialize the output parameter to null
799
+ assembly_reference = null ;
800
+
801
+ // Iterate through all assembly references
802
+ foreach ( var asm_ref in module . AssemblyReferences ) {
803
+ if ( ! checked_assemblies . Add ( asm_ref . FullName ) )
804
+ continue ;
805
+
806
+ AssemblyDefinition resolved_assembly ;
807
+ try {
808
+ // Attempt to resolve the assembly reference
809
+ resolved_assembly = module . AssemblyResolver . Resolve ( asm_ref ) ;
810
+ }
811
+ catch ( AssemblyResolutionException ) {
812
+ // Skip the assembly if resolution fails
813
+ continue ;
814
+ }
815
+
816
+ // Check exported types for type forwarding within the assembly
817
+ foreach ( var module_def in resolved_assembly . Modules ) {
818
+ foreach ( var exported_type in module_def . ExportedTypes ) {
819
+ // Check if the exported type has a scope that matches the target assembly name
820
+ var scope = exported_type . Scope as AssemblyNameReference ;
821
+ if ( scope == null )
822
+ continue ;
823
+
824
+ if ( ! checked_assemblies . Add ( scope . FullName ) )
825
+ continue ;
826
+
827
+ if ( AssemblyWrapper . Equals ( scope , name_reference ) ) {
828
+ // If a match is found, return the assembly reference from which the type was forwarded
829
+ assembly_reference = asm_ref ;
830
+ return true ;
831
+ } else {
832
+ if ( TryGetForwardedAssemblyNameReference ( module , ( AssemblyWrapper ) scope , out assembly_reference , checked_assemblies ) )
833
+ return true ;
834
+ }
835
+ }
836
+ }
837
+ }
838
+
839
+ return false ;
795
840
}
796
841
797
- static bool Equals ( AssemblyNameReference a , AssemblyNameReference b )
842
+ static bool TryGetSystemAssemblyNameReference ( this ModuleDefinition module , AssemblyWrapper name_reference , out AssemblyNameReference assembly_reference )
798
843
{
799
- if ( ReferenceEquals ( a , b ) )
800
- return true ;
801
- if ( a . Name != b . Name )
802
- return false ;
803
- if ( ! Equals ( a . Version , b . Version ) )
844
+ assembly_reference = null ;
845
+
846
+ var possible_system_assemblies = new [ ] {
847
+ "System.Runtime" , // The main system assembly for .NET Core and .NET 5+
848
+ "mscorlib" , // The main system assembly for the .NET Framework
849
+ "netstandard" , // The pseudo-assembly for .NET Standard API surface
850
+
851
+ // Additional potential system assemblies used in specific contexts:
852
+ "System.Private.CoreLib" , // The implementation of the BCL in .NET Core and .NET 5+
853
+ "System" , // might be included if you are working with older versions of .NET Framework where it might be a system assembly
854
+ } ;
855
+
856
+ var core_libs = new List < AssemblyNameReference > ( ) ;
857
+ foreach ( var asm_ref in module . AssemblyReferences ) {
858
+ foreach ( var possible_system_assembly in possible_system_assemblies ) {
859
+ if ( string . Equals ( asm_ref . Name , possible_system_assembly , StringComparison . Ordinal ) ) {
860
+ core_libs . Add ( asm_ref ) ;
861
+ break ;
862
+ }
863
+ }
864
+ }
865
+
866
+ if ( core_libs . Count != 1 )
804
867
return false ;
805
- if ( a . Culture != b . Culture )
868
+
869
+ var core_lib = core_libs [ 0 ] ;
870
+ AssemblyDefinition resolved_core_lib ;
871
+
872
+ try {
873
+ resolved_core_lib = module . AssemblyResolver . Resolve ( core_lib ) ;
874
+ }
875
+ catch ( AssemblyResolutionException ) {
806
876
return false ;
807
- if ( ! Equals ( a . PublicKeyToken , b . PublicKeyToken ) )
877
+ }
878
+
879
+ if ( resolved_core_lib == null )
808
880
return false ;
809
- return true ;
881
+
882
+ TypeReference object_reference ;
883
+ foreach ( var module_def in resolved_core_lib . Modules ) {
884
+ if ( module_def . TryGetTypeReference ( typeof ( object ) . FullName , out object_reference ) ) {
885
+ assembly_reference = core_lib ;
886
+ return true ;
887
+ }
888
+
889
+ foreach ( var exported_type in module_def . ExportedTypes ) {
890
+ if ( string . Equals ( exported_type . FullName , typeof ( object ) . FullName , StringComparison . Ordinal ) ) {
891
+
892
+ var scope = exported_type . Scope as AssemblyNameReference ;
893
+ if ( scope != null ) {
894
+ foreach ( var possible_system_assembly in possible_system_assemblies ) {
895
+ if ( string . Equals ( scope . Name , possible_system_assembly , StringComparison . Ordinal ) ) {
896
+ assembly_reference = core_lib ;
897
+ return true ;
898
+ }
899
+ }
900
+ }
901
+ }
902
+ }
903
+ }
904
+
905
+ return false ;
906
+ }
907
+
908
+ sealed class AssemblyWrapper {
909
+ private readonly SR . AssemblyName assembly_name ;
910
+ private readonly AssemblyNameReference assembly_name_reference ;
911
+
912
+ public AssemblyWrapper ( SR . AssemblyName assembly_name )
913
+ {
914
+ CheckName ( assembly_name ) ;
915
+ this . assembly_name = assembly_name ;
916
+ }
917
+
918
+ public AssemblyWrapper ( AssemblyNameReference assembly_name_reference )
919
+ {
920
+ CheckName ( assembly_name_reference ) ;
921
+ this . assembly_name_reference = assembly_name_reference ;
922
+ }
923
+
924
+ public string FullName {
925
+ get {
926
+ if ( assembly_name == null ) {
927
+ return assembly_name_reference . FullName ;
928
+ } else {
929
+ return assembly_name . FullName ;
930
+ }
931
+ }
932
+ }
933
+
934
+ public string Name {
935
+ get {
936
+ if ( assembly_name == null ) {
937
+ return assembly_name_reference . Name ;
938
+ } else {
939
+ return assembly_name . Name ;
940
+ }
941
+ }
942
+ }
943
+
944
+ public Version Version {
945
+ get {
946
+ if ( assembly_name == null ) {
947
+ return assembly_name_reference . Version ;
948
+ } else {
949
+ return assembly_name . Version ;
950
+ }
951
+ }
952
+ }
953
+
954
+ public byte [ ] PublicKeyToken {
955
+ get {
956
+ if ( assembly_name == null ) {
957
+ return assembly_name_reference . PublicKeyToken ;
958
+ } else {
959
+ return assembly_name . GetPublicKeyToken ( ) ;
960
+ }
961
+ }
962
+ }
963
+
964
+ public string Culture {
965
+ get {
966
+ if ( assembly_name == null ) {
967
+ return assembly_name_reference . Culture ;
968
+ } else {
969
+ return assembly_name . CultureInfo . Name ;
970
+ }
971
+ }
972
+ }
973
+
974
+ public AssemblyNameReference GetAssemblyNameReference ( )
975
+ {
976
+ if ( this . assembly_name != null ) {
977
+ return new AssemblyNameReference ( this . assembly_name . Name , this . assembly_name . Version ) {
978
+ PublicKeyToken = this . assembly_name . GetPublicKeyToken ( ) ,
979
+ Culture = this . assembly_name . CultureInfo . Name ,
980
+ HashAlgorithm = ( AssemblyHashAlgorithm ) this . assembly_name . HashAlgorithm ,
981
+ } ;
982
+ } else {
983
+ return this . assembly_name_reference ;
984
+ }
985
+ }
986
+
987
+ public override string ToString ( )
988
+ {
989
+ return this . Name ;
990
+ }
991
+
992
+ public static bool Equals ( AssemblyWrapper a , AssemblyWrapper b )
993
+ {
994
+ if ( ReferenceEquals ( a , b ) )
995
+ return true ;
996
+ if ( a . assembly_name != null && ReferenceEquals ( a . assembly_name , b . assembly_name ) )
997
+ return true ;
998
+ if ( a . assembly_name_reference != null && ReferenceEquals ( a . assembly_name_reference , b . assembly_name_reference ) )
999
+ return true ;
1000
+ if ( a . Name != b . Name )
1001
+ return false ;
1002
+ if ( ! Equals ( a . Version , b . Version ) )
1003
+ return false ;
1004
+ if ( a . Culture != b . Culture )
1005
+ return false ;
1006
+ if ( ! Equals ( a . PublicKeyToken , b . PublicKeyToken ) )
1007
+ return false ;
1008
+ return true ;
1009
+ }
1010
+
1011
+ static bool Equals ( byte [ ] a , byte [ ] b )
1012
+ {
1013
+ if ( ReferenceEquals ( a , b ) )
1014
+ return true ;
1015
+ if ( a == null )
1016
+ return false ;
1017
+ if ( a . Length != b . Length )
1018
+ return false ;
1019
+ for ( int i = 0 ; i < a . Length ; i ++ )
1020
+ if ( a [ i ] != b [ i ] )
1021
+ return false ;
1022
+ return true ;
1023
+ }
1024
+
1025
+ static bool Equals < T > ( T a , T b ) where T : class , IEquatable < T >
1026
+ {
1027
+ if ( ReferenceEquals ( a , b ) )
1028
+ return true ;
1029
+ if ( a == null )
1030
+ return false ;
1031
+ return a . Equals ( b ) ;
1032
+ }
1033
+
1034
+ public static explicit operator AssemblyWrapper ( SR . AssemblyName assembly_name )
1035
+ {
1036
+ return new AssemblyWrapper ( assembly_name ) ;
1037
+ }
1038
+
1039
+ public static explicit operator AssemblyWrapper ( AssemblyNameReference assembly_name_reference )
1040
+ {
1041
+ return new AssemblyWrapper ( assembly_name_reference ) ;
1042
+ }
810
1043
}
811
1044
}
812
1045
}
0 commit comments