Com'è magico Mono?


149

Sto imparando C #, quindi ho creato un piccolo programma C # che dice Hello, World!, quindi l'ho compilato mono-csced eseguito con mono:

$ mono-csc Hello.cs
$ mono Hello.exe
Hello, World!

Ho notato che quando mi ha colpito TABin bash, Hello.exeè stato caratterizzato eseguibile. In effetti, viene eseguito solo da una shell che carica il nome file!

Hello.exenon è un file ELF con un'estensione divertente:

$ readelf -a Hello.exe
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
$ xxd Hello.exe | head -n1
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............

MZsignifica che è un eseguibile collegato staticamente a Microsoft Windows. Rilascialo su una finestra di Windows e verrà (dovrebbe) eseguito.

Ho wineinstallato, ma wine, essendo un layer di compatibilità per le applicazioni di Windows, richiede circa 5 volte più a lungo a correre Hello.execome monoe l'esecuzione direttamente fare, quindi non è wineche lo gestisce.

Sto assumendo c'è qualche monomodulo del kernel installato con monoche intercetta la execchiamata di sistema / s, o di cattura binari che iniziano con 4D 5A, ma lsmod | grep monoe gli amici restituiscono un errore.

Cosa sta succedendo qui e come fa il kernel a sapere che questo eseguibile è speciale?


Solo per la prova che non è la mia magia di funzionamento della shell, ho usato Crap Shell (aka sh) per eseguirlo e funziona ancora in modo nativo.


Ecco il programma completo, poiché un commentatore era curioso:

using System;

class Hello {
  /// <summary>
  ///   The main entry point for the application
  /// </summary>
  [STAThread]
  public static void Main(string[] args) {
    System.Console.Write("Hello, World!\n");
  }
}

4
Mentre hai la risposta, ma sono un po 'confuso, se esegui i comandi come php hello.phpo python hello.pyo perl hello.plo in caso di linguaggio compilato come java java hello, verrebbero eseguiti anche perché i loro non sono eseguibili lì, ma un programma legge ed esegue il file. Tuttavia, se corri ./hello.exeinvece del mono hello.exeho trovato la tua domanda e accettato la risposta più ragionevole (che nel caso utilizzi definitivamente il supporto
binfmt

@ kuldeep.kamboj Non sono sicuro di aver capito cosa stai dicendo, ma sono rimasto sorpreso dal fatto che un eseguibile di Windows funzioni "nativamente" su un box Linux.
gatto

1
In realtà quello che stavo dicendo che qualsiasi file di codice (o file compilato) può essere eseguito tramite il suo programma in formato program codefile, nel tuo caso il programma è mono, mentre i miei esempi includono php, python, perl e java. Sospetto che mono consenti l'estensione a un file diverso da .exe ancora eseguito tramite codice. Non dovrebbe dipendere affatto da Windows poiché alla fine si esegue un codice compilato. Tuttavia, se il tuo file sorgente ha un codice dipendente come solo API di Windows, ovviamente devi avere bisogno di vino per eseguire quel file exe.
kuldeep.kamboj,

4
Parte della meravigliosa ironia di questo è che /etc/magico /usr/share/file/magic(o simile posizione magica) è il file che contiene le informazioni necessarie per poterlo fare.

1
@cat è un file molto interessante (se avessi un file preferito, probabilmente sarebbe la mia prima scelta). Ha le informazioni per identificare tutti i tipi di file. Ma è necessario identificare quale sia il file prima di poter capire come eseguirlo. Questo è ciò che fa il file e la sua magia. Una cosa simile: il supporto del kernel binario Java per Linux da un po 'di tempo in modo da poter fare $ foo.jarpiuttosto che $ java -jar foo.jar- simile a ciò che viene fatto per mono.

Risposte:


183

Questo è binfmt_misc in azione: consente al kernel di sapere come eseguire binari di cui non è a conoscenza. Guarda il contenuto di /proc/sys/fs/binfmt_misc; tra i file che vedi lì, uno dovrebbe spiegare come eseguire i binari Mono:

enabled
interpreter /usr/lib/binfmt-support/run-detectors
flags:
offset 0
magic 4d5a

(su un sistema Debian). Questo dice al kernel che dovrebbero essere dati i binari che iniziano con MZ( 4d5a) run-detectors. Quest'ultimo capisce se usare Mono o Wine per eseguire il binario.

I tipi binari possono essere aggiunti, rimossi, abilitati e disabilitati in qualsiasi momento; vedere la documentazione sopra per i dettagli (la semantica è sorprendente, il filesystem virtuale usato qui non si comporta del tutto come un filesystem standard). /proc/sys/fs/binfmt_misc/statusfornisce lo stato globale e ogni "descrittore" binario mostra il suo stato individuale. Un altro modo di disabilitare binfmt_miscè scaricare il suo modulo del kernel, se è costruito come un modulo; questo significa anche che è possibile inserirlo nella blacklist per evitarlo del tutto.

Questa funzione consente di supportare nuovi tipi binari, come eseguibili MZ (che includono binari Windows PE e PE +, ma anche binari DOS e OS / 2!), File JAR Java ... Permette anche di supportare tipi binari noti su nuove architetture, in genere usando Qemu; quindi, con le librerie appropriate, puoi eseguire in modo trasparente i binari ARM Linux su un processore Intel!

La tua domanda è nata dalla compilazione incrociata, anche se nel senso di .NET, e questo fa apparire un avvertimento con binfmt_misc: alcuni script di configurazione si comportano in modo errato quando si tenta di eseguire la compilazione incrociata su un sistema che può eseguire i binari compilati in modo incrociato. In genere, rilevare la compilazione incrociata implica la creazione di un file binario e il tentativo di eseguirlo; se funziona, non stai eseguendo la compilazione incrociata, in caso contrario, sei (o il tuo compilatore non funziona). autoconfgli script di solito possono essere corretti in questo caso specificando esplicitamente le architetture di build e host, ma a volte dovrai disabilitare binfmt_misctemporaneamente ...


2
Per coloro che sono curiosi di / proc, potresti essere interessato a Come funziona / proc / *? su Super User .
un CVn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.