Mono native binary bundle fails to load libc in ne

2019-07-04 04:02发布

问题:

I'm attempting to build a C# Mono application as a native binary so it can be run on Linux systems without any dependencies (Such as Mono).

To ensure some backwards compatibility I am using Ubuntu 12.04 to build the native binary. I had to build Mono 3.x from source as Ubuntu 12.04 only has packages for Mono 2. I documented that process here, if you're interested.

I am using mkbundle to bundle the Mono runtime and its dependencies:

mkbundle -c -o WFTOLauncherNative.c -oo bundles.o --static --deps WFTOLauncher.exe Open.NAT.dll

I am using the cc compiler like so:

cc -o WFTOLauncherNative.exe WFTOLauncherNative.c bundles.o -l:libmono-2.0.a -l:libgdiplus.a -lc -lpthread -lrt -lm -ldl -I /usr/local/include/mono-2.0/

This works on the system I built it on (Ubuntu 12.04). However on Ubuntu 14.04 with no Mono installation I get the following error:

Unhandled Exception:
System.TypeInitializationException: An exception was thrown by the type initializer for System.Windows.Forms.XplatUI ---> System.DllNotFoundException: libc

ldd of the application:

scott@ubuntu:/media/strichnet/WFTOLauncher/bin/Release/LinuxNative$ ldd WFTOLauncherNative.exe
    linux-vdso.so.1 =>  (0x00007fffd0ffe000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa6c794a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fa6c7d27000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa6c772c000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fa6c7523000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa6c721d000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa6c7019000)

My hunch so far is Mono is at fault here - I think it relies on the Mono DllMap configs to map from libc to libc.so.6, but its failing. There is a similar question on SO and the answer here looks promising, but as my goal is to create an independent native assembly its not a solution I can accept.

I have copied the default Mono 3 config file from /etc/mono/config to the binary directory and renamed it to WFTOLauncher.exe.config and WFTOLauncherNative.exe.config (Just in case). This has not helped.

Full Mono debug trace here: https://gist.github.com/strich/e71b23421cdbe941b4f4

回答1:

The root cause of the problem was that Mono was looking for libc.so where the OS only had libc.so.6. Mono needs a DllMap config file to understand how to translate this.

The solution to the problem was to add the default Mono3 DllMap config file to the same directory as my binary. Sadly it appears that Mono doesn't cache the DllMap globally for the process, so I had to make multiple duplicate copies of the config file under the different names of the various modules that were being called. For example:

Mono.Posix.dll.config
System.Drawing.dll.config
System.Windows.Forms.dll.config