Lokad / ILPack

Serialize .NET Core assemblies

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support entry-point method and executable assemblies

osman-turan opened this issue · comments

Initial code had some problems to support executable assemblies (e.g. console applications). The main reason was we need to know entry-point method handle ahead of its serialization to able to serialize <Module> type as first type in the assembly. See:

// Add "<Module>" type definition *before* any type definition.
//
// TODO: [osman] methodList argument should be as following:
//
// methodList: entryPoint.IsNil ? MetadataTokens.MethodDefinitionHandle(1) : entryPoint
//
// But, in order to work above code, we need to serialize
// entry point *without* serializing any type definition.
// This is not needed for libraries since they don't have any entry point.
_metadata.Builder.AddTypeDefinition(
default,
default,
_metadata.GetOrAddString("<Module>"),
default,
MetadataTokens.FieldDefinitionHandle(1),
MetadataTokens.MethodDefinitionHandle(1));

With #31, we could reserve metadata tokens prior to serialization. So, this could help us to support executable assemblies.

I see that this issue is still open. Where would you suggest I go reading to get my head around this issue?

@luhis Thanks a lot for your feedback. You have the SandboxSubject.csproj in the solution that let you test a target of your choice, for example an executable. Don't hesitate to submit if PR if you can. We don't have resources for this project right now, but any help is highly appreciated.

This would be a very useful feature to have.

I just started taking a shot at it, and have made a little progress. Unfortunately the .entrypoint is being added to the constructor, not the actual entrypoint.

.class private auto ansi Program
	extends [System.Private.CoreLib]System.Object
{
	// Methods
	.method public specialname rtspecialname 
		instance void .ctor () cil managed 
	{
		// Method begins at RVA 0x2050
		// Code size 7 (0x7)
		.maxstack 8
		.entrypoint

		IL_0000: ldarg.0
		IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
		IL_0006: ret
	} // end of method Program::.ctor

	.method public static 
		void Main () cil managed 
	{
		// Method begins at RVA 0x2058
		// Code size 11 (0xb)
		.maxstack 8

		IL_0000: ldstr "Hello World!"
		IL_0005: call void [System.Console]System.Console::WriteLine(string)
		IL_000a: ret
	} // end of method Program::Main

} // end of class Program

I suspect this has something to do with @osman-turan 's comment:

"...we need to serialize entry point without serializing any type definition."

I'm afraid I'm not certain what that implies - this is a little new to me. Any clarification or elaboration would be greatly appreciated.

@jwhitehorn While defining the entry point, we need a method handle. I think you use ctor's handle by mistake (or more likely you use a constant method handle that's coincidently resolved to the ctor handle at the method serializing step due to its serialization order). My initial post describes more about the problem that I described in the code comments. The most important part is:

The main reason was we need to know entry-point method handle ahead of its serialization to able to serialize type as first type in the assembly.

So we need to "reserve" a method handle for entry-point "without" actually serializing the method (otherwise .NET Core will complain). Then we should feed this reserved handle to the entry-point definition. And finally, we can serialize the entry-point method handle with the previously reserved method handle.

I hope, it's a bit more clear now 🙂

Hi folks! Great library.

I'm trying to figure out how to set the entry point of an AssemblyBuilder instance. Is it possible with .NET Core/5+?