diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs index 6d02f9d8ed6f81..48396e6dd42ef9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs @@ -106,46 +106,41 @@ internal AssemblyNameFlags RawFlags internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm) { #pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _flags); + ProcessorArchitecture = CalculateProcArch(pek, ifm, _flags); #pragma warning restore SYSLIB0037 } - private static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags) + private static ProcessorArchitecture CalculateProcArch(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags aFlags) { - if (((uint)flags & 0xF0) == 0x70) + // 0x70 specifies "reference assembly". + // For these, CLR wants to return None as arch so they can be always loaded, regardless of process type. + if (((uint)aFlags & 0xF0) == 0x70) return ProcessorArchitecture.None; - if ((pek & PortableExecutableKinds.PE32Plus) == PortableExecutableKinds.PE32Plus) + switch (ifm) { - switch (ifm) - { - case ImageFileMachine.IA64: - return ProcessorArchitecture.IA64; - case ImageFileMachine.AMD64: - return ProcessorArchitecture.Amd64; - case ImageFileMachine.I386: - if ((pek & PortableExecutableKinds.ILOnly) == PortableExecutableKinds.ILOnly) + case ImageFileMachine.IA64: + return ProcessorArchitecture.IA64; + case ImageFileMachine.ARM: + return ProcessorArchitecture.Arm; + case ImageFileMachine.AMD64: + return ProcessorArchitecture.Amd64; + case ImageFileMachine.I386: + { + if ((pek & PortableExecutableKinds.ILOnly) != 0 && + (pek & PortableExecutableKinds.Required32Bit) == 0) + { + // platform neutral. return ProcessorArchitecture.MSIL; - break; - } - } - else - { - if (ifm == ImageFileMachine.I386) - { - if ((pek & PortableExecutableKinds.Required32Bit) == PortableExecutableKinds.Required32Bit) - return ProcessorArchitecture.X86; + } - if ((pek & PortableExecutableKinds.ILOnly) == PortableExecutableKinds.ILOnly) - return ProcessorArchitecture.MSIL; - - return ProcessorArchitecture.X86; - } - if (ifm == ImageFileMachine.ARM) - { - return ProcessorArchitecture.Arm; - } + // requires x86 + return ProcessorArchitecture.X86; + } } + + // ProcessorArchitecture is a legacy API and does not cover other Machine kinds. + // For example ARM64 is not expressible return ProcessorArchitecture.None; } diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs index a11a8fcacda4e5..f33c0455ee2dbc 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs @@ -85,6 +85,12 @@ public static unsafe AssemblyName GetAssemblyName(string assemblyFile) peReader = new PEReader((byte*)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength); MetadataReader mdReader = peReader.GetMetadataReader(MetadataReaderOptions.None); AssemblyName assemblyName = mdReader.GetAssemblyDefinition().GetAssemblyName(); + + AssemblyFlags aFlags = mdReader.AssemblyTable.GetFlags(); +#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete + assemblyName.ProcessorArchitecture = CalculateProcArch(peReader, aFlags); +#pragma warning restore SYSLIB0037 + return assemblyName; } finally @@ -101,6 +107,42 @@ public static unsafe AssemblyName GetAssemblyName(string assemblyFile) } } + private static ProcessorArchitecture CalculateProcArch(PEReader peReader, AssemblyFlags aFlags) + { + // 0x70 specifies "reference assembly". + // For these, CLR wants to return None as arch so they can be always loaded, regardless of process type. + if (((uint)aFlags & 0xF0) == 0x70) + return ProcessorArchitecture.None; + + PEHeaders peHeaders = peReader.PEHeaders; + switch (peHeaders.CoffHeader.Machine) + { + case Machine.IA64: + return ProcessorArchitecture.IA64; + case Machine.Arm: + return ProcessorArchitecture.Arm; + case Machine.Amd64: + return ProcessorArchitecture.Amd64; + case Machine.I386: + { + CorFlags flags = peHeaders.CorHeader!.Flags; + if ((flags & CorFlags.ILOnly) != 0 && + (flags & CorFlags.Requires32Bit) == 0) + { + // platform neutral. + return ProcessorArchitecture.MSIL; + } + + // requires x86 + return ProcessorArchitecture.X86; + } + } + + // ProcessorArchitecture is a legacy API and does not cover other Machine kinds. + // For example ARM64 is not expressible + return ProcessorArchitecture.None; + } + private static AssemblyNameFlags GetAssemblyNameFlags(AssemblyFlags flags) { AssemblyNameFlags assemblyNameFlags = AssemblyNameFlags.None; diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs index dad27d509ac645..a30606af963bf8 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs @@ -3091,7 +3091,12 @@ public void GetAssemblyName() if (PlatformDetection.HasAssemblyFiles) { Assembly a = typeof(MetadataReaderTests).Assembly; - Assert.Equal(new AssemblyName(a.FullName).ToString(), MetadataReader.GetAssemblyName(AssemblyPathHelper.GetAssemblyLocation(a)).ToString()); + AssemblyName name = MetadataReader.GetAssemblyName(AssemblyPathHelper.GetAssemblyLocation(a)); + Assert.Equal(new AssemblyName(a.FullName).ToString(), name.ToString()); + +#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete + Assert.Equal(ProcessorArchitecture.MSIL, name.ProcessorArchitecture); +#pragma warning restore SYSLIB0037 } } }