9 Stimmen

Wie der Lader die DLL dem Prozessadressraum zuordnet

Ich bin neugierig zu wissen, wie der Loader DLL in den Prozessadressraum zuordnet. Wie der Lader diese Magie macht. Ein Beispiel ist sehr willkommen.

Vielen Dank im Voraus.

9voto

0xC0000022L Punkte 19207

Okay, ich gehe hier von der Windows-Seite der Dinge aus. Was passiert, wenn Sie eine PE-Datei laden, ist, dass der Lader (in NTDLL enthalten) Folgendes tut:

  1. Suchen Sie jede der DLLs mit Hilfe der DLL-Such-Semantik (System- und Patch-Level-spezifisch), bekannte DLLs sind hiervon ausgenommen
  2. Abbildung der Datei im Speicher (MMF), wobei die Seiten beim Schreiben kopiert werden (CoW)
  3. Durchlaufen Sie das Importverzeichnis und beginnen Sie für jeden Import (rekursiv) bei Punkt 1.
  4. Auflösen von Verschiebungen, was in den meisten Fällen nur eine sehr begrenzte Anzahl von Entitäten ist, da der Code selbst positionsunabhängiger Code (PIC) ist
  5. (IIRC) die EAT von RVA (relative virtuelle Adresse) auf VA (virtuelle Adresse im aktuellen Prozessspeicher) zu patchen
  6. Änderung der IAT (Importadresstabelle), um die Importe mit ihrer tatsächlichen Adresse innerhalb des Prozessspeicherraums zu referenzieren
  7. Für einen DLL-Aufruf DLLMain() für eine EXE einen Thread erstellen, dessen Startadresse am Einstiegspunkt der PE-Datei liegt (auch dies ist stark vereinfacht, da die tatsächliche Startadresse bei Win32-Prozessen in kernel32.dll liegt)

Beim Kompilieren von Code hängt es nun vom Linker ab, wie die externe Funktion referenziert wird. Einige Linker erstellen Stubs, so dass - theoretisch - der Versuch, die Funktionsadresse gegen NULL zu prüfen, immer ergibt, dass sie nicht NULL ist. Das ist eine Eigenart, die Sie beachten müssen, wenn Ihr Linker davon betroffen ist. Andere verweisen direkt auf den IAT-Eintrag. In diesem Fall kann die Adresse einer nicht referenzierten Funktion (man denke an verzögert geladene DLLs) NULL sein, und der SEH-Handler ruft dann den Delay-Load-Helper auf und versucht, die Funktionsadresse aufzulösen, bevor er die Ausführung an der Stelle fortsetzt, an der sie fehlgeschlagen ist.

Der oben beschriebene Prozess ist mit einer Menge Bürokratie verbunden, die ich zu stark vereinfacht habe.

Das Wesentliche für das, was Sie wissen wollten, ist, dass das Mapping in den Prozess als MMF geschieht Allerdings kann man das Verhalten mit Heap Space künstlich nachahmen. Wenn Sie sich jedoch an den Punkt über CoW erinnern, ist das der Kernpunkt der Idee von DLLs. Eigentlich ist die dieselbe Kopie der (meisten) Seiten der DLL wird von den Prozessen, die eine bestimmte DLL laden, gemeinsam genutzt. Die Seiten, die nicht gemeinsam genutzt werden, sind diejenigen, auf die wir geschrieben haben, zum Beispiel bei der Auflösung von Relocations und ähnlichen Dingen. In diesem Fall hat jeder Prozess eine - nun modifizierte - Kopie der ursprünglichen Seite.

Und ein Wort der Warnung bezüglich EXE-Packern auf DLL. Sie umgehen genau den von mir beschriebenen CoW-Mechanismus, indem sie dem entpackten Inhalt der DLL Speicherplatz auf dem Heap des Prozesses zuweisen, in den die DLL geladen wird. Während also der eigentliche Dateiinhalt immer noch als MMF gemappt und gemeinsam genutzt wird, belegt der entpackte Inhalt für jeden Prozess, der die DLL lädt, die gleiche Menge an Speicher, anstatt diesen gemeinsam zu nutzen.

8voto

Mark Bessey Punkte 19301

Welchen Detaillierungsgrad wünschen Sie sich? Grundsätzlich funktionieren alle dynamischen Linker auf ziemlich gleiche Weise:

  1. Dynamische Bibliotheken werden zu lokalisierbarem Code kompiliert (z. B. mit relativen statt absoluten Sprüngen).
  2. Der Linker findet einen leeren Platz in der Speicherkarte der Anwendung in angemessener Größe und liest den Code der DLL und alle statischen Daten in diesen Platz.
  3. Die dynamische Bibliothek enthält eine Tabelle mit Offsets für den Beginn jeder exportierten Funktion, und Aufrufe der DLL-Funktionen im Client-Programm werden beim Laden mit einer neuen Zieladresse versehen, die darauf basiert, wo die Bibliothek geladen wurde.
  4. Die meisten dynamischen Linker-Systeme verfügen über ein System zur Einstellung einer bevorzugten Basisadresse für eine bestimmte Bibliothek. Wenn eine Bibliothek an ihrer bevorzugten Adresse geladen wird, kann die Verschiebung in den Schritten 2 und 3 übersprungen werden.

3voto

activout.se Punkte 5614

Wenn Sie wirklich interessiert sind, sollten Sie das Buch lesen Linker und Lader .

2voto

unwind Punkte 377331

Wenn Sie davon ausgehen, dass dies unter Windows geschieht (die DLL deutet darauf hin), sollten Sie Microsofts Dynamisches Linking während der Laufzeit Dokumentationsseite. Sie gibt nicht im Detail an wie die DLL wird in den Adressraum eingeblendet; ich nehme an, dass Sie das nicht wissen müssen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X