Como o Linux carregou este exe compilado com C#?

Como o Linux carregou este exe compilado com C#?

Acabei de descobrir algo realmente surpreendente.

Posso compilar um hello world C# simples em meu computador Windows usando csc(do Visual Studio), copiar o exearquivo resultante para meu computador Linux e executá-lo com mono helloworld.exe. Até agora, tudo faz sentido para mim: de acordo comesta postagem SO, no Windows, helloworld.exeé basicamente apenas um truque que acaba iniciando o tempo de execução do C#, e o bytecode CIL é lido apenas em alguma seção de dados posteriormente no exearquivo. Da mesma forma, imagino que, no Linux, fazer mono helloworld.exeapenas inicia o tempo de execução do C# e lê diretamente o bytecode sem se preocupar com os truques do exe.

Para a posteridade, aqui está a fonte, que obtive deExcelente livro gratuito de C# de Charles Petzold:

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

Mas é aqui que a coisa fica interessante: no Linux ( uname -rna minha máquina dá 4.14.188-1-MANJARO) eu posso simplesmente fazer ./helloworld.exee funciona!

Comecei a fazer algumas investigações e aqui estão as primeiras linhas da execução 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)

Eu esperava algum erro dizendo "este arquivo não é um executável válido", já que só espero que o carregador de programas do Linux entenda arquivos ELF em vez do formato PE do Windows. Em vez disso, parece que de alguma forma o sistema é inteligente o suficiente para começar a procurar por wine (na stracesaída, você pode ver que ele começa a procurar por bibliotecas de wine e, como instalei o wine em minha máquina Linux, ele eventualmente as encontra mais tarde sobre).

Então o que está acontecendo? A execvechamada é inteligente o suficiente para tentar usar o wine se detectar um arquivo PE ou isso é algo que bashestá acontecendo? Ou é algo totalmente diferente?

Responder1

Definitivamente, você tem o Wine ou/ou o Mono instalado por meio de um gerenciador de pacotes e junto com ele um arquivo de configuração especial que informa ao kernel o que fazer quando o usuário iniciar um arquivo exe.

Mais sobre isso aqui:https://en.wikipedia.org/wiki/Binfmt_misc

informação relacionada