Skip to content

Commit 69045ad

Browse files
authored
Set AssemblyName.ProcessorArchitecture for compatibility. (#80581)
* Set AssemblyName.ProcessorArchitecture for compatibility. * Simplified ProcArch computation.
1 parent 19fc478 commit 69045ad

3 files changed

Lines changed: 73 additions & 31 deletions

File tree

src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -106,46 +106,41 @@ internal AssemblyNameFlags RawFlags
106106
internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm)
107107
{
108108
#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete
109-
ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _flags);
109+
ProcessorArchitecture = CalculateProcArch(pek, ifm, _flags);
110110
#pragma warning restore SYSLIB0037
111111
}
112112

113-
private static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags)
113+
private static ProcessorArchitecture CalculateProcArch(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags aFlags)
114114
{
115-
if (((uint)flags & 0xF0) == 0x70)
115+
// 0x70 specifies "reference assembly".
116+
// For these, CLR wants to return None as arch so they can be always loaded, regardless of process type.
117+
if (((uint)aFlags & 0xF0) == 0x70)
116118
return ProcessorArchitecture.None;
117119

118-
if ((pek & PortableExecutableKinds.PE32Plus) == PortableExecutableKinds.PE32Plus)
120+
switch (ifm)
119121
{
120-
switch (ifm)
121-
{
122-
case ImageFileMachine.IA64:
123-
return ProcessorArchitecture.IA64;
124-
case ImageFileMachine.AMD64:
125-
return ProcessorArchitecture.Amd64;
126-
case ImageFileMachine.I386:
127-
if ((pek & PortableExecutableKinds.ILOnly) == PortableExecutableKinds.ILOnly)
122+
case ImageFileMachine.IA64:
123+
return ProcessorArchitecture.IA64;
124+
case ImageFileMachine.ARM:
125+
return ProcessorArchitecture.Arm;
126+
case ImageFileMachine.AMD64:
127+
return ProcessorArchitecture.Amd64;
128+
case ImageFileMachine.I386:
129+
{
130+
if ((pek & PortableExecutableKinds.ILOnly) != 0 &&
131+
(pek & PortableExecutableKinds.Required32Bit) == 0)
132+
{
133+
// platform neutral.
128134
return ProcessorArchitecture.MSIL;
129-
break;
130-
}
131-
}
132-
else
133-
{
134-
if (ifm == ImageFileMachine.I386)
135-
{
136-
if ((pek & PortableExecutableKinds.Required32Bit) == PortableExecutableKinds.Required32Bit)
137-
return ProcessorArchitecture.X86;
135+
}
138136

139-
if ((pek & PortableExecutableKinds.ILOnly) == PortableExecutableKinds.ILOnly)
140-
return ProcessorArchitecture.MSIL;
141-
142-
return ProcessorArchitecture.X86;
143-
}
144-
if (ifm == ImageFileMachine.ARM)
145-
{
146-
return ProcessorArchitecture.Arm;
147-
}
137+
// requires x86
138+
return ProcessorArchitecture.X86;
139+
}
148140
}
141+
142+
// ProcessorArchitecture is a legacy API and does not cover other Machine kinds.
143+
// For example ARM64 is not expressible
149144
return ProcessorArchitecture.None;
150145
}
151146

src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.netstandard.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ public static unsafe AssemblyName GetAssemblyName(string assemblyFile)
8585
peReader = new PEReader((byte*)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength);
8686
MetadataReader mdReader = peReader.GetMetadataReader(MetadataReaderOptions.None);
8787
AssemblyName assemblyName = mdReader.GetAssemblyDefinition().GetAssemblyName();
88+
89+
AssemblyFlags aFlags = mdReader.AssemblyTable.GetFlags();
90+
#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete
91+
assemblyName.ProcessorArchitecture = CalculateProcArch(peReader, aFlags);
92+
#pragma warning restore SYSLIB0037
93+
8894
return assemblyName;
8995
}
9096
finally
@@ -101,6 +107,42 @@ public static unsafe AssemblyName GetAssemblyName(string assemblyFile)
101107
}
102108
}
103109

110+
private static ProcessorArchitecture CalculateProcArch(PEReader peReader, AssemblyFlags aFlags)
111+
{
112+
// 0x70 specifies "reference assembly".
113+
// For these, CLR wants to return None as arch so they can be always loaded, regardless of process type.
114+
if (((uint)aFlags & 0xF0) == 0x70)
115+
return ProcessorArchitecture.None;
116+
117+
PEHeaders peHeaders = peReader.PEHeaders;
118+
switch (peHeaders.CoffHeader.Machine)
119+
{
120+
case Machine.IA64:
121+
return ProcessorArchitecture.IA64;
122+
case Machine.Arm:
123+
return ProcessorArchitecture.Arm;
124+
case Machine.Amd64:
125+
return ProcessorArchitecture.Amd64;
126+
case Machine.I386:
127+
{
128+
CorFlags flags = peHeaders.CorHeader!.Flags;
129+
if ((flags & CorFlags.ILOnly) != 0 &&
130+
(flags & CorFlags.Requires32Bit) == 0)
131+
{
132+
// platform neutral.
133+
return ProcessorArchitecture.MSIL;
134+
}
135+
136+
// requires x86
137+
return ProcessorArchitecture.X86;
138+
}
139+
}
140+
141+
// ProcessorArchitecture is a legacy API and does not cover other Machine kinds.
142+
// For example ARM64 is not expressible
143+
return ProcessorArchitecture.None;
144+
}
145+
104146
private static AssemblyNameFlags GetAssemblyNameFlags(AssemblyFlags flags)
105147
{
106148
AssemblyNameFlags assemblyNameFlags = AssemblyNameFlags.None;

src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3091,7 +3091,12 @@ public void GetAssemblyName()
30913091
if (PlatformDetection.HasAssemblyFiles)
30923092
{
30933093
Assembly a = typeof(MetadataReaderTests).Assembly;
3094-
Assert.Equal(new AssemblyName(a.FullName).ToString(), MetadataReader.GetAssemblyName(AssemblyPathHelper.GetAssemblyLocation(a)).ToString());
3094+
AssemblyName name = MetadataReader.GetAssemblyName(AssemblyPathHelper.GetAssemblyLocation(a));
3095+
Assert.Equal(new AssemblyName(a.FullName).ToString(), name.ToString());
3096+
3097+
#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete
3098+
Assert.Equal(ProcessorArchitecture.MSIL, name.ProcessorArchitecture);
3099+
#pragma warning restore SYSLIB0037
30953100
}
30963101
}
30973102
}

0 commit comments

Comments
 (0)