-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Labels
area-System.Reflection.Emitbughelp wanted[up-for-grabs] Good issue for external contributors[up-for-grabs] Good issue for external contributorsin-prThere is an active PR which will close this issue when it is mergedThere is an active PR which will close this issue when it is merged
Milestone
Description
Description
Field offsets aren't being set in the IL for types with an offset of zero. This causes the types to fail to load at runtime.
The cause, as far as I can tell, seems to be from lines 641 in the WriteFields function in ModuleBuilderImpl.cs
if (field._offset > 0 && (typeBuilder.Attributes & TypeAttributes.ExplicitLayout) != 0)
{
AddFieldLayout(handle, field._offset);
}
Reproduction Steps
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Loader;
PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly);
ModuleBuilder mob = ab.DefineDynamicModule("MyModule");
TypeBuilder exp = mob.DefineType("ExplicitLayoutType", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.ExplicitLayout, typeof(ValueType), 8);
var f1 = exp.DefineField("first", typeof(int), FieldAttributes.Public);
f1.SetOffset(0);
var f2 = exp.DefineField("second", typeof(int), FieldAttributes.Public);
f2.SetOffset(4);
exp.CreateType();
TypeBuilder tb = mob.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
tb.DefineField("structfield", exp, FieldAttributes.Public | FieldAttributes.Static);
MethodBuilder meb = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static,
typeof(int), new Type[] { typeof(int), typeof(int) });
ILGenerator il = meb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ret);
tb.CreateType();
using var stream = new MemoryStream();
ab.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(stream);
MethodInfo method = assembly.GetType("MyType").GetMethod("SumMethod");
Console.WriteLine(method.Invoke(null, new object[] { 5, 10 }));Expected behavior
Type loads, program prints 15.
Actual behavior
Unhandled exception. System.TypeLoadException: Could not load type 'ExplicitLayoutType' from assembly 'MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because field 'first' was not given an explicit offset.
at System.Reflection.RuntimeAssembly.GetTypeCore(QCallAssembly assembly, String typeName, ReadOnlySpan`1 nestedTypeNames, Int32 nestedTypeNamesLength, ObjectHandleOnStack retType)
at System.Reflection.RuntimeAssembly.GetTypeCore(String typeName, ReadOnlySpan`1 nestedTypeNames, Boolean throwOnError, Boolean ignoreCase)
at System.Reflection.TypeNameResolver.GetType(String escapedTypeName, ReadOnlySpan`1 nestedTypeNames, TypeName parsedName)
at System.Reflection.TypeNameResolver.GetSimpleType(TypeName typeName)
at System.Reflection.TypeNameResolver.Resolve(TypeName typeName)
at System.Reflection.TypeNameResolver.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Assembly topLevelAssembly)
at Program.<Main>$(String[] args) in Program.cs:line 32
Regression?
No response
Known Workarounds
No response
Configuration
Arch Linux x64, dotnet 9.0.100-rc.1.24381.3
Other information
No response
Metadata
Metadata
Assignees
Labels
area-System.Reflection.Emitbughelp wanted[up-for-grabs] Good issue for external contributors[up-for-grabs] Good issue for external contributorsin-prThere is an active PR which will close this issue when it is mergedThere is an active PR which will close this issue when it is merged