2009-07-30 25 views
35

Ich möchte hier sammeln, was passiert, wenn Sie eine ausführbare Datei unter Windows, Linux und OSX ausführen. Insbesondere möchte ich genau die Reihenfolge der Operationen verstehen: Ich vermute, dass das ausführbare Dateiformat (PE, ELF oder Mach-O) vom Kernel geladen wird (aber ich ignoriere die verschiedenen Abschnitte der ELF (Executable und Linkable Format) und ihre Bedeutung), und dann haben Sie den dynamischen Linker, der die Referenzen auflöst, dann wird der __init Teil der ausführbaren Datei ausgeführt, dann die Hauptversion, dann die __fini, und dann ist das Programm abgeschlossen, aber ich bin mir sicher sehr grob und wahrscheinlich falsch.Was passiert, wenn Sie ein Programm ausführen?

Bearbeiten: Die Frage ist jetzt CW. Ich fülle für Linux auf. Wenn jemand das gleiche für Win und OSX machen möchte, wäre es großartig.

+1

Ist es nur ich, oder ist der Umfang dieser Frage viel zu weit? – mezoid

+0

Ich denke nicht, dass es zu breit ist, aber sollte wahrscheinlich Community-Wiki –

+0

Ich würde gerne ein Kopfgeld darauf setzen, wenn ich nicht genug Feedback bekomme. Ich werde es nicht tun können, wenn es CW ist. –

Antwort

0

Nun, abhängig von Ihrer genauen Definition müssen Sie JIT-Compiler für Sprachen wie .Net und Java berücksichtigen. Wenn Sie eine .Net "exe" ausführen, die technisch nicht ausführbar ist, tritt der JIT-Compiler ein und kompiliert sie.

+3

Die .Net-Laufzeit ist eine ausführbare Datei ... Die Tatsache dass es eine komplette virtuelle Umgebung ausführt und Bytecode optimiert ist irrelevant. –

1

Sobald das Bild in den Speicher geladen wird, übernimmt Magie.

+0

Das ist, wenn Sie es auf "Magic" gesetzt haben. "More Magic" bricht das Universum. – jkeys

30

Dies ist natürlich nur auf einem sehr hohen und abstrakten Niveau!

Wie routeNpingme sagt, Register sind in der CPU gesetzt und die Magie passiert!

Update: Ja, ich kann heute nicht richtig speelen!

+0

"Kernel lädt Binär in den Speicher -> Kernel springt auf bestimmte Speicheradresse" "Kernel führt Code von diesem freigegebenen Speicherort aus" Ich bezweifle das. Der Kernel achtet sehr genau darauf, welcher Code ausgeführt werden soll. normalerweise würde es keinen User-Space-Code ausführen. Was Sie gesagt haben, kann von Angreifern leicht ausgenutzt werden. Die Antwort von Stefano macht viel mehr Sinn. – Infinite

21

Ok, beantworte meine eigene Frage. Dies wird progressiv und nur für Linux (und vielleicht Mach-O) durchgeführt. Fühlen Sie sich frei, mehr Sachen zu Ihren persönlichen Antworten hinzuzufügen, so dass sie upvoted werden (und Sie können Abzeichen bekommen, da es jetzt CW ist).

Ich fange auf halber Strecke an und baue den Rest auf, wie ich es herausfinde. Dieses Dokument wurde mit einem x86_64, gcc (GCC) 4.1.2 erstellt.

Öffnen der Datei, Initialisierung

In diesem Abschnitt beschreiben wir, was passiert, wenn das Programm aufgerufen wird, aus dem Kernel Sicht, bis das Programm bereit ist, ausgeführt werden.

  1. Die ELF ist geöffnet.
  2. Der Kernel sucht nach dem Abschnitt .text und lädt ihn in den Speicher. Markiert es als readonly
  3. der Kernel lädt den .data-Abschnitt
  4. der Kernel lädt den Abschnitt .bss und initialisiert den gesamten Inhalt auf Null.
  5. der Kernel überträgt das Steuerelement an den dynamischen Linker (dessen Name in der ELF-Datei im Abschnitt .interp ist). Der dynamische Linker löst alle Aufrufe der gemeinsam genutzten Bibliothek auf.
  6. wird die Steuerung an die Anwendung übertragen

Die Ausführung des Programms

  1. die Funktion _start wird aufgerufen, da der ELF-Header für sie als Einstiegspunkt gibt die ausführbare
  2. _start Anrufe in glibc (durch die PLT), die die folgenden Informationen, um es __libc_start_main

    1. die Anzeige Kleid der tatsächlichen Hauptfunktion
    2. die argc Adresse
    3. die argv Adresse
    4. die Adresse des _init Routine
    5. die Adresse des _fini Routine
    6. einen Funktionszeiger für die atexit() Anmeldung
    7. die höchste Stapeladresse verfügbar
  3. _init wird

    genannt
    1. ruft call_gmon_start auf, um gmon profiling zu initialisieren. nicht wirklich mit der Ausführung verbunden.
    2. Anrufe frame_dummy, die __register_frame_info Wraps (eh_frame Abschnitt Adresse, bss Abschnitt Adresse) (FIXME: Was diese Funktion macht initialisiert globale Variablen aus dem BSS Abschnitt scheinbar)
    3. Anrufe __do_global_ctors_aux, ist deren Rolle all global nennen Konstruktoren, die im Abschnitt .ctors aufgeführt sind.
  4. Haupt wird
  5. Haupt Enden
  6. _fini aufgerufen wird genannt, was wiederum alle Anrufe __do_global_dtors_aux Destruktoren laufen, wie im Abschnitt .dtors angegeben.
  7. das Programm beendet.
+1

Ich weiß nicht, in wie viel Details Sie gehen wollen, aber ich habe Probleme damit, weil ich nicht weiß, was ein ELF ist. (Nun, entweder das oder Linux ist _very_ anders unter der Haube von dem, was ich mir vorgestellt habe) –

+0

Ich werde diesen Teil fortsetzen, sobald ich Zeit habe, die Dokumente weiter zu lesen, die ich fand. ELF ist ein Binärformat für ausführbare Dateien unter Linux. Es ist wie PE in Win und Mach-O in OSX –

3

Unter Windows wird zuerst das Bild in den Speicher geladen. Der Kernel analysiert welche Bibliotheken (lies "DLL") benötigt und lädt sie auch.

Anschließend bearbeitet es das Programmabbild, um die Speicheradressen jeder benötigten Bibliotheksfunktion einzufügen. Diese Adressen haben bereits ein Leerzeichen in der .EXE-Binärdatei, aber sie sind nur mit Nullen gefüllt.

Jede DllMain() - Prozedur der DLL wird dann nacheinander von der am meisten benötigten DLL zur letzten ausgeführt, wie in einer Reihenfolge von Abhängigkeiten.

Sobald alle Bibliotheken geladen wurden und fertig sind, wird das Image schließlich gestartet, und was auch immer jetzt passiert, hängt von der verwendeten Sprache, dem verwendeten Compiler und der Programmroutine ab.

Verwandte Themen