MichalStrehovsky / zerosharp

Demo of the potential of C# for systems programming with the .NET native ahead-of-time compilation technology.
2.02k stars 105 forks source link

Diagnosing EFI attempted imports #42

Closed ayesaac closed 1 year ago

ayesaac commented 1 year ago

Getting exports and import libraries are not supported with /SUBSYSTEM:EFI_APPLICATION when attempting to invoke a method/prop on an interface. As with, say, allocation (new object()), it's almost certainly that there's some missing code (eg an export for RhpNewFast) I need to add, and the compiler is trying to pull it in from the runtime because it's not present, but unlike w/ allocation, I can't for the life of me figure out what I need to add.

Partly the question is what I might be missing, but equally, is there any good way of telling what the compiler is actually trying to pull in? Changing the verbosity on the dotnet publish doesn't seem to yield any useful information.

For context:

interface IFoo
{
  void Bar();
}

class Foo1 : IFoo
{
  public void Bar() { }
}

class Foo2: IFoo
{
  public void Bar() { }
}

static class Indirection
{
  private ulong _counter;

  public static IFoo GetFoo() => _counter++ % 2 is 0 ? new Foo1() : new Foo2()
}

I can compile:

IFoo foo = new Foo1();
foo.Bar();
IFoo baz = new Foo2();
baz.Bar();

Presumably as the interface is just being optimized away.

But

var foos = new IFoo[] { new Foo1(), new Foo2() };
for (var i = 0; i < foos.Length; ++i)
{
  foos[i].Foo();
}

or

var foo = Indirection.GetFoo();
foo.Foo();

Results in the compilation error.

I also get

Runtime.WorkstationGC.lib(thread.cpp.obj) : error LNK2005: RhpReversePInvoke already defined in Project.obj [F:\projects\Project\src\Project\Project.csproj]
Runtime.WorkstationGC.lib(thread.cpp.obj) : error LNK2005: RhpReversePInvokeReturn already defined in Project.obj [F:\projects\Project\src\Project\Project.csproj]
Runtime.WorkstationGC.lib(EHHelpers.cpp.obj) : error LNK2005: RhpFallbackFailFast already defined in Project.obj [F:\projects\Project\src\Project\Project.csproj]
Runtime.WorkstationGC.lib(WriteBarriers.asm.obj) : error LNK2005: RhpCheckedAssignRef already defined in Project.obj [F:\projects\Project\src\Project\Project.csproj]
Runtime.WorkstationGC.lib(WriteBarriers.asm.obj) : error LNK2005: RhpAssignRef already defined in Project.obj [F:\projects\Project\src\Project\Project.csproj]
Runtime.WorkstationGC.lib(WriteBarriers.asm.obj) : error LNK2005: RhpByRefAssignRef already defined in Project.obj [F:\projects\Project\src\Project\Project.csproj]
LIBCMT.lib(gs_cookie.obj) : error LNK2005: __security_cookie already defined in Project.obj [F:\projects\Project\src\Project\Project.csproj]

Because those are all explicitly defined, but I'm working under the assumption those will go away if I add whatever it is it's trying to import.

Pretty sure it's down to the method invocation, as I can, for example, create an array of IFoos, Unsafe.As<IFoo, IntPtr>, and print out the pointers.

Cheers!

MichalStrehovsky commented 1 year ago

Use the build.cmd workflow: https://github.com/MichalStrehovsky/zerosharp/blob/master/efi-no-runtime/build.cmd

The project files are a giant hack and cause more trouble than they're worth.

build.cmd will not try to pull in Runtime.WorkstationGC.lib and you get a much better error reporting.

Alternatively, give bflat a try: https://github.com/bflattened/bflat

ayesaac commented 1 year ago

Am trying out bflat, much preferring this setup, cheers!