Skip to content

NativeModuleWriter - Could not create header #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
acizmarik opened this issue Sep 3, 2019 · 9 comments
Closed

NativeModuleWriter - Could not create header #305

acizmarik opened this issue Sep 3, 2019 · 9 comments

Comments

@acizmarik
Copy link

Currently native writer fails for some assemblies.
This is caused by an unimplemented feature at the end of CreateHeaderSection in class NativeModuleWriter:

    //TODO: Support this too
    throw new ModuleWriterException("Could not create header");

Reproduce issue

  1. Create clean console application using dotnet new console
  2. Publish with ubuntu RID, for example, dotnet publish --runtime ubuntu.18.04-x64
  3. Try to load published System.Private.CoreLib.dll and write it back to disk
    var module = AssemblyDef.Load("System.Private.CoreLib.dll");
    ((ModuleDefMD)module.ManifestModule).NativeWrite("System.Private.CorLib.dll-2");

Exprected result: Assembly is stored to disk
Actual result: An exception is thrown

dnlib.DotNet.Writer.ModuleWriterException: Could not create header
   at dnlib.DotNet.Writer.NativeModuleWriter.CreateHeaderSection(IChunk& extraHeaderData)
   at dnlib.DotNet.Writer.NativeModuleWriter.WriteFile()
   at dnlib.DotNet.Writer.NativeModuleWriter.WriteImpl()
   at dnlib.DotNet.Writer.ModuleWriterBase.Write(Stream dest)
   at dnlib.DotNet.Writer.ModuleWriterBase.Write(String fileName)

Is there any chance that this will be implemented?
Also let me know if you need additional info.

@0xd4d
Copy link
Collaborator

0xd4d commented Sep 4, 2019

Yes, this is an old todo.

That file is probably an R2R assembly (created by the crossgen tool), and you should probably just save it as a normal IL assembly, and optionally run crossgen on it again.

@0xd4d
Copy link
Collaborator

0xd4d commented Sep 4, 2019

If you save it as an IL assembly, you may need to clear the IL Library bit too.

@acizmarik
Copy link
Author

I tried setting IsILOnly to true and saving it as normal IL library. It no longer crashes on assembly write. Also I noticed that the new assembly is significantly smaller (~14MB -> ~2,5MB).

However, now it crashes when I try to use it. Whenever I try to load an assembly which uses new System.Private.CoreLib it crashes with following message: Failed to initialize CoreCLR, HRESULT: 0x80004005. The result is same when trying both on Windows and on Linux.

When I try to run crossgen on new System.Private.CoreLib it throws this:

Could not load file or assembly '<PATH>\System.Private.CoreLib.dll'. Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))
Error: compilation failed for ".\System.Private.CoreLib.dll" (0x80004005)

I forgot to mention that my original approach (using native write) worked on Windows and I have been actually using it for the past 3 or 4 months. I started to experience issues once I tried to get it working on Linux.

@acizmarik
Copy link
Author

When testing new / instrumented assemblies I am doing it with following settings:
COMPlus_ReadyToRun = 0 - disable R2R
COMPlus_JITMinOpts = 1 - disable JIT optimizations

@0xd4d
Copy link
Collaborator

0xd4d commented Sep 5, 2019

It's the IL Library bit, but there could be more bits. I suggest you compare the bits with a normal DLL and make sure they're identical. Then save it.

The file is smaller because it doesn't contain native code. System.Private.CoreLib.dll is crossgen'd.

@0xd4d
Copy link
Collaborator

0xd4d commented Sep 5, 2019

Also compare other stuff, eg. the PE stuff such as the Machine property (should be eg. I386 or AMD64 etc)

@acizmarik
Copy link
Author

You were right with your first comment. I did not realize that there is actually an ILLibrary flag in Cor20 header. Once the flag is cleared it works.

Just one more questions regarding the fix:

  • Can I break something by "stripping" native code from assemblies? I am just curious if I should expect any problems or whether this is a completely valid operation.

Anyway thank you for your help with this issue. This is truly a great library.

@0xd4d
Copy link
Collaborator

0xd4d commented Sep 7, 2019

I doubt you'll break anything, but you can always re-run crossgen to get the native code back and probably faster startup (make sure you use the correct version).

@acizmarik
Copy link
Author

Ok. Thanks for you help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant