Linux は C# でコンパイルされたこの exe をどのようにロードしたのでしょうか?

Linux は C# でコンパイルされたこの exe をどのようにロードしたのでしょうか?

本当に驚くべきことを発見しました。

私は、Windowsコンピュータで(Visual Studioから)を使用して単純なC# Hello Worldをコンパイルしcsc、結果のexeファイルをLinuxコンピュータにコピーして、で実行することができますmono helloworld.exe。これまでのところ、すべてが私には理にかなっています。このSOの投稿Windows の場合、helloworld.exeこれは基本的に C# ランタイムを起動するだけのトリックであり、CIL バイトコードはファイルの後半のデータ セクションから読み取られるだけです。同様に、Linux の場合、 を実行すると C# ランタイムが起動し、exe トリックを気にすることなくバイトコードが直接読み取られるexeと思います。mono helloworld.exe

後世のために、ここに私が入手した情報源を載せておきます。Charles Petzold の優れた無料の C# 本:

//---------------------------------------------
// FirstProgram.cs (c) 2006 by Charles Petzold
//---------------------------------------------
class FirstProgram
{
    public static void Main()
    {
        System.Console.WriteLine("Hello, Microsoft .NET Framework!");
    }
}

しかし、ここからが面白いところです。Linux (uname -r私のマシンでは4.14.188-1-MANJARO) では、単純に./helloworld.exeこれを実行するだけで動作します。

私は調査を始めましたが、実行中の最初の数行は次のとおりですstrace ./helloworld.exe

execve("./hw.exe", ["./hw.exe"], 0x7fffae8e6070 /* 61 vars */) = 0
[ Process PID=3381 runs in 32 bit mode. ]
brk(NULL)                               = 0x7eedb000
arch_prctl(0x3001 /* ARCH_??? */, 0xffb19948) = -1 EINVAL (Invalid argument)
readlink("/proc/self/exe", "/usr/bin/wine", 4096) = 13
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7faa000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/tls/i686/sse2/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/tls/i686/sse2", 0xffb18e00) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/tls/i686/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/tls/i686", 0xffb18e00) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/tls/sse2/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/tls/sse2", 0xffb18e00) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/tls/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/tls", 0xffb18e00) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/bin/../lib32/i686/sse2/libwine.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/usr/bin/../lib32/i686/sse2", 0xffb18e00) = -1 ENOENT (No such file or directory)

Linux プログラム ローダーが Windows の PE 形式ではなく ELF ファイルのみを理解すると予想していたため、「このファイルは有効な実行ファイルではありません」というエラーが表示されることを予想していました。しかし、どうやらシステムは Wine の検索を開始するほど賢いようです (出力ではstrace、Wine ライブラリの検索が開始されていることがわかります。Linux マシンに Wine をインストールしていたため、最終的には後で見つかります)。

それで何が起こっているのでしょうか?execve呼び出しは、PE ファイルを検出すると wine の使用を試みるのに十分賢いのでしょうか、それともこれは何かbash実行されているのでしょうか? それとも、まったく別の何かなのでしょうか?

答え1

パッケージ マネージャー経由で Wi​​ne または Mono のいずれかがインストールされており、それとともに、ユーザーが exe ファイルを起動したときにカーネルに何を実行するかを指示する特別な構成ファイルもインストールされているはずです。

詳細はこちらをご覧ください:https://en.wikipedia.org/wiki/Binfmt_misc

関連情報